Wie deaktiviere ich ffap (Datei am Punkt suchen), wenn die ersten beiden Nicht-Leerzeichen in einer Zeile '//' sind?


8

In Verilog / C / C ++ können Kommentare mit beginnen //.

Hier ist ein Beispielkommentar: //This is a comment

Ich verwende gerne die Funktion " Datei am Punkt suchen" . Wenn sich mein Cursor auf dem Dateinamen in befindet `include "some_file.v".

Wenn sich mein Cursor jedoch auf dem obigen Beispielkommentar befindet und ich C-x C-fdrücke, versucht emacs, einen vorläufigen Pfad zu öffnen //This!

Wie verhindere ich selektiv, dass Find-File-at-Point aktiviert wird? verilog-modeWie kann ich in diesem Fall im Hauptmodus NICHT vorgehen, find-file-at-pointwenn sich mein Cursor in einer Zeile befindet, in der sich die ersten beiden Nicht-Leerzeichen befinden //?


Ich verstehe nicht ganz Ihr usecase ... Haben Sie neu zuordnen C-x C-fzu ffapoder auf einen Wrapper um ffap?
T. Verron

Überprüfen Sie die für Sie zugeordnete Funktion C-x C-f(per C-h kRET C-x C-f). Es sollte sagen, dass es "den Befehl ausführt" find-file.
Caisah

Ich kann dies auf meinem 24.3.1 GNU Emacs nicht reproduzieren. Vielleicht wurde dieser Fehler (wie @ Sigma bemerkt) bereits behoben?
Remvee

2
@remvee Die find-file-at-pointFunktion ist standardmäßig deaktiviert. Ich habe es über aktiviert ido. Ich habe (setq ido-use-filename-at-point 'guess)in meiner Konfiguration.
Kaushal Modi

Antworten:


9

Dies ist etwas enttäuschend, da ffap.eles einen Code gibt, der genau das tun sollte :

 ;; Immediate rejects (/ and // and /* are too common in C/C++):
     ((member name '("" "/" "//" "/*" ".")) nil)

Leider hängt es davon ab, dass nach dem Kommentartrennzeichen ein Leerzeichen steht.

Es ist auch sehr enttäuschend, da Kommentarmarkierungen niemals Teil eines String-at-Point sein sollten. Hier ist eine gepatchte Version davon ffap-string-at-point, die versucht, diese Markierungen systematisch zu ignorieren

(require 'ffap)
(defun ffap-string-at-point (&optional mode)
  (let* ((args
      (cdr
       (or (assq (or mode major-mode) ffap-string-at-point-mode-alist)
           (assq 'file ffap-string-at-point-mode-alist))))
         next-comment
     (pt (point))
     (beg (if (use-region-p)
          (region-beginning)
        (save-excursion
          (skip-chars-backward (car args))
          (skip-chars-forward (nth 1 args) pt)
                  (save-excursion
                    (setq next-comment
                          (progn (comment-search-forward (line-end-position) t)
                                 (point))))
          (point))))
     (end (if (use-region-p)
          (region-end)
        (save-excursion
          (skip-chars-forward (car args))
          (skip-chars-backward (nth 2 args) pt)
          (point)))))
  (when (> end next-comment)
    (setq beg next-comment))
  (setq ffap-string-at-point
      (buffer-substring-no-properties
       (setcar ffap-string-at-point-region beg)
       (setcar (cdr ffap-string-at-point-region) end)))))

Als Nebeneffekt behebt es Ihr Problem, aber es ist viel allgemeiner. Ich frage mich, ob ein solches Update vorgelagert werden sollte.


Hinzugefügt die (require 'ffap). Ich habe festgestellt, dass dieser Patch in Emacs Init nicht effektiv ist, da er ffapwahrscheinlich automatisch geladen wird. Dies geschieht erst, wenn ich es interaktiv machefind-file
Kaushal Modi

Ich würde einen Upstream-Fix begrüßen.
Wasamasa


4

Dank der Lösung von @Sigma . Ich hatte diese Lösung mehr als 2 Jahre in meiner Konfiguration und schickte sie schließlich als Patch an Emacs Upstream.

Commit in Emacs Master: e472cfe8


Folgendes bewirkt der Patch effektiv:

(defun modi/ffap-string-at-point (&optional mode)
  "Return a string of characters from around point.

MODE (defaults to value of `major-mode') is a symbol used to look up
string syntax parameters in `ffap-string-at-point-mode-alist'.

If MODE is not found, we use `file' instead of MODE.

If the region is active,return a string from the region.

If the point is in a comment, ensure that the returned string does not contain
the comment start characters (especially for major modes that have '//' as
comment start characters). https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24057

|-----------------------------------+---------------------------------|
| Example string in `c-mode' buffer | Returned `ffap-string-at-point' |
|-----------------------------------+---------------------------------|
| ▮//tmp                            | tmp                             |
| //▮tmp                            | tmp                             |
| ▮///tmp                           | /tmp                            |
| //▮/tmp                           | /tmp                            |
| ▮////tmp                          | //tmp                           |
| ////▮tmp                          | //tmp                           |
| ▮// //tmp                         | (empty string) \"\"             |
| // ▮/tmp                          | /tmp                            |
| // ▮//tmp                         | //tmp                           |
|-----------------------------------+---------------------------------|

