Open the file in a line with the syntax "filename: line"

Very often compilation errors are displayed with the syntax file:line .

It would be nice to copy-paste this directly to open the file on the right line.

Emacs already has some mode for handling this in buffers (compile-mode, iirc), but I would like it to be accessible from the shell command line, since I use the standard shell most of the time outside of emacs.

Any idea how to configure emacs to learn the syntax of file:line to open file in line line ? (obviously, if file:line really exists on disk, it should be opened preferably)

+48
bash emacs
Jun 29 '10 at 10:56
source share
12 answers

You can do this using emacsclient. for example, to open FILE in row 4, column 3 in a new frame:

 emacsclient +4:3 FILE 

Leave the value :3 to simply open the file on line 4.

+39
Jun 29 2018-10-12T00:
source share

I have the following in my .emacs , but I did not find it useful, as I thought it would be.

 ;; 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)))))) 
+13
Jun 29 2018-10-06T00:
source share

And here is my move. Calls the source file 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))) 
+9
Aug 23 2018-12-23T00:
source share

Another version of the welcome advice of Ivan Andrus, which indicates the row number + optional column number, as you see in node and coffeescript errors:

 ;; 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))))))) 
+7
Aug 02
source share

You can use bash script:

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

If you call this script for openline and get an error message like

 Error: file.cpp:1046 

You can do

 openline file.cpp:1046 

to open file.cpp in Emacs on line 1046 ..

+7
Dec 04 '13 at 10:41
source share

I suggest adding the following code to your emacs configuration:

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

Now you can open the file with the line number directly from the command line as follows:

 emacsclient filename:linenumber:position 

PS I hope I'm not late with the answer.

+7
May 25 '14 at 16:55
source share

You are talking about insertion to open the file (I assume you mean the hint of the find file inside emacs), as well as doing something from the command line. If you want to copy and paste, you need to do something like what Ivan showed with a hyphen. If you want something from the command line, you can do the following. I adapted this from what I did a year ago, with the emacs: // URI handler (for use from Firefox):

Put this in your .emacs file:

 (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 my 'emacsat):

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

The DOS script package will be similar, but I do not know how to make the default values ​​(although I am sure you can do this).

See How to configure firefox to run emacsclientw with specific links? for more instructions if you want to integrate with Firefox.

+3
Jun 29 2018-10-06T00:
source share

Emacs 25 no longer uses defadvice . Refs :.

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

So, the version has been 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 the open file from inside emacs (Cx Cf), but no longer works from the command line, it seems that emacs 25 does not use find-file when you call it from the command line, and I don’t know how to debug such things .

+2
Sep 18 '17 at 7:23
source share

I rewrote the find-file-at-point function a bit.

If the line number corresponds, the file will be opened in another window, and the cursor will be placed in this line. If the line number does not match, do what ffap usually does ...

 ;; 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 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)))))) 

If you have an old version of ffap (2008), you should upgrade emacs or apply another small patch ...

 --- 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 
+1
Jan 05 '12 at 16:05
source share

Here is a zsh function that works if you put it in your .zshrc file.

Since I usually run my code in zsh, and this is where I see errors. Kudos to @sanityinc for the emacs part. Just thought it should be on google.

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

Use as emn /long/stack/error.rb:123

+1
Oct 13 '13 at 0:07
source share

I changed ivan-andrus defadvice , so it works with 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))))))) 
+1
Feb 14 '17 at 14:03
source share

The return42 code, added support for the column number and cleared case where the column number is present and the row number is requested.

 ;; 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 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)))))) 
0
Aug 30 '13 at 12:32
source share



All Articles