2010-06-29 11 views
48

Sehr oft, Kompilierungsfehler werden mit der Syntax angezeigt.Öffnen Sie eine Datei in Zeile mit "Dateiname: Zeile" Syntax

Es wäre schön, dies direkt zu kopieren, um die Datei in der richtigen Zeile zu öffnen.

Emacs hat bereits einen Modus, um dies in Puffern zu handhaben (Kompiliermodus, IIRC), aber ich möchte dies über die Shell-Befehlszeile verfügbar haben, da ich die Standard-Shell die meiste Zeit außerhalb von Emacs verwende.

Irgendeine Idee, wie man Emacs zwickt, um file:line Syntax zu lernen, um file an der Linie line zu öffnen? (natürlich, wennwirklich existiert auf der Festplatte, sollte es vorzugsweise geöffnet werden)

+0

Ich möchte eine Möglichkeit sehen, eine Datei zu öffnen, die Emacs einen PHP-Fehler übergibt. Das würde so aussehen: Warnung: Ungültiges Argument für foreach() in _drupal_schema_initialize() (Zeile 6866 von /srv/work.electricgroups.com/dave/projects/htdocs/includes/common.inc). –

+4

Möchten Sie eine Antwort auswählen? – sanityinc

Antwort

40

Sie können dies mit Emacsclient tun. z.B. FILE in Zeile 4 zu öffnen, Spalte 3 in einem neuen Rahmen:

emacsclient +4:3 FILE 

die :3 einfach wegzulassen, um die Datei in Zeile zu öffnen 4.

+5

Das Flag "-c" zeigt an, dass ein neuer Frame erstellt werden soll. Sie müssen das nicht angeben, damit das Springen zur Linie funktioniert. – Damyan

+0

Guter Punkt - das war eine Frage der persönlichen Präferenz/Gewohnheit. – sanityinc

+1

Während dies eine interessante Tatsache ist, ist die Lösung von Ivan viel funktionaler, wenn Sie Dateinamen aus Fehlermeldungen ausschneiden und einfügen, wie die ursprüngliche Frage sagt – simpleuser

13

ich in meinem .emacs die folgenden, aber ich haven‘ Ich fand es so nützlich wie ich dachte.

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

nett! irgendeine Idee, wie man das in der Standardöffnungsfunktion anbringt? – elmarco

+0

Ich bin mir nicht sicher, was du meinst. find-file _ist_ die Standardfunktion zum Öffnen. Was zeigt C-h C-k C-x C-f? –

+2

"defadvice" ändert die Definition des nächsten Namens (in diesem Fall find-file, die Standardfunktion zum Öffnen). Also ändert diese (defadvice find-file ...) die find-Datei, um sich so zu verhalten. – jackr

3

Sie sprechen über das Einfügen einer Datei zu öffnen (ich nehme meinen Sie an einer Datei suchen prompt innerhalb von Emacs) und auch von der Kommandozeile, etwas zu tun. Wenn Sie & Paste kopieren möchten, dann müssen Sie etwas tun, was Ivan mit dem Defadvice zeigte. Wenn Sie etwas von der Befehlszeile möchten, können Sie Folgendes tun. Ich habe dies von etwas angepasst ich mit einem Emacs vor einem Jahr: // URI-Handler (für den Einsatz innerhalb von Firefox):

Setzen Sie diese in Ihrer .emacs-Datei:

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

und erstellen ein Shell-Skript in Ihrem Pfad (I genannt mine ‚emacsat‘):

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

eine DOS-Batch-Skript ähnlich aussehen würde, aber ich weiß nicht, wie die Standardwerte zu tun (obwohl ich ziemlich sicher bin, können Sie TU es).

Weitere Anweisungen finden Sie unter How to configure firefox to run emacsclientw on certain links?, wenn Sie auch in Firefox integrieren möchten.

+0

