Подтвердить что ты не робот

Откройте файл в строке с синтаксисом "filename: line"

Очень часто ошибки компиляции отображаются с синтаксисом file:line.

Было бы неплохо скопировать-вставить это прямо, чтобы открыть файл в правой строке.

У Emacs уже есть некоторый режим для обработки этого в буферах (compile-mode, iirc), но я хотел бы, чтобы это было доступно из командной строки оболочки, поскольку я использую стандартную оболочку большую часть времени за пределами emacs.

Любая идея, как настроить emacs, чтобы узнать синтаксис file:line, чтобы открыть file в строке line? (очевидно, если file:line действительно существует на диске, его следует открывать предпочтительно)

4b9b3361

Ответ 1

Вы можете сделать это, используя emacsclient. например для открытия FILE в строке 4, столбец 3 в новом кадре:

emacsclient +4:3 FILE

Оставьте значение :3, чтобы просто открыть файл в строке 4.

Ответ 2

У меня есть следующее в моем .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))))))

Ответ 3

И вот мой ход. Вызывает исходный файл 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)))

Ответ 4

Еще одна версия приветственного совета Ивана Андруса, в котором указывается номер строки + необязательный номер столбца, как вы видите в 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)))))))

Ответ 5

Вы можете использовать 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..

Ответ 6

Я предлагаю добавить следующий код в конфигурацию 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. Надеюсь, я не опоздал с ответом.

Ответ 7

Вы говорите о вставке, чтобы открыть файл (я предполагаю, что вы имеете в виду подсказку файла 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.

Ответ 8

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, когда вы вызываете его из командной строки, и я не знаю как отлаживать подобные вещи.

Ответ 9

Я немного переписал функцию 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

Ответ 10

Вот функция 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

Ответ 11

Я изменил 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)))))))

Ответ 12

Код 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))))))