bash 使用“文件名:行”语法打开文件行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3139970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Open a file at line with "filename:line" syntax
提问by elmarco
Very often, compilations errors are displayed with the file:linesyntax.
很多时候,编译错误与file:line语法一起显示。
It would be nice to copy-paste this directly to open the file at the right line.
最好直接复制粘贴它以在正确的行打开文件。
Emacs already has some mode to handle this in buffers (compile-mode, iirc), but I would like to have this available from the shell command line, since I use the standard shell most of the time outside of emacs.
Emacs 已经有一些模式可以在缓冲区中处理这个问题(编译模式,iirc),但我希望可以从 shell 命令行获得它,因为我大部分时间在 emacs 之外使用标准 shell。
Any idea how to tweak emacs to learn file:linesyntax to open fileat line line? (obviously, if file:linereally exists on disk, it should be opened preferably)
知道如何调整 emacs 以学习在线file:line打开的语法吗?(显然,如果磁盘上确实存在,最好打开)filelinefile:line
回答by sanityinc
You can do this using emacsclient. e.g. to open FILE at line 4, column 3 in a new frame:
您可以使用 emacsclient 执行此操作。例如,在新框架中的第 4 行第 3 列处打开 FILE:
emacsclient +4:3 FILE
Leave off the :3to simply open the file at line 4.
省略:3以简单地在第 4 行打开文件。
回答by Ivan Andrus
I have the following in my .emacs, but I haven't found it as useful as I thought it would be.
我的.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))))))
回答by jacob
And here is my go at it. Calls the original find-file-at-point
这是我的目标。调用原始的 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)))
回答by user3674075
I suggest to add following code in your emacs config:
我建议在您的 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))
)
by now you can open file with a line number right from command line like this:
现在,您可以直接从命令行打开带有行号的文件,如下所示:
emacsclient filename:linenumber:position
P.S. I hope i'm not too late with my answer.
PS我希望我的回答不会太晚。
回答by H?kon H?gland
You can use a bash script:
您可以使用 bash 脚本:
#! /bin/bash
file=$(awk '{sub(/:[0-9]*$/,"")}1' <<< "")
line=$(awk '{sub(/^.*:/,"")}1' <<< "")
emacs --no-splash "+$line" "$file" &
If you call this script for openlineand you get an error message, e.g.
如果您调用此脚本openline并收到错误消息,例如
Error: file.cpp:1046
you can do
你可以做
openline file.cpp:1046
to open the file.cppin Emacsat line 1046..
在第 1046 行打开file.cppin Emacs..
回答by ecmanaut
Another version of Ivan Andrus' nice find-file advice which does both line + optional column number, as you see in node and coffeescript errors:
另一个版本的 Ivan Andrus 的不错的 find-file 建议,它同时执行行 + 可选列号,正如您在节点和咖啡脚本错误中看到的:
;; 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)))))))
回答by Everton J. Carpes
Emacs 25 does not use defadviceanymore. Refs.
Emacs 25 不再使用defadvice。参考。
So here is the version updated to the new syntax:
所以这里是更新到新语法的版本:
(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)
This works if you call open file from inside emacs (C-x C-f), but not works anymore from command line, it seems that emacs 25 is not using find-filewhen you call it from command line and I don't know how to debug this kind of thing.
如果您从 emacs (Cx Cf) 内部调用打开文件,这将起作用,但不再从命令行运行,似乎 emacs 25find-file在您从命令行调用时没有使用,我不知道如何调试这种事物。
回答by Joe Casadonte
You talk about pasting to open a file (I assume you mean at a find file prompt inside of emacs) and also doing something from the command line. If you want to copy & paste then you need to do something like what Ivan showed with the defadvice. If you want something from the command line you can do the following. I've adapted this from something I did a year ago with an emacs:// URI handler (for use from within Firefox):
您谈论粘贴以打开文件(我假设您的意思是在 emacs 内的查找文件提示符下)以及从命令行执行某些操作。如果你想复制和粘贴,那么你需要做一些像 Ivan 用 defadvice 展示的那样。如果您想从命令行获得一些东西,您可以执行以下操作。我已经从我一年前用 emacs:// URI 处理程序(用于在 Firefox 中使用)所做的事情改编了这个:
Put this in your .emacs file:
把它放在你的 .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))))
and then create a shell script in your path (I called mine 'emacsat'):
然后在您的路径中创建一个 shell 脚本(我称我的为“emacsat”):
#!/bin/bash
emacsclient --no-wait -e "(emacs-uri-handler \"emacs:///${2:-1}\")"
A DOS batch script would look similar, but I don't know how to do default values (though I'm pretty sure you can do it).
DOS 批处理脚本看起来很相似,但我不知道如何设置默认值(尽管我很确定您可以做到)。
See How to configure firefox to run emacsclientw on certain links?for further instructions if you want to integrate with Firefox, too.
请参阅如何配置 firefox 以在某些链接上运行 emacsclientw?如果您也想与 Firefox 集成,请参阅进一步说明。
回答by return42
I made a little rewrite of the find-file-at-pointfunction.
我对该find-file-at-point函数进行了一些重写。
If there is a line number match, the file will be opened within an other window and the courser will be placed in this line. If no line number match, do what ffap normally does ...
如果行号匹配,则文件将在另一个窗口中打开,并且课程将放置在此行中。如果没有行号匹配,请执行 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))))))
If you have an old version of the ffap (2008) you should update your emacs or apply an other small patch ...
如果您有旧版本的 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
回答by DrChandra
To return42's code, added column number support, and cleaned up case where column number is present, and line number is sought.
为了返回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))))))

