diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-08 19:22:26 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-08 19:22:26 -0800 |
commit | 6ee827059463e4b95c9251ef22a21f9c67cf668d (patch) | |
tree | 0612e1b84922cc43eeed5ea219104d4c5985cbdf /lisp/progmodes | |
parent | 83dc3f0e9b518e45bcfb0aaebcc706f79622f157 (diff) | |
parent | 255ba01148f69f452937e67feb7af5d4c1466fed (diff) | |
download | emacs-6ee827059463e4b95c9251ef22a21f9c67cf668d.tar.gz |
Merge from origin/emacs-26
255ba01148 Fix handling of nil PRED2 arg for completion-table-with-pr...
949b70a7d8 ; Minor comment copyedit in window.c
20f9bf30f0 Describe Lao rendering problem
3d61657694 Fix docstring of arabic-shaper-ZWNJ-handling
db949166ec Handle single-line comments correctly (Bug#26049)
795bb233a5 * test/lisp/net/tramp-tests.el (tramp-test16-file-expand-w...
ba00ea7d0d * etc/PROBLEMS: Add URL to relevant issues for xterm+evil bug
4a6015811e ; In text.texi fix typo spotted by Štěpán Němec
93cd8415b2 Document new treatment of 'comment-auto-fill-only-comments'
ca2d94ba61 Do not load Tramp unless `tramp-mode' is non-nil
709478eaa8 Prefer `customize-set-variable' in tramp.texi
5d36f2227f Fix last change in hscroll_window_tree
72d07d1950 Ediff: add some missing documentation
18af404ef3 Support python virtualenv on w32 (Bug#24464)
efd0371c23 Improve dired deletion error handling (Bug#28797)
5d744e032f Don't replace user input when completion prefix is empty (...
ec6cf35c5f ; Describe xt-mouse problems with Evil mode
c572e1f329 Return non-nil from gnutls-available-p under GnuTLS 2.x
a2cc6d74c5 Fix Flymake help-echo functions across windows (bug#29142)
58bb3462ee Add tests for Flymake backends for Ruby and Perl
58e742b21d Add a Flymake backend for Perl
9dee764165 Add a Flymake backend for Ruby
3ad712ebc9 Add a Flymake backend for Python (bug#28808)
8db2b3a79b Allow "%" in Tramp host names
8c50842790 ; Fix typo in test/file-organization.org
00fa4449cd ; Fix typo
918a2dda07 Use hybrid malloc for FreeBSD (Bug#28308)
725ab635d9 Add html-, mhtml- and python-mode support to semantic symref
369da28702 Improve documentation of 'window-scroll-functions'
93818eed8a Fix subtle problems in tabulated-list-mode with line numbers
1f1de8e872 Make gdb-non-stop-setting default to nil on MS-Windows
680e8e119b Fix gdb-mi prompt after "attach PID" command
ff33074546 Fix doc string of 'window-configuration-change-hook'
787b75ad71 Improve documentation of window hooks
d9be8704ae Fix hscroll suspension after cursor motion
6f43d29d29 ; * CONTRIBUTE, admin/make-tarball.txt: Doc tweaks re 'ema...
a0d30d6369 Introduce a function to CC Mode which displays the current...
383abc8898 ; Fix some comment typos
b02c2714c3 Fix typos in ediff-wind.el
4f38bdec74 Examine tex-chktex--process in the correct buffer
94b490529a * nt/INSTALL.W64: Update to current mingw64 install instru...
c25113d4ac Don't resignal errors in flymake-diag-region
e950f329c0 New xref-quit-and-goto-xref command bound to TAB (bug#28814)
5d34e1b288 Allow split-window-sensibly to split threshold in further ...
2a973edeac Honor window-switching intents in xref-find-definitions (b...
78e9065e9f * lisp/emacs-lisp/generator.el (iter-do): Add a debug decl...
caa63cc96c * lisp/progmodes/flymake.el (flymake-start): Fix dead buff...
9f4f130b79 Fix buffer name comparison in async shell-command
# Conflicts:
# etc/NEWS
# lisp/vc/ediff-wind.el
Diffstat (limited to 'lisp/progmodes')
-rw-r--r-- | lisp/progmodes/cc-cmds.el | 19 | ||||
-rw-r--r-- | lisp/progmodes/cc-mode.el | 3 | ||||
-rw-r--r-- | lisp/progmodes/cperl-mode.el | 4 | ||||
-rw-r--r-- | lisp/progmodes/flymake-proc.el | 2 | ||||
-rw-r--r-- | lisp/progmodes/flymake.el | 26 | ||||
-rw-r--r-- | lisp/progmodes/gdb-mi.el | 19 | ||||
-rw-r--r-- | lisp/progmodes/perl-mode.el | 71 | ||||
-rw-r--r-- | lisp/progmodes/python.el | 151 | ||||
-rw-r--r-- | lisp/progmodes/ruby-mode.el | 63 | ||||
-rw-r--r-- | lisp/progmodes/xref.el | 91 |
10 files changed, 397 insertions, 52 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index ca64b544200..2b663135932 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -1821,7 +1821,6 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'." "Return the name of the current defun, or NIL if there isn't one. \"Defun\" here means a function, or other top level construct with a brace block." - (interactive) (c-save-buffer-state (beginning-of-defun-function end-of-defun-function where pos name-end case-fold-search) @@ -2048,6 +2047,23 @@ with a brace block." (eq (char-after) ?\{) (cons (point-min) (point-max)))))))) +(defun c-display-defun-name (&optional arg) + "Display the name of the current CC mode defun and the position in it. +With a prefix arg, push the name onto the kill ring too." + (interactive "P") + (save-restriction + (widen) + (c-save-buffer-state ((name (c-defun-name)) + (limits (c-declaration-limits t)) + (point-bol (c-point 'bol))) + (when name + (message "%s. Line %s/%s." name + (1+ (count-lines (car limits) point-bol)) + (count-lines (car limits) (cdr limits))) + (if arg (kill-new name)) + (sit-for 3 t))))) +(put 'c-display-defun-name 'isearch-scroll t) + (defun c-mark-function () "Put mark at end of the current top-level declaration or macro, point at beginning. If point is not inside any then the closest following one is @@ -2092,7 +2108,6 @@ function does not require the declaration to contain a brace block." (defun c-cpp-define-name () "Return the name of the current CPP macro, or NIL if we're not in one." - (interactive) (let (case-fold-search) (save-excursion (and c-opt-cpp-macro-define-start diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index b0e5fe47a7c..f74e931a8bb 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -389,7 +389,8 @@ control). See \"cc-mode.el\" for more info." ;;(define-key c-mode-base-map "\C-c\C-v" 'c-version) ;; (define-key c-mode-base-map "\C-c\C-y" 'c-toggle-hungry-state) Commented out by ACM, 2005-11-22. (define-key c-mode-base-map "\C-c\C-w" 'c-subword-mode) - (define-key c-mode-base-map "\C-c\C-k" 'c-toggle-comment-style)) + (define-key c-mode-base-map "\C-c\C-k" 'c-toggle-comment-style) + (define-key c-mode-base-map "\C-c\C-z" 'c-display-defun-name)) ;; We don't require the outline package, but we configure it a bit anyway. (cc-bytecomp-defvar outline-level) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 1681922fa5a..e6ab8c4ea60 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -1896,7 +1896,9 @@ or as help on variables `cperl-tips', `cperl-problems', (if cperl-pod-here-scan (or cperl-syntaxify-by-font-lock (progn (or cperl-faces-init (cperl-init-faces-weak)) - (cperl-find-pods-heres))))) + (cperl-find-pods-heres)))) + ;; Setup Flymake + (add-hook 'flymake-diagnostic-functions 'perl-flymake nil t)) ;; Fix for perldb - make default reasonable (defun cperl-db () diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el index f504a1c21a8..e28451d9417 100644 --- a/lisp/progmodes/flymake-proc.el +++ b/lisp/progmodes/flymake-proc.el @@ -82,7 +82,7 @@ Overrides `flymake-proc-allowed-file-name-masks'." ("\\.xml\\'" flymake-proc-xml-init) ("\\.html?\\'" flymake-proc-xml-init) ("\\.cs\\'" flymake-proc-simple-make-init) - ("\\.p[ml]\\'" flymake-proc-perl-init) + ;; ("\\.p[ml]\\'" flymake-proc-perl-init) ("\\.php[345]?\\'" flymake-proc-php-init) ("\\.h\\'" flymake-proc-master-make-header-init flymake-proc-master-cleanup) ("\\.java\\'" flymake-proc-simple-make-java-init flymake-proc-simple-java-cleanup) diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 19dac81fe6d..0d200f01b34 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -342,7 +342,7 @@ region is invalid." (let* ((beg (fallback-bol)) (end (fallback-eol beg))) (cons beg end))))))) - (error (flymake-error "Invalid region line=%s col=%s" line col)))) + (error (flymake-log :warning "Invalid region line=%s col=%s" line col)))) (defvar flymake-diagnostic-functions nil "Special hook of Flymake backends that check a buffer. @@ -522,11 +522,12 @@ associated `flymake-category' return DEFAULT." (flymake--fringe-overlay-spec (overlay-get ov 'bitmap))) (default-maybe 'help-echo - (lambda (_window _ov pos) - (mapconcat - #'flymake--diag-text - (flymake-diagnostics pos) - "\n"))) + (lambda (window _ov pos) + (with-selected-window window + (mapconcat + #'flymake--diag-text + (flymake-diagnostics pos) + "\n")))) (default-maybe 'severity (warning-numeric-level :error)) (default-maybe 'priority (+ 100 (overlay-get ov 'severity)))) ;; Some properties can't be overridden. @@ -603,8 +604,8 @@ not expected." (null expected-token)) ;; should never happen (flymake-error "Unexpected report from stopped backend %s" backend)) - ((and (not (eq expected-token token)) - (not force)) + ((not (or (eq expected-token token) + force)) (flymake-error "Obsolete report from backend %s with explanation %s" backend explanation)) ((eq :panic report-action) @@ -744,8 +745,11 @@ Interactively, with a prefix arg, FORCE is t." () (remove-hook 'post-command-hook #'start-post-command nil) - (with-current-buffer buffer - (flymake-start (remove 'post-command deferred) force))) + ;; The buffer may have disappeared already, e.g. because of + ;; code like `(with-temp-buffer (python-mode) ...)'. + (when (buffer-live-p buffer) + (with-current-buffer buffer + (flymake-start (remove 'post-command deferred) force)))) (start-on-display () (remove-hook 'window-configuration-change-hook #'start-on-display @@ -948,7 +952,7 @@ applied." (message "%s" (funcall (overlay-get target 'help-echo) - nil nil (point))))) + (selected-window) target (point))))) (interactive (user-error "No more Flymake errors%s" (if filter diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 28d1974893d..58552759b95 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -400,14 +400,22 @@ valid signal handlers.") (const :tag "Unlimited" nil)) :version "22.1") -(defcustom gdb-non-stop-setting t - "When in non-stop mode, stopped threads can be examined while +(defcustom gdb-non-stop-setting (not (eq system-type 'windows-nt)) + "If non-nil, GDB sessions are expected to support the non-stop mode. +When in the non-stop mode, stopped threads can be examined while other threads continue to execute. +If this is non-nil, GDB will be sent the \"set non-stop 1\" command, +and if that results in an error, the non-stop setting will be +turned off automatically. + +On MS-Windows, this is off by default, because MS-Windows targets +don't support the non-stop mode. + GDB session needs to be restarted for this setting to take effect." :type 'boolean :group 'gdb-non-stop - :version "23.2") + :version "26.1") ;; TODO Some commands can't be called with --all (give a notice about ;; it in setting doc) @@ -2188,7 +2196,10 @@ a GDB/MI reply message." (defun gdbmi-bnf-console-stream-output (c-string) "Handler for the console-stream-output GDB/MI output grammar rule." - (gdb-console c-string)) + (gdb-console c-string) + ;; We've written to the GUD console, so we should print the prompt + ;; after the next result-class or async-class. + (setq gdb-first-done-or-error t)) (defun gdbmi-bnf-target-stream-output (_c-string) "Handler for the target-stream-output GDB/MI output grammar rule." diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el index 24b934ce6c2..8e7cd13088f 100644 --- a/lisp/progmodes/perl-mode.el +++ b/lisp/progmodes/perl-mode.el @@ -581,6 +581,73 @@ create a new comment." (match-string-no-properties 1)))) +;;; Flymake support +(defcustom perl-flymake-command '("perl" "-w" "-c") + "External tool used to check Perl source code. +This is a non empty list of strings, the checker tool possibly +followed by required arguments. Once launched it will receive +the Perl source to be checked as its standard input." + :group 'perl + :type '(repeat string)) + +(defvar-local perl--flymake-proc nil) + +;;;###autoload +(defun perl-flymake (report-fn &rest _args) + "Perl backend for Flymake. Launches +`perl-flymake-command' (which see) and passes to its standard +input the contents of the current buffer. The output of this +command is analysed for error and warning messages." + (unless (executable-find (car perl-flymake-command)) + (error "Cannot find a suitable checker")) + + (when (process-live-p perl--flymake-proc) + (kill-process perl--flymake-proc)) + + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq + perl--flymake-proc + (make-process + :name "perl-flymake" :noquery t :connection-type 'pipe + :buffer (generate-new-buffer " *perl-flymake*") + :command perl-flymake-command + :sentinel + (lambda (proc _event) + (when (eq 'exit (process-status proc)) + (unwind-protect + (if (with-current-buffer source (eq proc perl--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp + "^\\(.+\\) at - line \\([0-9]+\\)" + nil t) + for msg = (match-string 1) + for (beg . end) = (flymake-diag-region + source + (string-to-number (match-string 2))) + for type = + (if (string-match + "\\(Scalar value\\|Useless use\\|Unquoted string\\)" + msg) + :warning + :error) + collect (flymake-make-diagnostic source + beg + end + type + msg) + into diags + finally (funcall report-fn diags))) + (flymake-log :debug "Canceling obsolete check %s" + proc)) + (kill-buffer (process-buffer proc))))))) + (process-send-region perl--flymake-proc (point-min) (point-max)) + (process-send-eof perl--flymake-proc)))) + + (defvar perl-mode-hook nil "Normal hook to run when entering Perl mode.") @@ -665,7 +732,9 @@ Turning on Perl mode runs the normal hook `perl-mode-hook'." ;; Setup outline-minor-mode. (setq-local outline-regexp perl-outline-regexp) (setq-local outline-level 'perl-outline-level) - (setq-local add-log-current-defun-function #'perl-current-defun-name)) + (setq-local add-log-current-defun-function #'perl-current-defun-name) + ;; Setup Flymake + (add-hook 'flymake-diagnostic-functions #'perl-flymake nil t)) ;; This is used by indent-for-comment ;; to decide how much to indent a comment in Perl code diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 895117b9ee3..d4226e5ce7b 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -2113,20 +2113,25 @@ remote host, the returned value is intended for (defun python-shell-calculate-exec-path () "Calculate `exec-path'. Prepends `python-shell-exec-path' and adds the binary directory -for virtualenv if `python-shell-virtualenv-root' is set. If -`default-directory' points to a remote host, the returned value -appends `python-shell-remote-exec-path' instead of `exec-path'." +for virtualenv if `python-shell-virtualenv-root' is set - this +will use the python interpreter from inside the virtualenv when +starting the shell. If `default-directory' points to a remote host, +the returned value appends `python-shell-remote-exec-path' instead +of `exec-path'." (let ((new-path (copy-sequence (if (file-remote-p default-directory) python-shell-remote-exec-path - exec-path)))) + exec-path))) + + ;; Windows and POSIX systems use different venv directory structures + (virtualenv-bin-dir (if (eq system-type 'windows-nt) "Scripts" "bin"))) (python-shell--add-to-path-with-priority new-path python-shell-exec-path) (if (not python-shell-virtualenv-root) new-path (python-shell--add-to-path-with-priority new-path - (list (expand-file-name "bin" python-shell-virtualenv-root))) + (list (expand-file-name virtualenv-bin-dir python-shell-virtualenv-root))) new-path))) (defun python-shell-tramp-refresh-remote-path (vec paths) @@ -5142,6 +5147,138 @@ returned as is." (ignore-errors (string-match regexp "") t)) +;;; Flymake integration + +(defgroup python-flymake nil + "Integration between Python and Flymake." + :group 'python + :link '(custom-group-link :tag "Flymake" flymake) + :version "26.1") + +(defcustom python-flymake-command '("pyflakes") + "The external tool that will be used to perform the syntax check. +This is a non empty list of strings, the checker tool possibly followed by +required arguments. Once launched it will receive the Python source to be +checked as its standard input. +To use `flake8' you would set this to (\"flake8\" \"-\")." + :group 'python-flymake + :type '(repeat string)) + +;; The default regexp accomodates for older pyflakes, which did not +;; report the column number, and at the same time it's compatible with +;; flake8 output, although it may be redefined to explicitly match the +;; TYPE +(defcustom python-flymake-command-output-pattern + (list + "^\\(?:<?stdin>?\\):\\(?1:[0-9]+\\):\\(?:\\(?2:[0-9]+\\):\\)? \\(?3:.*\\)$" + 1 2 nil 3) + "Specify how to parse the output of `python-flymake-command'. +The value has the form (REGEXP LINE COLUMN TYPE MESSAGE): if +REGEXP matches, the LINE'th subexpression gives the line number, +the COLUMN'th subexpression gives the column number on that line, +the TYPE'th subexpression gives the type of the message and the +MESSAGE'th gives the message text itself. + +If COLUMN or TYPE are nil or that index didn't match, that +information is not present on the matched line and a default will +be used." + :group 'python-flymake + :type '(list regexp + (integer :tag "Line's index") + (choice + (const :tag "No column" nil) + (integer :tag "Column's index")) + (choice + (const :tag "No type" nil) + (integer :tag "Type's index")) + (integer :tag "Message's index"))) + +(defcustom python-flymake-msg-alist + '(("\\(^redefinition\\|.*unused.*\\|used$\\)" . :warning)) + "Alist used to associate messages to their types. +Each element should be a cons-cell (REGEXP . TYPE), where TYPE must be +one defined in the variable `flymake-diagnostic-types-alist'. +For example, when using `flake8' a possible configuration could be: + + ((\"\\(^redefinition\\|.*unused.*\\|used$\\)\" . :warning) + (\"^E999\" . :error) + (\"^[EW][0-9]+\" . :note)) + +By default messages are considered errors." + :group 'python-flymake + :type `(alist :key-type (regexp) + :value-type (symbol))) + +(defvar-local python--flymake-proc nil) + +(defun python--flymake-parse-output (source proc report-fn) + "Collect diagnostics parsing checker tool's output line by line." + (let ((rx (nth 0 python-flymake-command-output-pattern)) + (lineidx (nth 1 python-flymake-command-output-pattern)) + (colidx (nth 2 python-flymake-command-output-pattern)) + (typeidx (nth 3 python-flymake-command-output-pattern)) + (msgidx (nth 4 python-flymake-command-output-pattern))) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp rx nil t) + for msg = (match-string msgidx) + for (beg . end) = (flymake-diag-region + source + (string-to-number + (match-string lineidx)) + (and colidx + (match-string colidx) + (string-to-number + (match-string colidx)))) + for type = (or (and typeidx + (match-string typeidx) + (assoc-default + (match-string typeidx) + python-flymake-msg-alist + #'string-match)) + (assoc-default msg + python-flymake-msg-alist + #'string-match) + :error) + collect (flymake-make-diagnostic + source beg end type msg) + into diags + finally (funcall report-fn diags))))) + +(defun python-flymake (report-fn &rest _args) + "Flymake backend for Python. +This backend uses `python-flymake-command' (which see) to launch a process +that is passed the current buffer's content via stdin. +REPORT-FN is Flymake's callback function." + (unless (executable-find (car python-flymake-command)) + (error "Cannot find a suitable checker")) + + (when (process-live-p python--flymake-proc) + (kill-process python--flymake-proc)) + + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq python--flymake-proc + (make-process + :name "python-flymake" + :noquery t + :connection-type 'pipe + :buffer (generate-new-buffer " *python-flymake*") + :command python-flymake-command + :sentinel + (lambda (proc _event) + (when (eq 'exit (process-status proc)) + (unwind-protect + (when (with-current-buffer source + (eq proc python--flymake-proc)) + (python--flymake-parse-output source proc report-fn)) + (kill-buffer (process-buffer proc))))))) + (process-send-region python--flymake-proc (point-min) (point-max)) + (process-send-eof python--flymake-proc)))) + + (defun python-electric-pair-string-delimiter () (when (and electric-pair-mode (memq last-command-event '(?\" ?\')) @@ -5255,7 +5392,9 @@ returned as is." (make-local-variable 'python-shell-internal-buffer) (when python-indent-guess-indent-offset - (python-indent-guess-indent-offset))) + (python-indent-guess-indent-offset)) + + (add-hook 'flymake-diagnostic-functions #'python-flymake nil t)) (provide 'python) diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 0024957c39b..1f4aa6d9fbd 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -2253,6 +2253,68 @@ See `font-lock-syntax-table'.") (progn (set-match-data value) t)) (ruby-match-expression-expansion limit))))) +;;; Flymake support +(defcustom ruby-flymake-command '("ruby" "-w" "-c") + "External tool used to check Ruby source code. +This is a non empty list of strings, the checker tool possibly +followed by required arguments. Once launched it will receive +the Ruby source to be checked as its standard input." + :group 'ruby + :type '(repeat string)) + +(defvar-local ruby--flymake-proc nil) + +(defun ruby-flymake (report-fn &rest _args) + "Ruby backend for Flymake. Launches +`ruby-flymake-command' (which see) and passes to its standard +input the contents of the current buffer. The output of this +command is analysed for error and warning messages." + (unless (executable-find (car ruby-flymake-command)) + (error "Cannot find a suitable checker")) + + (when (process-live-p ruby--flymake-proc) + (kill-process ruby--flymake-proc)) + + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq + ruby--flymake-proc + (make-process + :name "ruby-flymake" :noquery t :connection-type 'pipe + :buffer (generate-new-buffer " *ruby-flymake*") + :command ruby-flymake-command + :sentinel + (lambda (proc _event) + (when (eq 'exit (process-status proc)) + (unwind-protect + (if (with-current-buffer source (eq proc ruby--flymake-proc)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp + "^\\(?:.*.rb\\|-\\):\\([0-9]+\\): \\(.*\\)$" + nil t) + for msg = (match-string 2) + for (beg . end) = (flymake-diag-region + source + (string-to-number (match-string 1))) + for type = (if (string-match "^warning" msg) + :warning + :error) + collect (flymake-make-diagnostic source + beg + end + type + msg) + into diags + finally (funcall report-fn diags))) + (flymake-log :debug "Canceling obsolete check %s" + proc)) + (kill-buffer (process-buffer proc))))))) + (process-send-region ruby--flymake-proc (point-min) (point-max)) + (process-send-eof ruby--flymake-proc)))) + ;;;###autoload (define-derived-mode ruby-mode prog-mode "Ruby" "Major mode for editing Ruby code." @@ -2265,6 +2327,7 @@ See `font-lock-syntax-table'.") (add-hook 'after-save-hook 'ruby-mode-set-encoding nil 'local) (add-hook 'electric-indent-functions 'ruby--electric-indent-p nil 'local) + (add-hook 'flymake-diagnostic-functions 'ruby-flymake nil 'local) (setq-local font-lock-defaults '((ruby-font-lock-keywords) nil nil)) (setq-local font-lock-keywords ruby-font-lock-keywords) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 3dbf65ef6f5..db025d40aa3 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -448,43 +448,74 @@ If SELECT is non-nil, select the target window." (when xref-w (set-window-dedicated-p xref-w xref-w-dedicated))))) -(defun xref--show-pos-in-buf (pos buf select) - (let ((xref-buf (current-buffer)) - win) +(defvar-local xref--original-window-intent nil + "Original window-switching intent before xref buffer creation.") + +(defvar-local xref--original-window nil + "The original window this xref buffer was created from.") + +(defun xref--show-pos-in-buf (pos buf) + "Goto and display position POS of buffer BUF in a window. +Honor `xref--original-window-intent', run `xref-after-jump-hook' +and finally return the window." + (let* ((xref-buf (current-buffer)) + (pop-up-frames + (or (eq xref--original-window-intent 'frame) + pop-up-frames)) + (action + (cond ((memq + xref--original-window-intent + '(window frame)) + t) + ((and + (window-live-p xref--original-window) + (or (not (window-dedicated-p xref--original-window)) + (eq (window-buffer xref--original-window) buf))) + `(,(lambda (buf _alist) + (set-window-buffer xref--original-window buf) + xref--original-window)))))) (with-selected-window - (xref--with-dedicated-window - (display-buffer buf)) + (with-selected-window + ;; Just before `display-buffer', place ourselves in the + ;; original window to suggest preserving it. Of course, if + ;; user has deleted the original window, all bets are off, + ;; just use the selected one. + (or (and (window-live-p xref--original-window) + xref--original-window) + (selected-window)) + (display-buffer buf action)) (xref--goto-char pos) (run-hooks 'xref-after-jump-hook) (let ((buf (current-buffer))) - (setq win (selected-window)) (with-current-buffer xref-buf - (setq-local other-window-scroll-buffer buf)))) - (when select - (select-window win)))) + (setq-local other-window-scroll-buffer buf))) + (selected-window)))) (defun xref--show-location (location &optional select) + "Help `xref-show-xref' and `xref-goto-xref' do their job. +Go to LOCATION and if SELECT is non-nil select its window. If +SELECT is `quit', also quit the *xref* window." (condition-case err (let* ((marker (xref-location-marker location)) - (buf (marker-buffer marker))) - (xref--show-pos-in-buf marker buf select)) + (buf (marker-buffer marker)) + (xref-buffer (current-buffer))) + (cond (select + (if (eq select 'quit) (quit-window nil nil)) + (with-current-buffer xref-buffer + (select-window (xref--show-pos-in-buf marker buf)))) + (t + (save-selected-window + (xref--with-dedicated-window + (xref--show-pos-in-buf marker buf)))))) (user-error (message (error-message-string err))))) -(defvar-local xref--window nil - "The original window this xref buffer was created from.") - (defun xref-show-location-at-point () "Display the source of xref at point in the appropriate window, if any." (interactive) (let* ((xref (xref--item-at-point)) (xref--current-item xref)) (when xref - ;; Try to avoid the window the current xref buffer was - ;; originally created from. - (if (window-live-p xref--window) - (with-selected-window xref--window - (xref--show-location (xref-item-location xref))) - (xref--show-location (xref-item-location xref)))))) + (xref--show-location (xref-item-location xref))))) (defun xref-next-line () "Move to the next xref and display its source in the appropriate window." @@ -503,12 +534,19 @@ If SELECT is non-nil, select the target window." (back-to-indentation) (get-text-property (point) 'xref-item))) -(defun xref-goto-xref () - "Jump to the xref on the current line and select its window." +(defun xref-goto-xref (&optional quit) + "Jump to the xref on the current line and select its window. +Non-interactively, non-nil QUIT means to first quit the *xref* +buffer." (interactive) (let ((xref (or (xref--item-at-point) (user-error "No reference at point")))) - (xref--show-location (xref-item-location xref) t))) + (xref--show-location (xref-item-location xref) (if quit 'quit t)))) + +(defun xref-quit-and-goto-xref () + "Quit *xref* buffer, then jump to xref on current line." + (interactive) + (xref-goto-xref t)) (defun xref-query-replace-in-results (from to) "Perform interactive replacement of FROM with TO in all displayed xrefs. @@ -632,6 +670,7 @@ references displayed in the current *xref* buffer." (define-key map (kbd "p") #'xref-prev-line) (define-key map (kbd "r") #'xref-query-replace-in-results) (define-key map (kbd "RET") #'xref-goto-xref) + (define-key map (kbd "TAB") #'xref-quit-and-goto-xref) (define-key map (kbd "C-o") #'xref-show-location-at-point) ;; suggested by Johan Claesson "to further reduce finger movement": (define-key map (kbd ".") #'xref-next-line) @@ -726,7 +765,8 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)." (xref--xref-buffer-mode) (pop-to-buffer (current-buffer)) (goto-char (point-min)) - (setq xref--window (assoc-default 'window alist)) + (setq xref--original-window (assoc-default 'window alist) + xref--original-window-intent (assoc-default 'display-action alist)) (current-buffer))))) @@ -753,7 +793,8 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)." (t (xref-push-marker-stack) (funcall xref-show-xrefs-function xrefs - `((window . ,(selected-window))))))) + `((window . ,(selected-window)) + (display-action . ,display-action)))))) (defun xref--prompt-p (command) (or (eq xref-prompt-for-identifier t) |