zu machen. Ja, obwohl es sich auf die Shell ein bisschen zu viel verlässt (ich könnte schreibe wahrscheinlich ein Skript, um die Datei zu bearbeiten: keine Syntax, das ist eine Idee) – elmarco

1

Ich habe die find-file-at-point Funktion etwas umgeschrieben.

Wenn es eine Übereinstimmung der Zeilennummer gibt, wird die Datei in einem anderen Fenster geöffnet, und der Cursor wird in diese Zeile eingefügt. Wenn keine Zeilennummer Spiel, das tun, was normalerweise der Fall ist 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'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)))))) 

Wenn Sie eine alte Version des FFAP (2008) Sie Emacs aktualisieren sollte oder eine andere kleine Patch anwenden ...

--- 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 
9

Und hier ist mein Ziel.Ruft die Originalfund-Datei-at-Punkt

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

Arbeitete für mich! Vielen Dank! – dolzenko

+0

Ich würde nur ändern (find-file-at-point) zu (find-file (ffap-güßer)). Dann bekommst du keine Aufforderung :) – teaforthecat

+1

@jacob Hat bei mir nicht funktioniert, es öffnet sich eine Pufferdatei.ext: 34. – Jaseem

7

Eine andere Version von Ivan Andrus' nice find-Datei Beratung, die sowohl Linie tut + optional Spaltennummer, wie Sie in Knoten und Coffeescript Fehler sehen:

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

Super, funktioniert super! –

+0

gibt es eine Möglichkeit, dies für die zweite und spätere Dateien in der Befehlszeile beim Starten von Emacs funktionieren? – simpleuser

0

Um den Code von return42 zurückzugeben, wurde die Unterstützung für die Spaltennummer hinzugefügt und der Fall bereinigt, in dem die Spaltennummer vorhanden ist und die Zeilennummer gesucht wird.

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

Hier ist eine Funktion, die zsh, wenn Sie ihn in Ihre .zshrc Datei funktioniert.

Da ich meinen Code in zsh normalerweise ausführen, und das ist, wo ich die Fehler sehe. Kudos zu @sanityinc für den Emacs-Teil. Dachte nur, das sollte bei Google sein.


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

Verwenden wie emn /long/stack/error.rb:123

8

Sie ein Bash-Skript verwenden:

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

Wenn Sie dieses Skript aufrufen für openline und Sie erhalten eine Fehlermeldung, z.B.

Error: file.cpp:1046 

Sie tun können,

openline file.cpp:1046 

die file.cpp in Emacs in Zeile 1046 zu öffnen ..

+0

Danke !, Das hat mir geholfen !. Ich benutze eine leicht modifizierte Version: 'emacs --no-splash" + $ line "--file" $ file "' – nacho4d

7

Ich schlage vor, folgenden Code in Ihrer Emacs Config hinzuzufügen:

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

Jetzt können Sie die Datei mit einer Zeilennummer direkt von der Befehlszeile aus öffnen:

emacsclient filename:linenumber:position 

P.S. Ich hoffe, ich bin nicht zu spät mit meiner Antwort.

+2

Es ist nie zu spät für eine nützliche Antwort. – phils

+0

scheint nicht für mich zu arbeiten :( – elmarco

+0

elmarco: Getestet und arbeitet in Emacs 24.3, FWIW. – phils

1

Ich habe modifizierte ivan-Andrus defadvice so funktioniert es mit 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))))))) 
2

Emacs 25 defadvice nicht mehr nicht verwendet. Refs .:

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

So, hier ist die Version auf die neue Syntax aktualisiert:

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

Dies funktioniert, wenn Sie offene Datei aufrufen von innen Emacs (Cx Cf), aber keine Werke mehr aus Es scheint, dass Emacs 25 nicht find-file verwendet, wenn Sie es von der Befehlszeile aus aufrufen und ich weiß nicht, wie Sie diese Art von Debuggen.

Verwandte Themen