3333; ;
3434; ; Add the following to your init file:
3535; ;
36- ; ; ;; Enable Flycheck checker
36+ ; ; (add-to-list 'load-path "/path/to/directory/containing/flycheck-julia.el/file")
37+ ; ; (require 'flycheck-julia)
3738; ; (flycheck-julia-setup)
39+ ; ; (add-to-list 'flycheck-global-modes 'julia-mode)
40+ ; ; (add-to-list 'flycheck-global-modes 'ess-julia-mode)
3841; ;
3942; ; # Usage
4043; ;
4750(require 'json )
4851(require 'flycheck )
4952
50-
51-
5253(defgroup flycheck-julia nil
5354 " flycheck-julia options"
5455 :prefix " flycheck-julia"
6566 :type 'integer
6667 :group 'flycheck-julia )
6768
68- (defcustom flycheck-julia-max-wait 1
69- " The maximum time to wait for an answer from the server."
70- :type 'number
71- :group 'flycheck-julia )
72-
73- (defun flycheck-julia-start-or-query-server (checker callback )
74- " Start a Julia syntax check, init the server if necessary.
75-
76- CHECKER and CALLBACK are flycheck requirements."
77-
78- ; ; TODO: use (when ...) here and do the query
79- (if (not (flycheck-julia-serverp))
80- (progn
81- (message " no server --- starting " )
82- (flycheck-julia-server-start)
83- (funcall callback 'finished nil ))
84- (message " server running --- querying " )
85- (funcall callback 'finished (flycheck-julia-server-query checker))))
69+ ; ; (defcustom flycheck-julia-max-wait 0.01
70+ ; ; "The maximum time to wait for an answer from the server."
71+ ; ; :type 'number
72+ ; ; :group 'flycheck-julia)
8673
87- ; ; TODO: make these functions interactive
88- ; ; needs checking, if the server is already running, closing of the linter
89- ; ; buffer, etc...
74+ ; ; This is the variable that is used to receive the data from the server
75+ ; ; TODO: Find out if this is possible without a global value
76+ (setq flycheck-julia-proc-output " " )
77+ (setq flycheck-julia-server-proc nil )
9078
91- (defun flycheck-julia-serverp ()
92- " Check if the lint server is up"
93- (get-process " flycheck-julia-server" ))
79+ (defun flycheck-julia-server-p ()
80+ " Check if the Lint server is up, returns the process or nil "
81+ (processp flycheck-julia-server-proc ))
9482
9583(defun flycheck-julia-server-start ()
96- " Start the julia server for linting."
97- (start-process-shell-command
98- " flycheck-julia-server" " *julia-linter*"
99- ; ; TODO: use pipes or something different than an open port
100- ; ; TODO: decide how too handle query on exit (set-process-query-on-exit-flag)
101- (concat flycheck-julia-executable
102- " -e \' using Lint\; lintserver\( "
103- (number-to-string flycheck-julia-port)
104- " \, \" standard-linter-v2\"\)\' " )))
84+ " If not already running, start the Julia server for linting."
85+ (if (not (flycheck-julia-server-p))
86+ (setq flycheck-julia-server-proc
87+ (start-process-shell-command
88+ " flycheck-julia-server" " *julia-linter*"
89+ ; ; TODO: use pipes or something different than an open port
90+ ; ; TODO: decide how too handle query on exit (set-process-query-on-exit-flag)
91+ (concat flycheck-julia-executable
92+ " -e \' using Lint\; lintserver\( "
93+ (number-to-string flycheck-julia-port)
94+ " \, \" standard-linter-v2\"\)\' " )))
95+ (message " flycheck-julia-server-start: server already running. " )))
10596
10697(defun flycheck-julia-server-stop ()
107- " Kill the julia lint server."
108- (kill-process (get-process " flycheck-julia-server" )))
98+ " Kill the Julia lint server."
99+ (interactive )
100+ (delete-process flycheck-julia-server-proc)
101+ (setq flycheck-julia-server-proc nil ))
109102
110103(defun flycheck-julia-server-restart ()
111- " Kill the julia lint server and restart it."
104+ " Kill the Julia lint server and restart it."
105+ (interactive )
112106 (flycheck-julia-server-stop)
113107 (sleep-for 5 )
114108 (flycheck-julia-server-start))
115109
116- (defun flycheck-julia-server-query (checker )
110+ (defun flycheck-julia-start-or-query-server (checker callback )
111+ " Start a Julia syntax check, start the server if necessary.
112+
113+ CHECKER and CALLBACK are flycheck requirements."
114+
115+ (when (not (flycheck-julia-server-p)) (flycheck-julia-server-start))
116+ (flycheck-julia-server-query checker callback))
117+
118+ (defun flycheck-julia-server-query (checker callback )
117119 " Query a lint.
118120
119121Query a lint for the current buffer and return the errors as
120122flycheck objects.
121123
122124CHECKER is 'julia-linter, this is a flycheck internal."
123-
124- ; ; TODO: is it better to have the network process running all the time?
125- ; ; i.e. is there overhead for using a new process every time this function is run?
126- (let ((proc (make-network-process
127- :name " julia-lint-client"
128- :host 'local
129- :service flycheck-julia-port))
130- (query-list `((" file" . ,(if buffer-file-name (buffer-file-name ) " " ))
131- (" code_str" . ,(buffer-substring-no-properties
132- (point-min ) (point-max )))
133- (" ignore_info" . , json-false )
134- (" ignore_warnings" . , json-false )
135- (" show_code" . t )))
136- (proc-output nil ))
137-
138- ; ; Network processes may be return results in different orders, then we are
139- ; ; screwed, not sure what to do about this? use named pipes? use sockets?
140- ; ; use priority queues?
141- ; ; I actually never observed this, so ignoring it for now.
142- ; ; TODO: this gives a compiler warning, try to make the warning disappear!
143- (defun flycheck-julia-keep-output (process output )
144- (setq proc-output (concat proc-output output)))
145- (set-process-filter proc 'flycheck-julia-keep-output )
146-
147- (process-send-string proc (json-encode query-list))
148-
149- ; ; Because our process is asynchronous, we need to
150- ; ; 1. to wait and
151- ; ; 2. the string is sent in 500 char pieces and the results may arrive in a
152- ; ; different order. -> I did not observe this behavior until now!
153- ; ; TODO: figure out a way to do this completely asynchronous.
154- (accept-process-output proc flycheck-julia-max-wait)
155- (flycheck-julia-error-parser
156- (when proc-output (json-read-from-string proc-output))
157- checker
158- (current-buffer ))))
125+ (setq flycheck-julia-proc-output " " )
126+
127+ (let* ((filter (lambda (process output )
128+ (setq flycheck-julia-proc-output
129+ (concat flycheck-julia-proc-output output))))
130+ ; ; This is where the asynchronous magic is supposed to happen:
131+ ; ;
132+ ; ; the returned string can be:
133+ ; ;
134+ ; ; "", i.e the server is not running yet -> not parsed correctly
135+ ; ;
136+ ; ; "[]", there are no errors -> parsed correctly to json
137+ ; ;
138+ ; ; a complete json object -> there are errors/issues in the file,
139+ ; ; everything is fine
140+ ; ;
141+ ; ; an incomplete json object -> the object was not retrieved correctly
142+ ; ;
143+ ; ;Also: this sentinl should only be called if the connection is closed,
144+ ; ; if it gets with a different message, something is wrong
145+ (sentinel (lambda (process event )
146+ (unless (string= event " connection broken by remote peer\n " )
147+ (message " connection not closed! " ))
148+ (delete-process process)
149+ (if (string= flycheck-julia-proc-output " " )
150+ (funcall callback 'interrupted )
151+ (condition-case nil
152+ (funcall callback 'finished
153+ (flycheck-julia-error-parser
154+ (json-read-from-string
155+ flycheck-julia-proc-output)
156+ checker
157+ (current-buffer )))
158+ (error (funcall callback 'errored
159+ " there was a parsing error" ))))))
160+ ; ; if the server is not running yet, this fails because it cannot
161+ ; ; connect to the server and np will be nil
162+ (np (ignore-errors (make-network-process :name " flycheck-julia-client"
163+ :host 'local
164+ :service flycheck-julia-port
165+ :filter filter
166+ :sentinel sentinel)))
167+ (js (json-encode `((" file" . ,(if buffer-file-name (buffer-file-name ) (buffer-name )))
168+ (" code_str" . ,(buffer-substring-no-properties (point-min ) (point-max )))
169+ (" ignore_info" . , json-false )
170+ (" ignore_warnings" . , json-false )
171+ (" show_code" . t )))))
172+ ; ; return immediately without any errors, leave that to the sentinel
173+ (if np (process-send-string np js) (funcall callback 'interrupted ))))
159174
160175(defun flycheck-julia-error-parser (errors checker buffer )
161176 " Parse the error returned from the Julia lint server.
@@ -173,6 +188,7 @@ BUFFER is the buffer that was checked for errors."
173188 ; ; Lint.jl returns 0-based line and column numbers
174189 ; ; Lint.jl returns only a line in the format [[l, 0], [l, 80]],
175190 :line (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0 ) 0 ))
191+ ; ; TODO: simply put 0 here?
176192 :column (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0 ) 1 ))
177193 :message (cdr (assoc 'excerpt it))
178194 :level (intern (cdr (assoc 'severity it)))))
0 commit comments