Ответ 1
Вы можете сделать это, используя emacsclient. например для открытия FILE в строке 4, столбец 3 в новом кадре:
emacsclient +4:3 FILE
Оставьте значение :3
, чтобы просто открыть файл в строке 4.
Очень часто ошибки компиляции отображаются с синтаксисом file:line
.
Было бы неплохо скопировать-вставить это прямо, чтобы открыть файл в правой строке.
У Emacs уже есть некоторый режим для обработки этого в буферах (compile-mode, iirc), но я хотел бы, чтобы это было доступно из командной строки оболочки, поскольку я использую стандартную оболочку большую часть времени за пределами emacs.
Любая идея, как настроить emacs, чтобы узнать синтаксис file:line
, чтобы открыть file
в строке line
? (очевидно, если file:line
действительно существует на диске, его следует открывать предпочтительно)
Вы можете сделать это, используя emacsclient. например для открытия FILE в строке 4, столбец 3 в новом кадре:
emacsclient +4:3 FILE
Оставьте значение :3
, чтобы просто открыть файл в строке 4.
У меня есть следующее в моем .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))))))
И вот мой ход. Вызывает исходный файл 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)))
Еще одна версия приветственного совета Ивана Андруса, в котором указывается номер строки + необязательный номер столбца, как вы видите в node и ошибках 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)))))))
Вы можете использовать bash script:
#! /bin/bash
file=$(awk '{sub(/:[0-9]*$/,"")}1' <<< "$1")
line=$(awk '{sub(/^.*:/,"")}1' <<< "$1")
emacs --no-splash "+$line" "$file" &
Если вы вызываете этот script для openline
и получаете сообщение об ошибке, например
Error: file.cpp:1046
вы можете сделать
openline file.cpp:1046
чтобы открыть file.cpp
в Emacs
в строке 1046..
Я предлагаю добавить следующий код в конфигурацию 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. Надеюсь, я не опоздал с ответом.
Вы говорите о вставке, чтобы открыть файл (я предполагаю, что вы имеете в виду подсказку файла find внутри emacs), а также что-то делать из командной строки. Если вы хотите скопировать и вставить, вам нужно сделать что-то вроде того, что показал Иван с дефисом. Если вы хотите что-то из командной строки, вы можете сделать следующее. Я адаптировал это из того, что я сделал год назад, с обработчиком emacs://URI (для использования из Firefox):
Поместите это в файл .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))))
а затем создайте оболочку script на вашем пути (я назвал my 'emacsat):
#!/bin/bash
emacsclient --no-wait -e "(emacs-uri-handler \"emacs://$1/${2:-1}\")"
Пакет DOS script будет похож, но я не знаю, как делать значения по умолчанию (хотя я уверен, что вы можете это сделать).
См. Как настроить firefox для запуска emacsclientw по определенным ссылкам? для получения дополнительных инструкций, если вы хотите интегрироваться с Firefox.
Emacs 25 больше не использует defadvice
. Refs:.
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
, когда вы вызываете его из командной строки, и я не знаю как отлаживать подобные вещи.
Я немного переписал функцию find-file-at-point
.
Если соответствует номер строки, файл будет открыт в другом окне, и курсор будет помещен в эту строку. Если номер строки не соответствует, выполните то, что обычно делает 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 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
Вот функция zsh, которая работает, если вы поместите ее в свой .zshrc
файл.
Так как я обычно запускаю свой код в zsh, и вот где я вижу ошибки. Престижность @sanityinc для части emacs. Просто подумал, что это должно быть в google.
emn () {
blah=$1
filen=(${(s.:.)blah})
/Applications/Emacs.app/Contents/MacOS/Emacs +$filen[2] $filen[1] &
}
Используйте как emn /long/stack/error.rb:123
Я изменил ivan-andrus 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)))))))
Код return42, добавленная поддержка номера столбца и очищенный регистр, где присутствует номер столбца, и номер строки запрашивается.
;; 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-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))))))