33
33
; ;
34
34
; ; Add the following to your init file:
35
35
; ;
36
- ; ; ;; Enable Flycheck checker
36
+ ; ; (add-to-list 'load-path "/path/to/directory/containing/flycheck-julia.el/file")
37
+ ; ; (require 'flycheck-julia)
37
38
; ; (flycheck-julia-setup)
39
+ ; ; (add-to-list 'flycheck-global-modes 'julia-mode)
40
+ ; ; (add-to-list 'flycheck-global-modes 'ess-julia-mode)
38
41
; ;
39
42
; ; # Usage
40
43
; ;
47
50
(require 'json )
48
51
(require 'flycheck )
49
52
50
-
51
-
52
53
(defgroup flycheck-julia nil
53
54
" flycheck-julia options"
54
55
:prefix " flycheck-julia"
65
66
:type 'integer
66
67
:group 'flycheck-julia )
67
68
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)
86
73
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 )
90
78
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 ))
94
82
95
83
(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. " )))
105
96
106
97
(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 ))
109
102
110
103
(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 )
112
106
(flycheck-julia-server-stop)
113
107
(sleep-for 5 )
114
108
(flycheck-julia-server-start))
115
109
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 )
117
119
" Query a lint.
118
120
119
121
Query a lint for the current buffer and return the errors as
120
122
flycheck objects.
121
123
122
124
CHECKER 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 ))))
159
174
160
175
(defun flycheck-julia-error-parser (errors checker buffer )
161
176
" Parse the error returned from the Julia lint server.
@@ -173,6 +188,7 @@ BUFFER is the buffer that was checked for errors."
173
188
; ; Lint.jl returns 0-based line and column numbers
174
189
; ; Lint.jl returns only a line in the format [[l, 0], [l, 80]],
175
190
:line (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0 ) 0 ))
191
+ ; ; TODO: simply put 0 here?
176
192
:column (1+ (aref (aref (cdr (assoc 'position (cdr (assoc 'location it)))) 0 ) 1 ))
177
193
:message (cdr (assoc 'excerpt it))
178
194
:level (intern (cdr (assoc 'severity it)))))
0 commit comments