2010-06-29 27 views
48

通常,编译错误通过file:line语法显示。使用“文件名:行”语法打开文件

如果直接复制粘贴以便在正确的位置打开文件将会很好。

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

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

+0

我想看到一种方式来打开文件传递emacs PHP错误。这看起来像这样:警告:在_drupal_schema_initialize()中为foreach()提供了无效参数(/srv/work.electricgroups.com/dave/projects/htdocs/includes/common.inc的第6866行)。 – 2012-08-21 04:58:50

+4

谨慎选择答案? – sanityinc 2012-09-17 09:02:56

回答

40

您可以使用emacsclient执行此操作。例如在新的框架中打开第4行文件中,列3:

emacsclient +4:3 FILE 

离开关:3简单地打开该文件在第4行

+5

“-c”标志表示创建一个新的框架;你不必指定为了跳转到工作。 – Damyan 2010-06-29 14:06:45

+0

好点 - 这是个人喜好/习惯的问题。 – sanityinc 2010-06-29 19:32:08

+1

虽然这是一个有趣的事实,但是当你从错误消息中剪切和粘贴文件名时,Ivan的解决方案功能更强大,就像原始问题 – simpleuser 2015-03-09 01:35:40

13

我已经在我的.emacs以下,但还没发现它和我想象的一样有用。

;; Open files and goto lines like we see from g++ etc. i.e. 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)))))) 
+0

好!任何想法如何挂钩在默认打开功能? – elmarco 2010-06-29 14:24:52

+0

我不确定你的意思。 find-file _is_是默认的打开函数。 C-h C-k C-x C-f表示什么? – 2010-06-30 13:02:06

+2

“defadvice”修改下一个名称的定义(在本例中为find-file,默认打开的函数)。所以这个(defadvice find-file ...)实际上修改find​​文件来表现这种行为。 – jackr 2012-09-24 21:29:00

3

请您谈一下粘贴打开一个文件(我假设你的意思是在查找文件提示的Emacs内),并做一些命令行。如果你想复制&粘贴,那么你需要做一些事情,比如伊万在defadvice中显示的内容。如果你想从命令行得到一些东西,你可以做以下事情。 (Firefox中使用来自)// URI处理程序:我已经适应了这个从我做的事一年前用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)))) 

,然后创建:

在你的.emacs文件将这个在你的路径shell脚本(我叫我的“emacsat”):

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

DOS批处理脚本将看起来相似,但我不知道该怎么办的默认值(虽然我敢肯定,你可以做它)。

请参阅How to configure firefox to run emacsclientw on certain links?了解更多说明,如果您想要与Firefox集成。

+0

我可以从中得到一些想法,虽然它依赖于shell太多了(我可以可能写一个脚本来处理文件:没有语法,这是一个想法) – elmarco 2010-06-29 15:06:30

1

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

如果存在行号匹配,文件将在另一个窗口中打开,并且courser将被放置在该行中。如果没有行号的比赛,做什么FFAP一般不会...

;; 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-n-p "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 
9

这就是我的目标。调用原始查找文件,在点

(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))) 
+0

为我工作!谢谢! – dolzenko 2012-10-31 18:03:47

+0

我只是将(find-file-at-point)更改为(find-file(ffap-guesser))。然后你没有得到提示:) – teaforthecat 2013-07-21 02:42:03

+1

@jacob没有为我工作,它打开了一个缓冲区file.ext:34。 – Jaseem 2013-09-07 19:03:28

7

伊万·安德鲁斯 - 尼斯找到文件咨询的另一个版本,同时做两线+可选的列数,只要在节点和CoffeeScript的错误,请参阅:

;; Open files and go places like we see from error messages, i e: 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))))))) 
+0

棒极了,效果很棒! – 2013-09-05 19:06:27

+0

有没有什么办法可以在启动emacs时在命令行中为第二个和后续文件做这项工作? – simpleuser 2015-03-09 01:49:42

0

要返回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-n-p "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)))))) 
1

这是一个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

8

您可以使用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 

以线1046打开Emacsfile.cpp ..

+0

谢谢!,这帮助了我!我正在使用一个稍微修改过的版本:'emacs --no-splash“+ $ line”--file“$ file”' – nacho4d 2014-01-04 14:25:59

7

我建议加上按照您的Emacs配置代码:

(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 

P.S.我希望我的回答不迟。

+2

对于有用的答案永远不会太晚。 – phils 2014-05-25 22:23:08

+0

似乎不适合我:( – elmarco 2014-05-26 08:15:00

+0

elmarco:测试和工作在emacs 24.3,FWIW。 – phils 2014-05-26 21:57:30

1

我修改伊万 - 安德鲁斯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))))))) 
2

的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当你从命令行调用它,我不知道如何调试这种事情。