2014-09-03 07:35:50 +00:00
|
|
|
;; -*- lexical-binding: t; -*-
|
2014-08-14 00:02:49 +00:00
|
|
|
;; Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
;; Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
;;
|
|
|
|
;; Author: Soonho Kong
|
|
|
|
;;
|
|
|
|
(require 'cl-lib)
|
2014-09-04 23:31:20 +00:00
|
|
|
(require 'dash)
|
2014-09-10 19:45:19 +00:00
|
|
|
(require 'dash-functional)
|
2014-09-12 16:20:31 +00:00
|
|
|
(require 's)
|
|
|
|
(require 'lean-debug)
|
2014-08-14 00:02:49 +00:00
|
|
|
(require 'lean-variable)
|
|
|
|
(require 'lean-cmd)
|
|
|
|
(require 'lean-info)
|
|
|
|
(require 'lean-util)
|
|
|
|
|
|
|
|
;; Parameters
|
|
|
|
;; ==========
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-process-name (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard "lean-server-standard")
|
|
|
|
(`hott "lean-server-hott"))))
|
|
|
|
(defun lean-server-buffer-name (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard "*lean-server-standard*")
|
|
|
|
(`hott "*lean-server-hott*"))))
|
|
|
|
(defun lean-server-trace-buffer-name (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard "*lean-server-standard-trace*")
|
|
|
|
(`hott "*lean-server-hott-trace*" ))))
|
|
|
|
(defun lean-server-option-list (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard '("--lean" "--server"))
|
|
|
|
(`hott '("--hlean" "--server")))))
|
|
|
|
(defun lean-server-process (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard lean-global-server-standard-process)
|
|
|
|
(`hott lean-global-server-hott-process))))
|
|
|
|
(defun lean-server-buffer (&optional type)
|
|
|
|
(let ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard lean-global-server-standard-buffer)
|
|
|
|
(`hott lean-global-server-hott-buffer))))
|
|
|
|
(defun lean-server-set-buffer (str &optional type)
|
|
|
|
"Set server-buffer"
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard (setq lean-global-server-standard-buffer str))
|
|
|
|
(`hott (setq lean-global-server-hott-buffer str)))))
|
|
|
|
(defun lean-server-set-process (p &optional type)
|
|
|
|
"Set server-process"
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(pcase type
|
|
|
|
(`standard (setq lean-global-server-standard-process p))
|
|
|
|
(`hott (setq lean-global-server-hott-process p)))))
|
|
|
|
|
2014-09-12 16:20:31 +00:00
|
|
|
|
|
|
|
;; Log & Trace
|
|
|
|
;; ===========
|
2014-08-25 18:40:37 +00:00
|
|
|
(defun lean-server-log (format-string &rest args)
|
|
|
|
"Display a message at the bottom of the *lean-server* buffer."
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-output-to-buffer (lean-server-get-buffer)
|
|
|
|
(concat format-string)
|
|
|
|
args)
|
|
|
|
(apply 'lean-debug (cons format-string args)))
|
|
|
|
|
2014-08-30 14:35:00 +00:00
|
|
|
|
|
|
|
(defun lean-server-trace (format-string &rest args)
|
|
|
|
"Display a message at the bottom of the *lean-server* buffer."
|
2014-10-01 21:37:34 +00:00
|
|
|
(when lean-debug-mode
|
2014-08-30 14:51:53 +00:00
|
|
|
(when lean-global-server-last-time-sent
|
|
|
|
(let ((time-diff (- (float-time) lean-global-server-last-time-sent)))
|
2015-02-25 19:21:23 +00:00
|
|
|
(lean-output-to-buffer (lean-server-trace-buffer-name)
|
|
|
|
"SLEEP %i\n"
|
2014-09-05 22:22:34 +00:00
|
|
|
`(,(truncate (* 1000 time-diff))))))
|
2014-08-30 14:51:53 +00:00
|
|
|
(setq lean-global-server-last-time-sent (float-time))
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-output-to-buffer (lean-server-trace-buffer-name)
|
|
|
|
format-string
|
|
|
|
args)))
|
2014-08-25 18:40:37 +00:00
|
|
|
|
2014-08-14 00:02:49 +00:00
|
|
|
;; How to read data from an async process
|
|
|
|
;; ======================================
|
2014-08-25 18:40:37 +00:00
|
|
|
(defconst lean-server-syntax-pattern
|
2014-09-04 22:30:23 +00:00
|
|
|
`((INFO ,(rx line-start "-- BEGININFO" (* not-newline) line-end)
|
|
|
|
,(rx line-start (group "-- ENDINFO") line-end))
|
|
|
|
(SET ,(rx line-start "-- BEGINSET" line-end)
|
|
|
|
,(rx line-start (group "-- ENDSET") line-end))
|
|
|
|
(EVAL ,(rx line-start "-- BEGINEVAL" line-end)
|
|
|
|
,(rx line-start (group "-- ENDEVAL") line-end))
|
2014-09-01 00:46:40 +00:00
|
|
|
(OPTIONS ,(rx line-start "-- BEGINOPTIONS" line-end)
|
2014-09-04 22:30:23 +00:00
|
|
|
,(rx line-start (group "-- ENDOPTIONS") line-end))
|
|
|
|
(SHOW ,(rx line-start "-- BEGINSHOW" line-end)
|
|
|
|
,(rx line-start (group "-- ENDSHOW") line-end))
|
|
|
|
(FINDP ,(rx line-start "-- BEGINFINDP" (* not-newline) line-end)
|
|
|
|
,(rx line-start (group "-- ENDFINDP") line-end))
|
2014-09-08 20:14:15 +00:00
|
|
|
(FINDG ,(rx line-start "-- BEGINFINDG" (* not-newline) line-end)
|
|
|
|
,(rx line-start (group "-- ENDFINDG") line-end))
|
2014-09-10 19:46:08 +00:00
|
|
|
(WAIT ,(rx line-start "-- BEGINWAIT" line-end)
|
2014-09-08 23:01:58 +00:00
|
|
|
,(rx line-start (group "-- ENDWAIT") line-end))
|
2014-09-04 22:30:23 +00:00
|
|
|
(ERROR ,(rx line-start "-- " (0+ not-newline) line-end)
|
|
|
|
,(rx line-start (group "-- ERROR" (0+ not-newline)) line-end)))
|
2014-08-25 18:40:37 +00:00
|
|
|
"Regular expression pattern for lean-server message syntax")
|
|
|
|
|
|
|
|
(defun lean-server-split-buffer (buf-str beg-regex end-regex)
|
|
|
|
""
|
|
|
|
(let ((beg (string-match beg-regex buf-str))
|
|
|
|
(end (string-match end-regex buf-str))
|
|
|
|
pre body post)
|
|
|
|
(when (and beg end)
|
|
|
|
(setq end (match-end 1))
|
|
|
|
(setq pre (substring-no-properties buf-str 0 beg))
|
|
|
|
(setq body (substring-no-properties buf-str beg end))
|
|
|
|
(setq post (substring-no-properties buf-str end))
|
|
|
|
`(,pre ,body ,post))))
|
|
|
|
|
|
|
|
(defun lean-server-check-buffer-and-partition (buf-str)
|
|
|
|
"Return the status of buffer."
|
2014-09-10 19:46:08 +00:00
|
|
|
(when buf-str
|
|
|
|
(let (matches partition-result)
|
|
|
|
(setq matches
|
|
|
|
(cl-loop for (type beg-regex end-regex) in lean-server-syntax-pattern
|
|
|
|
do (setq partition-result (lean-server-split-buffer buf-str beg-regex end-regex))
|
|
|
|
if partition-result
|
|
|
|
collect `(,type ,partition-result)))
|
|
|
|
(when matches
|
|
|
|
(-min-by (-on '< (lambda (type-partition-result) (length (car (cdr type-partition-result)))))
|
|
|
|
matches)))))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
|
|
|
(defun lean-server-process-received-message (buf str)
|
|
|
|
"Process received message from lean-server"
|
2014-09-05 22:22:34 +00:00
|
|
|
(lean-server-log "%s:\n%s\n"
|
|
|
|
(propertize "Received Message" 'face 'font-lock-variable-name-face)
|
|
|
|
str)
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-set-buffer (concat (lean-server-buffer) str)))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
|
|
|
(defun lean-server-output-filter (process string)
|
|
|
|
"Filter function attached to lean-server process"
|
|
|
|
(lean-server-process-received-message (process-buffer process) string))
|
|
|
|
|
2014-08-26 23:21:48 +00:00
|
|
|
(defun lean-server-handle-signal (process event)
|
|
|
|
"Handle signals for lean-server-process"
|
2014-09-10 16:06:33 +00:00
|
|
|
(let ((event-string (s-trim event)))
|
|
|
|
(lean-server-initialize-global-vars)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-handle-signal: %s"
|
2014-09-11 11:04:20 +00:00
|
|
|
(propertize event-string 'face '(:foreground "red")))
|
|
|
|
(lean-server-trace "lean-server-handle-signal: %s\n"
|
2014-09-10 16:06:33 +00:00
|
|
|
(propertize event-string 'face '(:foreground "red")))))
|
2014-08-26 23:21:48 +00:00
|
|
|
|
2014-08-14 00:02:49 +00:00
|
|
|
;; How to create an async process
|
|
|
|
;; ==============================
|
2014-09-05 22:22:59 +00:00
|
|
|
|
|
|
|
(defun lean-server-cancel-retry-timer ()
|
|
|
|
(when (timerp lean-global-retry-timer)
|
|
|
|
(cancel-timer lean-global-retry-timer))
|
|
|
|
(setq lean-global-retry-timer nil))
|
|
|
|
|
2014-08-26 23:21:48 +00:00
|
|
|
(defun lean-server-initialize-global-vars ()
|
|
|
|
"Initialize lean-server related global variables"
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-set-buffer nil)
|
2014-08-26 23:21:48 +00:00
|
|
|
(setq lean-global-server-current-file-name nil)
|
2014-08-27 07:48:55 +00:00
|
|
|
(setq lean-global-server-message-to-process nil)
|
2014-08-30 14:51:53 +00:00
|
|
|
(setq lean-global-server-last-time-sent nil)
|
2014-09-04 23:31:20 +00:00
|
|
|
(setq lean-global-async-task-queue nil)
|
2014-09-06 06:04:22 +00:00
|
|
|
(setq lean-global-nay-retry-counter 0)
|
2014-09-15 16:46:06 +00:00
|
|
|
(setq lean-global-option-alist nil)
|
2014-09-05 22:22:59 +00:00
|
|
|
(lean-server-cancel-retry-timer))
|
2014-08-26 23:21:48 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-create-process (&optional type)
|
|
|
|
"Create lean-server process. type can be either 'standard or 'hott"
|
|
|
|
;; (message "lean-server-create-process")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension)))
|
|
|
|
(process-connection-type nil)
|
|
|
|
(p (apply 'start-process
|
|
|
|
(append (list (lean-server-process-name type)
|
|
|
|
(lean-server-buffer-name type)
|
|
|
|
(lean-get-executable lean-executable-name))
|
|
|
|
(lean-server-option-list type)
|
|
|
|
lean-server-options))))
|
|
|
|
(set-process-coding-system p 'utf-8 'utf-8)
|
|
|
|
(set-process-filter p 'lean-server-output-filter)
|
|
|
|
(set-process-sentinel p 'lean-server-handle-signal)
|
|
|
|
(set-process-query-on-exit-flag p nil)
|
2014-08-26 23:21:48 +00:00
|
|
|
(lean-server-initialize-global-vars)
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-set-process p type)
|
|
|
|
(lean-debug "lean-server process [%S] %S is created" type p)
|
|
|
|
p))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-kill-process (&optional type)
|
2014-08-25 18:40:37 +00:00
|
|
|
"Kill lean-server process. Return t if killed, nil if nothing to kill"
|
2014-08-14 15:56:07 +00:00
|
|
|
(interactive)
|
2015-02-12 21:56:26 +00:00
|
|
|
;; (message "lean-server-kill-process")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(lean-server-initialize-global-vars)
|
|
|
|
(cond
|
|
|
|
((and (lean-server-process type)
|
|
|
|
(not (= 0 (process-exit-status (lean-server-process type)))))
|
|
|
|
(setq lean-global-server-process nil) t)
|
|
|
|
((lean-server-process type)
|
|
|
|
(when (interactive-p)
|
|
|
|
(message "lean-server-kill-process: %S killed" (lean-server-process type)))
|
|
|
|
(kill-process (lean-server-process type))
|
|
|
|
(setq lean-global-server-process nil) t)
|
|
|
|
(t
|
|
|
|
(when (interactive-p)
|
|
|
|
(message "lean-server-kill-process: no process to kill")) nil))))
|
2014-08-14 15:56:07 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-restart-process (&optional type)
|
2014-08-14 15:56:07 +00:00
|
|
|
"Restart lean-server process."
|
|
|
|
(interactive)
|
2015-02-12 21:56:26 +00:00
|
|
|
;; (message "lean-server-restart-process")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(and (lean-server-kill-process type)
|
|
|
|
(lean-server-create-process type))))
|
|
|
|
|
|
|
|
(defun lean-server-restart-all-processes ()
|
|
|
|
"Restart All lean-server processes"
|
|
|
|
;; (message "lean-server-restart-all-processes")
|
2015-02-12 22:20:21 +00:00
|
|
|
(interactive)
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-kill-process 'hott)
|
|
|
|
(lean-server-kill-process 'standard))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-process-exist-p (&optional type)
|
2014-09-12 21:22:39 +00:00
|
|
|
"Return t if lean-server-process exists, otherwise return nil"
|
2015-02-12 21:56:26 +00:00
|
|
|
;; (message "lean-server-process-exist-p")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(if (lean-server-process type) t nil)))
|
2014-09-12 21:22:39 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-get-process (&optional type)
|
2014-08-14 15:56:07 +00:00
|
|
|
"Get lean-server process. If needed, create a one."
|
2015-02-12 21:56:26 +00:00
|
|
|
;; (message "lean-server-get-process")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(cond ((not (lean-server-process))
|
|
|
|
(lean-server-create-process))
|
|
|
|
((not (process-live-p (lean-server-process)))
|
|
|
|
(when (interactive-p)
|
|
|
|
(message "lean-server-get-process: %S is not live, kill it"
|
|
|
|
(lean-server-process)))
|
|
|
|
(lean-server-restart-process))
|
|
|
|
(t (lean-server-process type)))))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2015-02-12 21:56:26 +00:00
|
|
|
(defun lean-server-get-buffer (&optional type)
|
2014-08-14 15:56:07 +00:00
|
|
|
"Get lean-server buffer."
|
2015-02-12 21:56:26 +00:00
|
|
|
;; (message "lean-server-get-buffer")
|
|
|
|
(let* ((type (or type (lean-choose-minor-mode-based-on-extension))))
|
|
|
|
(process-buffer (lean-server-get-process))))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
|
|
|
;; How to send data to an async process
|
|
|
|
;; ====================================
|
2014-09-12 16:38:09 +00:00
|
|
|
(defun lean-server-flush-changed-lines ()
|
2014-08-14 00:02:49 +00:00
|
|
|
"Flush lean-changed-lines.
|
|
|
|
|
|
|
|
Send REPLACE commands to lean-server, reset lean-changed-lines to nil."
|
|
|
|
(cl-loop for n in lean-changed-lines
|
2014-09-04 23:31:20 +00:00
|
|
|
do (lean-server-send-cmd-async (lean-cmd-replace n (lean-grab-line n)))
|
2014-08-14 00:02:49 +00:00
|
|
|
finally (setq lean-changed-lines nil)))
|
|
|
|
|
2014-08-25 23:27:33 +00:00
|
|
|
(defun lean-server-check-current-file (&optional file-name)
|
2014-09-10 19:45:19 +00:00
|
|
|
"Check lean-global-server-current-file-name
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2014-08-25 23:27:33 +00:00
|
|
|
If it's not the same with file-name (default: buffer-file-name), send VISIT cmd."
|
|
|
|
(let ((current-file-name (or file-name (buffer-file-name))))
|
2014-08-14 00:02:49 +00:00
|
|
|
(unless (string= lean-global-server-current-file-name
|
|
|
|
current-file-name)
|
2014-10-03 17:09:19 +00:00
|
|
|
(lean-server-send-cmd-async (lean-cmd-visit)))))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
|
|
|
(defun lean-server-before-send-cmd (cmd)
|
2014-08-14 15:56:07 +00:00
|
|
|
"Operations to perform before sending a command."
|
2014-08-14 00:02:49 +00:00
|
|
|
(cl-case (lean-cmd-type cmd)
|
2014-08-25 18:40:37 +00:00
|
|
|
('LOAD (setq lean-global-server-current-file-name
|
|
|
|
(lean-cmd-load-get-file-name cmd)))
|
|
|
|
('VISIT (setq lean-global-server-current-file-name
|
|
|
|
(lean-cmd-visit-get-file-name cmd)))
|
2014-08-14 00:02:49 +00:00
|
|
|
('REPLACE (lean-server-check-current-file))
|
|
|
|
('INSERT (lean-server-check-current-file))
|
|
|
|
('REMOVE (lean-server-check-current-file))
|
2014-09-12 16:38:09 +00:00
|
|
|
('INFO (lean-server-flush-changed-lines))
|
2014-09-01 00:46:40 +00:00
|
|
|
('CHECK ())
|
2014-08-25 18:40:37 +00:00
|
|
|
('SET ())
|
2014-09-01 00:46:40 +00:00
|
|
|
('EVAL (lean-server-check-current-file))
|
2014-09-03 07:45:16 +00:00
|
|
|
('OPTIONS ())
|
2014-09-04 22:30:23 +00:00
|
|
|
('SHOW (lean-server-check-current-file))
|
|
|
|
('VALID (lean-server-check-current-file))
|
2014-09-12 16:38:09 +00:00
|
|
|
('FINDP (lean-server-flush-changed-lines)
|
2014-09-08 23:03:44 +00:00
|
|
|
(lean-server-check-current-file))
|
2014-09-12 16:38:09 +00:00
|
|
|
('FINDG (lean-server-flush-changed-lines)
|
2014-09-08 23:03:44 +00:00
|
|
|
(lean-server-check-current-file))
|
2014-10-03 00:29:01 +00:00
|
|
|
('WAIT (lean-server-check-current-file))
|
|
|
|
('SYNC )))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2014-10-03 16:44:38 +00:00
|
|
|
(defun lean-server-delete-cache-file ()
|
|
|
|
"Delete the .clean file for the current buffer (if any)"
|
|
|
|
(let* ((file-name (buffer-file-name))
|
|
|
|
(ext (and file-name (f-ext file-name)))
|
|
|
|
cache-file-name
|
|
|
|
)
|
|
|
|
(when (string= ext "lean")
|
|
|
|
(setq cache-file-name
|
|
|
|
(concat (f-no-ext file-name)
|
|
|
|
".clean"))
|
|
|
|
(when (f-file? cache-file-name)
|
|
|
|
(lean-debug "Delete cache file %s" cache-file-name)
|
|
|
|
(ignore-errors
|
|
|
|
(delete-file cache-file-name))))))
|
|
|
|
|
2014-08-14 00:02:49 +00:00
|
|
|
(defun lean-server-after-send-cmd (cmd)
|
2014-08-14 15:56:07 +00:00
|
|
|
"Operations to perform after sending a command."
|
2014-08-14 00:02:49 +00:00
|
|
|
(cl-case (lean-cmd-type cmd)
|
2014-10-03 17:09:19 +00:00
|
|
|
('LOAD (lean-server-delete-cache-file)
|
|
|
|
(lean-server-handle-modified-buffer))
|
|
|
|
('VISIT (lean-server-delete-cache-file)
|
|
|
|
(lean-server-handle-modified-buffer))
|
2014-08-14 00:02:49 +00:00
|
|
|
('REPLACE ())
|
|
|
|
('INSERT ())
|
|
|
|
('REMOVE ())
|
|
|
|
('INFO ())
|
2014-08-25 18:40:37 +00:00
|
|
|
('CHECK ())
|
|
|
|
('SET ())
|
2014-09-01 00:46:40 +00:00
|
|
|
('EVAL ())
|
2014-09-03 07:45:16 +00:00
|
|
|
('OPTIONS ())
|
|
|
|
('SHOW ())
|
2014-09-04 22:30:23 +00:00
|
|
|
('VALID ())
|
2014-09-08 20:14:15 +00:00
|
|
|
('FINDP ())
|
2014-09-08 23:03:44 +00:00
|
|
|
('FINDG ())
|
2014-10-03 00:29:01 +00:00
|
|
|
('SYNC ())))
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2014-09-04 23:31:20 +00:00
|
|
|
(defun lean-server-send-cmd (cmd)
|
|
|
|
"Send cmd to lean-server"
|
2014-08-14 00:02:49 +00:00
|
|
|
(let ((proc (lean-server-get-process))
|
|
|
|
(string-to-send (concat (lean-cmd-to-string cmd) "\n")))
|
|
|
|
(lean-server-before-send-cmd cmd)
|
|
|
|
;; Logging
|
2014-09-05 22:22:34 +00:00
|
|
|
(lean-server-log "%s:\n%s"
|
|
|
|
(propertize "Sent Message" 'face 'font-lock-variable-name-face)
|
|
|
|
string-to-send)
|
2014-08-30 14:35:00 +00:00
|
|
|
;; Trace
|
|
|
|
(lean-server-trace
|
|
|
|
(format "%s" string-to-send))
|
|
|
|
(process-send-string proc string-to-send)
|
2014-09-04 23:31:20 +00:00
|
|
|
(lean-server-after-send-cmd cmd)))
|
|
|
|
|
2014-09-11 11:09:21 +00:00
|
|
|
(defun lean-server-process-message-with-cont (body type cont cmd-type)
|
2014-09-04 23:31:20 +00:00
|
|
|
"Process the message from lean-server and call continuation"
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "process-message-with-cont: type = %S, cmd-type = %S"
|
2014-09-11 11:09:21 +00:00
|
|
|
type cmd-type)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "process-message-with-cont: body\n-----\n%s\n-----\n" body)
|
2014-09-04 23:31:20 +00:00
|
|
|
(cl-case type
|
|
|
|
(INFO
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: INFO")
|
2014-09-04 23:31:20 +00:00
|
|
|
(let ((info-record (lean-server-get-info-record-at-pos body)))
|
|
|
|
(funcall cont info-record)))
|
|
|
|
(SET
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: SET")
|
2014-09-04 23:31:20 +00:00
|
|
|
;; Call cont with string
|
|
|
|
(funcall cont (lean-set-parse-string body)))
|
|
|
|
(EVAL
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: EVAL")
|
2014-09-04 23:31:20 +00:00
|
|
|
;; Call cont with string
|
|
|
|
(funcall cont (lean-eval-parse-string body)))
|
|
|
|
(OPTIONS
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: OPTIONS")
|
2014-09-04 23:31:20 +00:00
|
|
|
;; Call cont with alist of lean-option-records
|
|
|
|
(funcall cont (lean-options-parse-string body)))
|
|
|
|
(SHOW
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: SHOW")
|
2014-09-04 23:31:20 +00:00
|
|
|
;; Call cont with string
|
|
|
|
(funcall cont (lean-show-parse-string body)))
|
|
|
|
(FINDP
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: FINDP")
|
2014-09-04 23:31:20 +00:00
|
|
|
;; Call cont with (name * type) list
|
|
|
|
(funcall cont (lean-findp-parse-string body)))
|
2014-09-08 20:14:15 +00:00
|
|
|
(FINDG
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: FINDG")
|
2014-09-08 20:14:15 +00:00
|
|
|
;; Call cont with (name * type) list
|
|
|
|
(funcall cont (lean-findg-parse-string body)))
|
2014-09-10 19:45:19 +00:00
|
|
|
(WAIT
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "Process: WAIT")
|
2014-09-10 19:45:19 +00:00
|
|
|
;; Call cont
|
|
|
|
(funcall cont))
|
2014-09-04 23:31:20 +00:00
|
|
|
(ERROR
|
|
|
|
(lean-server-log "Error detected:\n%s" body))))
|
|
|
|
|
2014-09-11 11:07:50 +00:00
|
|
|
(defun lean-server-check-and-process-buffer-with-cont (cont cmd-type)
|
2014-09-04 23:31:20 +00:00
|
|
|
"Check server-buffer and process the message with a continuation if it's ready."
|
|
|
|
(let ((partition-result (lean-server-check-buffer-and-partition
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-buffer)))
|
2014-09-04 23:31:20 +00:00
|
|
|
result)
|
2014-09-11 11:07:50 +00:00
|
|
|
(condition-case err
|
|
|
|
(pcase partition-result
|
|
|
|
(`(,type (,pre ,body ,post))
|
|
|
|
(lean-server-log "The following pre-message will be thrown away:")
|
|
|
|
(lean-server-log "%s" pre)
|
2015-02-12 21:56:26 +00:00
|
|
|
(lean-server-set-buffer post)
|
2014-09-11 11:07:50 +00:00
|
|
|
(setq result (lean-server-process-message-with-cont body type cont cmd-type))
|
|
|
|
`(PROCESSED ,result))
|
|
|
|
(`nil '(NOTREADY)))
|
|
|
|
(error `(ERROR ,err))
|
|
|
|
(quit `(QUIT ,err)))))
|
2014-09-04 23:31:20 +00:00
|
|
|
|
2014-09-06 06:04:22 +00:00
|
|
|
(defun lean-server-async-task-queue-len ()
|
|
|
|
(length lean-global-async-task-queue))
|
|
|
|
|
2014-09-11 11:09:21 +00:00
|
|
|
(defun lean-server-async-task-queue-push-back (cont cmd-type)
|
|
|
|
(setq lean-global-async-task-queue (-snoc lean-global-async-task-queue
|
|
|
|
`(,cont . ,cmd-type))))
|
2014-09-06 06:04:22 +00:00
|
|
|
|
|
|
|
(defun lean-server-async-task-queue-peek-front ()
|
|
|
|
(car lean-global-async-task-queue))
|
|
|
|
|
|
|
|
(defun lean-server-async-task-queue-pop-front ()
|
|
|
|
(!cdr lean-global-async-task-queue))
|
|
|
|
|
2014-09-04 23:31:20 +00:00
|
|
|
(defun lean-server-send-cmd-async (cmd &optional cont)
|
|
|
|
"Send cmd to lean-server and attach continuation to the queue."
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "send-cmd-async: %S %S" (lean-cmd-type cmd) (cl-second cmd))
|
|
|
|
(lean-debug "send-cmd-async: queue len = %d" (lean-server-async-task-queue-len))
|
2014-09-04 23:31:20 +00:00
|
|
|
(lean-server-send-cmd cmd)
|
|
|
|
(when cont
|
2014-09-11 11:09:21 +00:00
|
|
|
(lean-server-async-task-queue-push-back cont (lean-cmd-type cmd))
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "send-cmd-async: added to %s the queue, queue size = %d"
|
2014-09-10 19:45:19 +00:00
|
|
|
(lean-cmd-type cmd)
|
2014-09-06 06:04:22 +00:00
|
|
|
(lean-server-async-task-queue-len))
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "send-cmd-async: call handler")
|
2014-09-05 22:22:59 +00:00
|
|
|
(lean-server-set-timer-for-event-handler)))
|
2014-09-04 23:31:20 +00:00
|
|
|
|
2014-09-05 04:04:44 +00:00
|
|
|
(defun lean-server-consume-all-async-tasks ()
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-consume-all-async-tasks: queue size = %d"
|
2014-09-08 23:03:44 +00:00
|
|
|
(lean-server-async-task-queue-len))
|
2014-09-04 23:31:20 +00:00
|
|
|
(while lean-global-async-task-queue
|
|
|
|
(accept-process-output (lean-server-get-process) 0 50 t)
|
2014-09-11 11:09:21 +00:00
|
|
|
(let* ((front-item (lean-server-async-task-queue-peek-front))
|
|
|
|
(cont (car front-item))
|
|
|
|
(cmd-type (cdr front-item))
|
|
|
|
(result (lean-server-check-and-process-buffer-with-cont cont
|
|
|
|
cmd-type)))
|
2014-09-04 23:31:20 +00:00
|
|
|
(pcase result
|
|
|
|
(`(PROCESSED ,ret)
|
2014-09-06 06:04:22 +00:00
|
|
|
(lean-server-async-task-queue-pop-front)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-consume-all-sync-tasks: processed. queue size = %d"
|
2014-09-11 11:09:21 +00:00
|
|
|
(lean-server-async-task-queue-len)))
|
|
|
|
(`(NOTREADY)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-consume-all-sync-tasks: not ready. queue size = %d"
|
2014-09-11 11:09:21 +00:00
|
|
|
(lean-server-async-task-queue-len)))
|
|
|
|
(t
|
|
|
|
(lean-server-async-task-queue-pop-front)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-consume-all-sync-tasks: either error or quit happend. queue size = %d"
|
2014-09-08 23:03:44 +00:00
|
|
|
(lean-server-async-task-queue-len))))))
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-consume-all-async-tasks: over. queue size = %d"
|
2014-09-08 23:03:44 +00:00
|
|
|
(lean-server-async-task-queue-len)))
|
2014-09-04 23:31:20 +00:00
|
|
|
|
2014-09-05 04:04:44 +00:00
|
|
|
(defun lean-server-send-cmd-sync (cmd &optional cont)
|
|
|
|
"Send cmd to lean-server (sync)."
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "send-cmd-sync: %S" (lean-cmd-type cmd))
|
2014-09-05 04:04:44 +00:00
|
|
|
(lean-server-cancel-retry-timer)
|
|
|
|
(lean-server-consume-all-async-tasks)
|
2014-09-04 23:31:20 +00:00
|
|
|
(lean-server-send-cmd cmd)
|
2014-09-11 11:07:50 +00:00
|
|
|
(let ((result (lean-server-check-and-process-buffer-with-cont cont (lean-cmd-type cmd))))
|
|
|
|
(while (equal result '(NOTREADY))
|
2014-09-04 23:31:20 +00:00
|
|
|
(accept-process-output (lean-server-get-process) 0 50 t)
|
2014-09-11 11:07:50 +00:00
|
|
|
(setq result (lean-server-check-and-process-buffer-with-cont cont (lean-cmd-type cmd))))
|
2014-09-04 23:31:20 +00:00
|
|
|
(pcase result
|
2014-09-11 11:07:50 +00:00
|
|
|
(`(PROCESSED ,ret)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-send-cmd-sync: %S, processed result = %S"
|
2014-09-11 11:07:50 +00:00
|
|
|
cmd
|
|
|
|
result)
|
|
|
|
ret)
|
|
|
|
(`(ERROR ,err)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-send-cmd-sync: %S, error = %S"
|
2014-09-11 11:07:50 +00:00
|
|
|
cmd
|
|
|
|
err))
|
|
|
|
(`(QUIT ,err)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-send-cmd-sync: %S, quit = %S"
|
2014-09-11 11:07:50 +00:00
|
|
|
cmd
|
|
|
|
err))
|
|
|
|
(t
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-send-cmd-sync: %S, ??? = %S"
|
2014-09-11 11:07:50 +00:00
|
|
|
cmd
|
|
|
|
result)))))
|
2014-09-03 07:39:54 +00:00
|
|
|
|
2014-09-03 07:45:16 +00:00
|
|
|
(defun lean-show-parse-string (str)
|
2014-09-04 23:31:20 +00:00
|
|
|
"Parse the output of show command."
|
2014-09-03 07:45:16 +00:00
|
|
|
(let ((str-list (split-string str "\n")))
|
|
|
|
;; Drop the first line "-- BEGINSHOW" and
|
|
|
|
;; the last line "-- ENDSHOW"
|
|
|
|
(setq str-list
|
|
|
|
(-take (- (length str-list) 2)
|
|
|
|
(-drop 1 str-list)))
|
|
|
|
(string-join str-list "\n")))
|
|
|
|
|
2014-09-04 22:30:23 +00:00
|
|
|
(defun lean-findp-parse-string (str)
|
|
|
|
"Parse the output of findp command."
|
|
|
|
(let ((str-list (split-string str "\n")))
|
|
|
|
;; Drop the first line "-- BEGINFINDP" and
|
|
|
|
;; the last line "-- ENDFINDP"
|
|
|
|
(setq str-list
|
|
|
|
(-take (- (length str-list) 2)
|
|
|
|
(-drop 1 str-list)))
|
|
|
|
(--map
|
2015-02-28 01:03:02 +00:00
|
|
|
(let ((items (s-split-up-to "|" it 1)))
|
2014-09-04 22:30:23 +00:00
|
|
|
`(,(cl-first items) . ,(cl-second items))) str-list)))
|
|
|
|
|
2014-09-08 20:14:15 +00:00
|
|
|
(defun lean-findg-parse-string (str)
|
|
|
|
"Parse the output of findg command."
|
|
|
|
(let ((str-list (split-string str "\n")))
|
|
|
|
;; Drop the first line "-- BEGINFINDG" and
|
|
|
|
;; the last line "-- ENDFINDG"
|
|
|
|
(setq str-list
|
|
|
|
(-take (- (length str-list) 2)
|
|
|
|
(-drop 1 str-list)))
|
|
|
|
(--map
|
|
|
|
(let ((items (split-string it "|")))
|
|
|
|
`(,(cl-first items) . ,(cl-second items))) str-list)))
|
|
|
|
|
2014-09-03 07:45:16 +00:00
|
|
|
(defun lean-server-show ()
|
|
|
|
(interactive)
|
2014-09-04 23:31:20 +00:00
|
|
|
(lean-server-send-cmd-async (lean-cmd-show) 'message))
|
2014-09-03 07:45:16 +00:00
|
|
|
|
|
|
|
(defun lean-server-valid ()
|
|
|
|
(interactive)
|
2014-09-04 23:31:20 +00:00
|
|
|
(lean-server-send-cmd-async (lean-cmd-valid) 'message))
|
|
|
|
|
|
|
|
(defun lean-server-set-timer-for-event-handler ()
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "set-timer-for-event-handler")
|
2014-09-04 23:31:20 +00:00
|
|
|
(unless lean-global-retry-timer
|
|
|
|
(setq lean-global-retry-timer
|
|
|
|
(run-with-idle-timer
|
|
|
|
(if (current-idle-time)
|
|
|
|
(time-add (seconds-to-time lean-server-retry-time) (current-idle-time))
|
|
|
|
lean-server-retry-time)
|
|
|
|
nil
|
|
|
|
'lean-server-event-handler)))
|
|
|
|
nil)
|
2014-08-14 00:02:49 +00:00
|
|
|
|
2014-09-03 07:39:54 +00:00
|
|
|
(defun lean-server-get-info-record-at-pos (body)
|
|
|
|
(let* ((file-name (buffer-file-name))
|
2014-10-07 21:40:54 +00:00
|
|
|
(column (lean-line-offset)))
|
2014-10-28 21:04:53 +00:00
|
|
|
(save-excursion
|
|
|
|
(when (and (or (looking-at (rx (or white ")" "}" "]")))
|
|
|
|
(eolp))
|
|
|
|
(> column 1))
|
|
|
|
(setq column (1- column))
|
|
|
|
(backward-char 1))
|
|
|
|
(lean-info-record-parse body file-name column))))
|
2014-09-03 07:39:54 +00:00
|
|
|
|
2014-09-04 23:31:20 +00:00
|
|
|
(defun lean-server-event-handler ()
|
|
|
|
"Process an item from async-task-queue.
|
|
|
|
|
2014-09-05 22:22:59 +00:00
|
|
|
If it's successful, take it out from the queue.
|
|
|
|
Otherwise, set an idle-timer to call the handler again"
|
|
|
|
(lean-server-cancel-retry-timer)
|
|
|
|
(when (eq major-mode 'lean-mode)
|
2014-09-11 11:09:21 +00:00
|
|
|
(let* ((front-item (lean-server-async-task-queue-peek-front))
|
|
|
|
(cont (car front-item))
|
|
|
|
(cmd-type (cdr front-item))
|
|
|
|
(result (lean-server-check-and-process-buffer-with-cont cont
|
|
|
|
cmd-type)))
|
2014-09-05 22:22:59 +00:00
|
|
|
(pcase result
|
|
|
|
(`(PROCESSED ,ret)
|
2014-09-06 06:04:22 +00:00
|
|
|
(lean-server-async-task-queue-pop-front)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "event-handler: processed. now the queue size = %d\n"
|
2014-09-06 06:04:22 +00:00
|
|
|
(lean-server-async-task-queue-len))
|
2014-09-10 21:13:17 +00:00
|
|
|
ret)
|
2014-09-11 11:07:50 +00:00
|
|
|
(`(NOTREADY)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "event-handler: not ready. queue size = %d"
|
2014-09-11 11:07:50 +00:00
|
|
|
(lean-server-async-task-queue-len)))
|
|
|
|
(`(ERROR ,err)
|
|
|
|
(lean-server-async-task-queue-pop-front)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "event-handler: error %S. queue size = %d"
|
2014-09-11 11:07:50 +00:00
|
|
|
err
|
|
|
|
(lean-server-async-task-queue-len)))
|
|
|
|
(`(QUIT ,err)
|
|
|
|
(lean-server-async-task-queue-pop-front)
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "event-handler: quit %S. queue size = %d"
|
2014-09-11 11:07:50 +00:00
|
|
|
err
|
|
|
|
(lean-server-async-task-queue-len)))))
|
2014-09-05 22:22:59 +00:00
|
|
|
(if lean-global-async-task-queue (lean-server-set-timer-for-event-handler))))
|
2014-09-03 07:45:16 +00:00
|
|
|
|
2014-09-10 19:45:19 +00:00
|
|
|
(defun lean-server-after-save ()
|
|
|
|
(let ((current-file-name (buffer-file-name)))
|
|
|
|
(when current-file-name
|
2014-09-12 16:20:31 +00:00
|
|
|
(lean-debug "lean-server-handle-save: %s" current-file-name)
|
2014-09-10 19:45:19 +00:00
|
|
|
(lean-server-send-cmd-async (lean-cmd-visit current-file-name)))))
|
|
|
|
|
|
|
|
(defun lean-server-save-buffer-to-temp-file (prefix)
|
|
|
|
"Save the current buffer to a temp-file and return its path"
|
|
|
|
(interactive)
|
|
|
|
(let ((temp-file (make-temp-file prefix)))
|
|
|
|
(with-current-buffer (flymake-copy-buffer-to-temp-buffer (current-buffer))
|
|
|
|
(set-visited-file-name temp-file)
|
2014-09-11 19:35:26 +00:00
|
|
|
(save-buffer 0)
|
2014-09-10 19:45:19 +00:00
|
|
|
(kill-buffer))
|
|
|
|
temp-file))
|
|
|
|
|
|
|
|
(defun lean-server-handle-modified-buffer ()
|
|
|
|
"Handle modified buffer when lean-mode start"
|
2014-10-03 17:09:19 +00:00
|
|
|
(when (buffer-modified-p)
|
|
|
|
(lean-server-send-cmd-async (lean-cmd-sync))))
|
2014-09-10 19:45:19 +00:00
|
|
|
|
2014-08-14 00:02:49 +00:00
|
|
|
(provide 'lean-server)
|