Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Open a file at line with "filename:line" syntax

Tags:

bash

emacs

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

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.

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

like image 886
elmarco Avatar asked Jun 29 '10 10:06

elmarco


6 Answers

You can do this using emacsclient. e.g. to open FILE at line 4, column 3 in a new frame:

emacsclient +4:3 FILE

Leave off the :3 to simply open the file at line 4.

like image 182
sanityinc Avatar answered Nov 04 '22 15:11

sanityinc


I have the following in my .emacs, but I haven't found it as useful as I thought it would be.

;; 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))))))
like image 30
Ivan Andrus Avatar answered Nov 04 '22 16:11

Ivan Andrus


I suggest to add following code in your emacs config:

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

like image 12
user3674075 Avatar answered Nov 04 '22 16:11

user3674075


And here is my go at it. Calls the original 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)))
like image 10
jacob Avatar answered Nov 04 '22 15:11

jacob


You can use a 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 you get an error message, e.g.

Error: file.cpp:1046

you can do

openline file.cpp:1046

to open the file.cpp in Emacs at line 1046..

like image 9
Håkon Hægland Avatar answered Nov 04 '22 16:11

Håkon Hægland


Another version of Ivan Andrus' nice find-file advice which does both line + optional column number, as you see in node and coffeescript errors:

;; 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)))))))
like image 8
ecmanaut Avatar answered Nov 04 '22 15:11

ecmanaut