按照“filename:line”语法打开文件

通常情况下,编译错误与file:line语法一起显示。

这将是很好的复制粘贴直接打开该文件在正确的行。

Emacs已经有一些模式可以在缓冲区(编译模式,iirc)中处理这个问题,但是我希望在shell命令行中提供这个模式,因为我在emacs之外大部分时间使用标准shell。

任何想法如何调整emacs学习file:line语法来打开file line ? (显然,如果file:line确实存在于磁盘上,最好打开它)

你可以使用emacsclient来做到这一点。 例如在第4行第3列打开一个新文件夹中的文件:

 emacsclient +4:3 FILE 

离开:3 ,直接在第4行打开文件。

我在我的.emacs有以下内容,但我没有发现它像我想的那样有用。

 ;; Open files and goto lines like we see from g++ etc. ie file:line# ;; (to-do "make `find-file-line-number' work for emacsclient as well") ;; (to-do "make `find-file-line-number' check if the file exists") (defadvice find-file (around find-file-line-number (filename &optional wildcards) activate) "Turn files like file.cpp:14 into file.cpp and going to the 14-th line." (save-match-data (let* ((matched (string-match "^\\(.*\\):\\([0-9]+\\):?$" filename)) (line-number (and matched (match-string 2 filename) (string-to-number (match-string 2 filename)))) (filename (if matched (match-string 1 filename) filename))) ad-do-it (when line-number ;; goto-line is for interactive use (goto-char (point-min)) (forward-line (1- line-number)))))) 

这是我去的地方 调用最初的find-file-at-point

 (defun find-file-at-point-with-line() "if file has an attached line num goto that line, ie boom.rb:12" (interactive) (setq line-num 0) (save-excursion (search-forward-regexp "[^ ]:" (point-max) t) (if (looking-at "[0-9]+") (setq line-num (string-to-number (buffer-substring (match-beginning 0) (match-end 0)))))) (find-file-at-point) (if (not (equal line-num 0)) (goto-line line-num))) 

Ivan Andrus的另一个版本,它提供了很好的find-filebuild议,可以在行+可选的列号中使用,就像在node和coffeescript错误中看到的那样:

 ;; Open files and go places like we see from error messages, ie: path:line:col ;; (to-do "make `find-file-line-number' work for emacsclient as well") ;; (to-do "make `find-file-line-number' check if the file exists") (defadvice find-file (around find-file-line-number (path &optional wildcards) activate) "Turn files like file.js:14:10 into file.js and going to line 14, col 10." (save-match-data (let* ((match (string-match "^\\(.*?\\):\\([0-9]+\\):?\\([0-9]*\\)$" path)) (line-no (and match (match-string 2 path) (string-to-number (match-string 2 path)))) (col-no (and match (match-string 3 path) (string-to-number (match-string 3 path)))) (path (if match (match-string 1 path) path))) ad-do-it (when line-no ;; goto-line is for interactive use (goto-char (point-min)) (forward-line (1- line-no)) (when (> col-no 0) (forward-char (1- col-no))))))) 

你可以使用一个bash脚本:

 #! /bin/bash file=$(awk '{sub(/:[0-9]*$/,"")}1' <<< "$1") line=$(awk '{sub(/^.*:/,"")}1' <<< "$1") emacs --no-splash "+$line" "$file" & 

如果您将此脚本openline并且您收到错误消息,例如

 Error: file.cpp:1046 

你可以做

 openline file.cpp:1046 

Emacs 1046行打开file.cpp

我build议在你的emacsconfiguration中添加下面的代码:

 (defadvice server-visit-files (before parse-numbers-in-lines (files proc &optional nowait) activate) "looks for filenames like file:line or file:line:position and reparses name in such manner that position in file" (ad-set-arg 0 (mapcar (lambda (fn) (let ((name (car fn))) (if (string-match "^\\(.*?\\):\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?$" name) (cons (match-string 1 name) (cons (string-to-number (match-string 2 name)) (string-to-number (or (match-string 3 name) ""))) ) fn))) files)) ) 

