aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2017-11-22 01:04:27 +0200
committerDmitry Gutov2017-11-22 01:53:37 +0200
commit09944d499a361044d81eb6afaa29ffda885b2076 (patch)
tree8689c0b6ba3bcd95e30528a87227709df62378fa
parentc65a0ae7c4592d7fd9a47de3231e6ed07807f8af (diff)
downloademacs-09944d499a361044d81eb6afaa29ffda885b2076.tar.gz
emacs-09944d499a361044d81eb6afaa29ffda885b2076.zip
Add Rubocop Flymake backend
* lisp/progmodes/ruby-mode.el (ruby-flymake-command): Inline the value. There are no known substitutes. (ruby-flymake): Rename to `ruby-flymake-simple' and simplify the docstring. (ruby-flymake-use-rubocop-if-available): New option. (ruby--rubocop-flymake-proc): New variable. (ruby-rubocop-config): New option. (ruby-flymake-rubocop, ruby-flymake-auto): New functions. (ruby-mode): Use `ruby-flymake-auto'.
-rw-r--r--lisp/progmodes/ruby-mode.el118
1 files changed, 100 insertions, 18 deletions
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index da08bb0788e..18ed6ee5e79 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -2254,23 +2254,12 @@ See `font-lock-syntax-table'.")
2254 (ruby-match-expression-expansion limit))))) 2254 (ruby-match-expression-expansion limit)))))
2255 2255
2256;;; Flymake support 2256;;; Flymake support
2257(defcustom ruby-flymake-command '("ruby" "-w" "-c")
2258 "External tool used to check Ruby source code.
2259This is a non empty list of strings, the checker tool possibly
2260followed by required arguments. Once launched it will receive
2261the Ruby source to be checked as its standard input."
2262 :group 'ruby
2263 :type '(repeat string))
2264
2265(defvar-local ruby--flymake-proc nil) 2257(defvar-local ruby--flymake-proc nil)
2266 2258
2267(defun ruby-flymake (report-fn &rest _args) 2259(defun ruby-flymake-simple (report-fn &rest _args)
2268 "Ruby backend for Flymake. Launches 2260 "`ruby -wc' backend for Flymake."
2269`ruby-flymake-command' (which see) and passes to its standard 2261 (unless (executable-find "ruby")
2270input the contents of the current buffer. The output of this 2262 (error "Cannot find the ruby executable"))
2271command is analyzed for error and warning messages."
2272 (unless (executable-find (car ruby-flymake-command))
2273 (error "Cannot find a suitable checker"))
2274 2263
2275 (when (process-live-p ruby--flymake-proc) 2264 (when (process-live-p ruby--flymake-proc)
2276 (kill-process ruby--flymake-proc)) 2265 (kill-process ruby--flymake-proc))
@@ -2281,9 +2270,9 @@ command is analyzed for error and warning messages."
2281 (setq 2270 (setq
2282 ruby--flymake-proc 2271 ruby--flymake-proc
2283 (make-process 2272 (make-process
2284 :name "ruby-flymake" :noquery t :connection-type 'pipe 2273 :name "ruby-flymake-simple" :noquery t :connection-type 'pipe
2285 :buffer (generate-new-buffer " *ruby-flymake*") 2274 :buffer (generate-new-buffer " *ruby-flymake*")
2286 :command ruby-flymake-command 2275 :command '("ruby" "-w" "-c")
2287 :sentinel 2276 :sentinel
2288 (lambda (proc _event) 2277 (lambda (proc _event)
2289 (when (eq 'exit (process-status proc)) 2278 (when (eq 'exit (process-status proc))
@@ -2315,6 +2304,99 @@ command is analyzed for error and warning messages."
2315 (process-send-region ruby--flymake-proc (point-min) (point-max)) 2304 (process-send-region ruby--flymake-proc (point-min) (point-max))
2316 (process-send-eof ruby--flymake-proc)))) 2305 (process-send-eof ruby--flymake-proc))))
2317 2306
2307(defcustom ruby-flymake-use-rubocop-if-available t
2308 "Non-nil to use the Rubocop Flymake backend.
2309Only takes effect if Rubocop is installed."
2310 :type 'boolean
2311 :group 'ruby
2312 :safe 'booleanp)
2313
2314(defvar-local ruby--rubocop-flymake-proc nil)
2315
2316(defcustom ruby-rubocop-config ".rubocop.yml"
2317 "Configuration file for `ruby-flymake-rubocop'."
2318 :type 'string
2319 :group 'ruby
2320 :safe 'stringp)
2321
2322(defun ruby-flymake-rubocop (report-fn &rest _args)
2323 "Rubocop backend for Flymake."
2324 (unless (executable-find "rubocop")
2325 (error "Cannot find the rubocop executable"))
2326
2327 (when (process-live-p ruby--rubocop-flymake-proc)
2328 (kill-process ruby--rubocop-flymake-proc))
2329
2330 (let ((source (current-buffer))
2331 (command (list "rubocop" "--stdin" buffer-file-name "--format" "emacs"
2332 "--cache" "false" ; Work around a bug in old version.
2333 "--display-cop-names"))
2334 config-dir)
2335 (when buffer-file-name
2336 (setq config-dir (locate-dominating-file buffer-file-name
2337 ruby-rubocop-config))
2338 (when config-dir
2339 (setq command (append command (list "--config"
2340 (expand-file-name ruby-rubocop-config
2341 config-dir)))))
2342 (save-restriction
2343 (widen)
2344 (setq
2345 ruby--rubocop-flymake-proc
2346 (make-process
2347 :name "rubocop-flymake" :noquery t :connection-type 'pipe
2348 :buffer (generate-new-buffer " *rubocop-flymake*")
2349 :command command
2350 :sentinel
2351 (lambda (proc _event)
2352 (when (eq 'exit (process-status proc))
2353 (unwind-protect
2354 (if (with-current-buffer source (eq proc ruby--rubocop-flymake-proc))
2355 (with-current-buffer (process-buffer proc)
2356 ;; Finding the executable is no guarantee of
2357 ;; rubocop working, especially in the presence
2358 ;; of rbenv shims (which cross ruby versions).
2359 (unless (zerop (process-exit-status proc))
2360 (flymake-log :warning "Rubocop returned non-zero status: %s"
2361 (buffer-string)))
2362 (goto-char (point-min))
2363 (cl-loop
2364 while (search-forward-regexp
2365 "^\\(?:.*.rb\\|-\\):\\([0-9]+\\):\\([0-9]<<+\\): \\(.*\\)$"
2366 nil t)
2367 for msg = (match-string 3)
2368 for (beg . end) = (flymake-diag-region
2369 source
2370 (string-to-number (match-string 1))
2371 (string-to-number (match-string 2)))
2372 for type = (cond
2373 ((string-match "^[EF]: " msg)
2374 :error)
2375 ((string-match "^W: " msg)
2376 :warning)
2377 (t :note))
2378 collect (flymake-make-diagnostic source
2379 beg
2380 end
2381 type
2382 (substring msg 3))
2383 into diags
2384 finally (funcall report-fn diags)))
2385 (flymake-log :debug "Canceling obsolete check %s"
2386 proc))
2387 (kill-buffer (process-buffer proc)))))))
2388 (process-send-region ruby--rubocop-flymake-proc (point-min) (point-max))
2389 (process-send-eof ruby--rubocop-flymake-proc)))))
2390
2391(defun ruby-flymake-auto (report-fn &rest args)
2392 (apply
2393 (if (and ruby-flymake-use-rubocop-if-available
2394 (executable-find "rubocop"))
2395 #'ruby-flymake-rubocop
2396 #'ruby-flymake-simple)
2397 report-fn
2398 args))
2399
2318;;;###autoload 2400;;;###autoload
2319(define-derived-mode ruby-mode prog-mode "Ruby" 2401(define-derived-mode ruby-mode prog-mode "Ruby"
2320 "Major mode for editing Ruby code." 2402 "Major mode for editing Ruby code."
@@ -2327,7 +2409,7 @@ command is analyzed for error and warning messages."
2327 2409
2328 (add-hook 'after-save-hook 'ruby-mode-set-encoding nil 'local) 2410 (add-hook 'after-save-hook 'ruby-mode-set-encoding nil 'local)
2329 (add-hook 'electric-indent-functions 'ruby--electric-indent-p nil 'local) 2411 (add-hook 'electric-indent-functions 'ruby--electric-indent-p nil 'local)
2330 (add-hook 'flymake-diagnostic-functions 'ruby-flymake nil 'local) 2412 (add-hook 'flymake-diagnostic-functions 'ruby-flymake-auto nil 'local)
2331 2413
2332 (setq-local font-lock-defaults '((ruby-font-lock-keywords) nil nil)) 2414 (setq-local font-lock-defaults '((ruby-font-lock-keywords) nil nil))
2333 (setq-local font-lock-keywords ruby-font-lock-keywords) 2415 (setq-local font-lock-keywords ruby-font-lock-keywords)