bash - Abra un archivo en la línea con la sintaxis de "nombre de archivo: línea"
emacs (12)
Aquí hay una función zsh que funciona si la pones en tu archivo .zshrc
.
Ya que estoy ejecutando mi código en zsh por lo general, y aquí es donde veo los errores. Felicitaciones a @sanityinc por la parte de emacs. Sólo pensé que esto debería estar en google.
emn () {
blah=$1
filen=(${(s.:.)blah})
/Applications/Emacs.app/Contents/MacOS/Emacs +$filen[2] $filen[1] &
}
Use como emn /long/stack/error.rb:123
Muy a menudo, los errores de compilación se muestran con el file:line
sintaxis de file:line
.
Sería bueno copiar y pegar esto directamente para abrir el archivo en la línea derecha.
Emacs ya tiene algún modo para manejar esto en buffers (compile-mode, iirc), pero me gustaría tenerlo disponible desde la línea de comandos del shell, ya que uso el shell estándar la mayor parte del tiempo fuera de emacs.
¿Alguna idea de cómo ajustar emacs para aprender el file:line
sintaxis de file:line
para abrir el file
en la línea de line
? (Obviamente, si el file:line
realmente existe en el disco, debería abrirse preferiblemente)
Emacs 25 ya no usa defadvice
. Refs .
Así que aquí está la versión actualizada a la nueva sintaxis:
(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)
Esto funciona si llama a un archivo abierto desde dentro de emacs (Cx Cf), pero ya no funciona desde la línea de comandos, parece que emacs 25 no está utilizando find-file
cuando lo llama desde la línea de comandos y no sé cómo depurar este tipo de cosas
Hablas sobre pegar para abrir un archivo (supongo que te refieres a un mensaje de búsqueda de archivos dentro de emacs) y también hacer algo desde la línea de comandos. Si desea copiar y pegar, entonces debe hacer algo como lo que mostró Iván con el defadvice. Si quieres algo de la línea de comandos puedes hacer lo siguiente. Lo he adaptado de algo que hice hace un año con un controlador de URI emacs: // (para usar desde Firefox):
Pon esto en tu archivo .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))))
y luego cree un script de shell en su ruta (yo llamé al mío ''emacsat''):
#!/bin/bash
emacsclient --no-wait -e "(emacs-uri-handler /"emacs://$1/${2:-1}/")"
Una secuencia de comandos de DOS se vería similar, pero no sé cómo hacer los valores predeterminados (aunque estoy bastante seguro de que puede hacerlo).
Consulte ¿Cómo configurar Firefox para ejecutar emacsclientw en ciertos enlaces? para más instrucciones si quieres integrarte con Firefox, también.
He modificado el dispositivo de defadvice
ivan- defadvice
para que funcione con 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)))))))
Hice una pequeña reescritura de la función find-file-at-point
.
Si hay una coincidencia de número de línea, el archivo se abrirá dentro de otra ventana y el cursor se colocará en esta línea. Si no coincide el número de línea, haga lo que ffap normalmente hace ...
;; 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))))))
Si tiene una versión anterior de ffap (2008), debe actualizar sus emacs o aplicar otro parche pequeño ...
--- 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
Otra versión del buen consejo de búsqueda y archivo de Ivan Andrus que incluye ambas líneas + número de columna opcional, como se ve en los errores de nodo y código de 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)))))))
Para devolver el código de 42, se agregó el soporte para el número de columna y se limpió el caso donde el número de columna está presente y se busca el número de línea.
;; 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))))))
Puedes hacerlo usando emacsclient. Por ejemplo, para abrir ARCHIVO en la línea 4, columna 3 en un nuevo marco:
emacsclient +4:3 FILE
Deje fuera de :3
para abrir simplemente el archivo en la línea 4.
Puedes usar un script de bash:
#! /bin/bash
file=$(awk ''{sub(/:[0-9]*$/,"")}1'' <<< "$1")
line=$(awk ''{sub(/^.*:/,"")}1'' <<< "$1")
emacs --no-splash "+$line" "$file" &
Si llama a este script para línea openline
y recibe un mensaje de error, por ejemplo,
Error: file.cpp:1046
tu puedes hacer
openline file.cpp:1046
para abrir el file.cpp
en Emacs
en la línea 1046 ..
Sugiero agregar el siguiente código en su configuración de 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))
)
ahora puede abrir el archivo con un número de línea directamente desde la línea de comando como este:
emacsclient filename:linenumber:position
PD: Espero no llegar demasiado tarde con mi respuesta.
Tengo lo siguiente en mi .emacs
, pero no lo he encontrado tan útil como pensé que sería.
;; 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))))))
Y aquí está mi ir en ello. Llama al archivo de encontrar original en el punto
(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)))