现在你可以像命令行一样从命令行打开文件:

 emacsclient filename:linenumber:position 

PS我希望我的回答不迟。

你谈论粘贴来打开一个文件(我假设你的意思是在emacs里面的查找文件提示符),也可以从命令行执行一些操作。 如果你想复制和粘贴,那么你需要做的事情就像伊万显示defadvice。 如果你想从命令行得到一些东西,你可以做以下的事情。 我已经从一年前使用emacs:// URI处理程序(从Firefox内部使用)进行了调整:

把它放在你的.emacs文件中:

 (defun emacs-uri-handler (uri) "Handles emacs URIs in the form: emacs:///path/to/file/LINENUM" (save-match-data (if (string-match "emacs://\\(.*\\)/\\([0-9]+\\)$" uri) (let ((filename (match-string 1 uri)) (linenum (match-string 2 uri))) (while (string-match "\\(%20\\)" filename) (setq filename (replace-match " " nil t filename 1))) (with-current-buffer (find-file filename) (goto-line (string-to-number linenum)))) (beep) (message "Unable to parse the URI <%s>" uri)))) 

然后在你的path中创build一个shell脚本(我称之为“emacsat”):

 #!/bin/bash emacsclient --no-wait -e "(emacs-uri-handler \"emacs://$1/${2:-1}\")" 

一个DOS批处理脚本看起来类似,但我不知道如何做默认值(虽然我敢肯定,你可以做到这一点)。

请参阅如何configurationFirefox以在特定链接上运行emacsclientw? 如果您想要与Firefox集成,还需要进一步的说明。

我对find-file-at-point函数做了一点改写。

如果有一个行号匹配,该文件将在另一个窗口内打开,并将在这一行中的courser。 如果没有行号匹配,通常做什么…

 ;; find file at point, jump to line no. ;; ==================================== (require 'ffap) (defun find-file-at-point-with-line (&optional filename) "Opens file at point and moves point to line specified next to file name." (interactive) (let* ((filename (or filename (ffap-prompter))) (line-number (and (or (looking-at ".* line \\(\[0-9\]+\\)") (looking-at ".*:\\(\[0-9\]+\\):")) (string-to-number (match-string-no-properties 1))))) (message "%s --> %s" filename line-number) (cond ((ffap-url-p filename) (let (current-prefix-arg) (funcall ffap-url-fetcher filename))) ((and line-number (file-exists-p filename)) (progn (find-file-other-window filename) (goto-line line-number))) ((and ffap-pass-wildcards-to-dired ffap-dired-wildcards (string-match ffap-dired-wildcards filename)) (funcall ffap-directory-finder filename)) ((and ffap-dired-wildcards (string-match ffap-dired-wildcards filename) find-file-wildcards ;; Check if it's find-file that supports wildcards arg (memq ffap-file-finder '(find-file find-alternate-file))) (funcall ffap-file-finder (expand-file-name filename) t)) ((or (not ffap-newfile-prompt) (file-exists-p filename) (y-or-np "File does not exist, create buffer? ")) (funcall ffap-file-finder ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. (expand-file-name filename))) ;; User does not want to find a non-existent file: ((signal 'file-error (list "Opening file buffer" "no such file or directory" filename)))))) 

如果你有一个老版本的ffap(2008),你应该更新你的emacs或者应用其他小补丁…

 --- Emacs/lisp/ffap.el +++ Emacs/lisp/ffap.el @@ -1170,7 +1170,7 @@ which may actually result in an url rather than a filename." ;; remote, you probably already have a connection. ((and (not abs) (ffap-file-exists-string name))) ;; Try stripping off line numbers; good for compilation/grep output. - ((and (not abs) (string-match ":[0-9]" name) + ((and (string-match ":[0-9]" name) (ffap-file-exists-string (substring name 0 (match-beginning 0))))) ;; Try stripping off prominent (non-root - #) shell prompts 