Set the variables `ffap-string-at-point' and `ffap-string-at-point-region'.

When the region is active and larger than `ffap-max-region-length',
return an empty string, and set `ffap-string-at-point-region' to '(1 1)."
  (let* ((args
          (cdr
           (or (assq (or mode major-mode) ffap-string-at-point-mode-alist)
               (assq 'file ffap-string-at-point-mode-alist))))
         (region-selected (use-region-p))
         (pt (point))
         (beg (if region-selected
                  (region-beginning)
                (save-excursion
                  (skip-chars-backward (car args))
                  (skip-chars-forward (nth 1 args) pt)
                  (point))))
         (end (if region-selected
                  (region-end)
                (save-excursion
                  (skip-chars-forward (car args))
                  (skip-chars-backward (nth 2 args) pt)
                  (point))))
         (region-len (- (max beg end) (min beg end))))

    ;; If the initial characters of the to-be-returned string are the
    ;; current major mode's comment starter characters, *and* are
    ;; not part of a comment, remove those from the returned string
    ;; (Bug#24057).
    ;; Example comments in `c-mode' (which considers lines beginning
    ;; with "//" as comments):
    ;;  //tmp - This is a comment. It does not contain any path reference.
    ;;  ///tmp - This is a comment. The "/tmp" portion in that is a path.
    ;;  ////tmp - This is a comment. The "//tmp" portion in that is a path.
    (when (and
           ;; Proceed if no region is selected by the user.
           (null region-selected)
           ;; Check if END character is part of a comment.
           (save-excursion
             (nth 4 (syntax-ppss end))))
      ;; Move BEG to beginning of comment (after the comment start
      ;; characters), or END, whichever comes first.
      (save-excursion
        (let ((state (syntax-ppss beg)))
          ;; (nth 4 (syntax-ppss)) will be nil for comment start chars
          (unless (nth 4 state)
            (parse-partial-sexp beg end nil nil state :commentstop)
            (setq beg (point))))))

    (if (and (natnump ffap-max-region-length)
             (< region-len ffap-max-region-length)) ; Bug#25243.
        (setf ffap-string-at-point-region (list beg end)
              ffap-string-at-point
              (buffer-substring-no-properties beg end))
      (setf ffap-string-at-point-region (list 1 1)
            ffap-string-at-point ""))))
(advice-add 'ffap-string-at-point :override #'modi/ffap-string-at-point)

2

Ich denke, Hacking find-file-at-pointist einfach, Sie können defadviceauf verwenden find-file-at-point.

Der entscheidende Punkt ist das Erkennen, ob sich der Cursor in einem Kommentar befindet. Ich hatte ein ähnliches Problem bei der Entwicklung evil-nerd-commenter. Hier ist die Funktion, die Sie wiederverwenden können. Der Trick besteht darin, die aktuelle Schriftart zu erkennen.

(defun evilnc--in-comment-p (pos)
  (interactive)
  (let ((fontfaces (get-text-property pos 'face)))
    (when (not (listp fontfaces))
      (setf fontfaces (list fontfaces)))
    (delq nil
      (mapcar #'(lambda (f)
              ;; learn this trick from flyspell
              (or (eq f 'font-lock-comment-face)
              (eq f 'font-lock-comment-delimiter-face)))
          fontfaces))))

0

Ich weiß, dass dies nicht genau das betrifft, was das OP verlangt hat, aber eine einfache Möglichkeit, ffap dazu zu bringen, das zu tun, was Sie wollen, besteht darin, ihm nur einen kleinen Rat zu geben.

(defun delp--ffap-string-at-point-filter (s)
  "Remove long stretches of /////'s from `ffap-string-at-point' return value."
  (interactive "sTest string: ")
  (if (string-match-p "^//" s)
      ""
    s))

(advice-add 'ffap-string-at-point :filter-return 'delp--ffap-string-at-point-filter)

Bearbeiten: falsches Lambda-Zitat behoben (# '=> nur') Ich verstehe, dass moderne Emacsen '# bevorzugen, aber diejenigen, die es nicht bevorzugen, verstehen es nicht.

Für mich hat das funktioniert. Ich habe die Erkenntnisse von Kaushal Modi, Sigma, Chen bin und Giles sehr geschätzt.

Ich verwende erweiterte Zeichenfolgen von ////, um die Seite aufzuteilen, und ich bin oft im Header, wenn ich versuche, entweder das aktuelle Verzeichnis oder eine Datei darin zu finden. Ich weiß, dass dieser Rat nicht allen dienen wird; Ich habe es hierher gebracht, weil mich eine Suche auf ffap hierher gebracht hat. Andere haben möglicherweise andere persönliche Ratschläge, um die Funktion bereitzustellen. Basierend auf dem, was ich hier gelesen habe, habe ich den obigen Code geschrieben.

Ich benutze Emacs seit 1984 und einige der neuen Funktionen werden erst auf meinem Radar angezeigt, wenn ich Code sehe. Ich empfehle den Info- Bereich zur Beratung. Oder in Emacs (Info-goto-node "(elisp)Advising Functions").

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.