这是一个zsh函数,如果你把它放到你的.zshrc文件中,

由于我通常在zsh中运行我的代码,而这正是我查看错误的地方。 荣誉@sanityinc的emacs部分。 只是认为这应该是在谷歌。

 emn () { blah=$1 filen=(${(s.:.)blah}) /Applications/Emacs.app/Contents/MacOS/Emacs +$filen[2] $filen[1] & } 

使用像emn /long/stack/error.rb:123

我修改了ivan-andrus defadvice所以它可以和emacsclient一起使用:

 (defadvice find-file-noselect (around find-file-noselect-at-line (filename &optional nowarn rawfile wildcards) activate) "Turn files like file.cpp:14 into file.cpp and going to the 14-th line." (save-match-data (let* ((matched (string-match "^\\(.*\\):\\([0-9]+\\):?$" filename)) (line-number (and matched (match-string 2 filename) (string-to-number (match-string 2 filename)))) (filename (if matched (match-string 1 filename) filename)) (buffer-name ad-do-it)) (when line-number (with-current-buffer buffer-name (goto-char (point-min)) (forward-line (1- line-number))))))) 

Emacs 25不再使用defadvice 。 参考文献:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Porting-old-advice.html

所以这里是更新到新语法的版本:

 (defun find-file--line-number (orig-fun filename &optional wildcards) "Turn files like file.cpp:14 into file.cpp and going to the 14-th line." (save-match-data (let* ((matched (string-match "^\\(.*\\):\\([0-9]+\\):?$" filename)) (line-number (and matched (match-string 2 filename) (string-to-number (match-string 2 filename)))) (filename (if matched (match-string 1 filename) filename))) (apply orig-fun (list filename wildcards)) (when line-number ;; goto-line is for interactive use (goto-char (point-min)) (forward-line (1- line-number)))))) (advice-add 'find-file :around #'find-file--line-number) 

如果你从emacs(Cx Cf)中调用打开的文件,但是不能从命令行中工作,这看起来很正常,看起来emacs 25在你从命令行调用它的时候没有使用find-file ,我不知道如何debugging这种事情

要返回42的代码,添加列号支持,并清理列号存在的情况,并寻找行号。

 ;; find file at point, jump to line no. ;; ==================================== (require 'ffap) (defun find-file-at-point-with-line (&optional filename) "Opens file at point and moves point to line specified next to file name." (interactive) (let* ((filename (or filename (if current-prefix-arg (ffap-prompter) (ffap-guesser)))) (line-number (and (or (looking-at ".* line \\(\[0-9\]+\\)") (looking-at "[^:]*:\\(\[0-9\]+\\)")) (string-to-number (match-string-no-properties 1)))) (column-number (or (and (looking-at "[^:]*:\[0-9\]+:\\(\[0-9\]+\\)") (string-to-number (match-string-no-properties 1))) (let 'column-number 0)))) (message "%s --> %s:%s" filename line-number column-number) (cond ((ffap-url-p filename) (let (current-prefix-arg) (funcall ffap-url-fetcher filename))) ((and line-number (file-exists-p filename)) (progn (find-file-other-window filename) ;; goto-line is for interactive use (goto-char (point-min)) (forward-line (1- line-number)) (forward-char column-number))) ((and ffap-pass-wildcards-to-dired ffap-dired-wildcards (string-match ffap-dired-wildcards filename)) (funcall ffap-directory-finder filename)) ((and ffap-dired-wildcards (string-match ffap-dired-wildcards filename) find-file-wildcards ;; Check if it's find-file that supports wildcards arg (memq ffap-file-finder '(find-file find-alternate-file))) (funcall ffap-file-finder (expand-file-name filename) t)) ((or (not ffap-newfile-prompt) (file-exists-p filename) (y-or-np "File does not exist, create buffer? ")) (funcall ffap-file-finder ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. (expand-file-name filename))) ;; User does not want to find a non-existent file: ((signal 'file-error (list "Opening file buffer" "no such file or directory" filename))))))