Come disabilitare ffap (trova il file al punto) quando i primi due caratteri non spaziali in una riga sono '//'?


8

In Verilog / C / C ++, i commenti possono iniziare con //.

Ecco un commento di esempio, //This is a comment

Mi piace usare la funzione find-file-at-point . Se il mio cursore si trova sul nome del file in `include "some_file.v".

Ma se il mio cursore si trova sul commento di esempio sopra e se C-x C-fpremo, emacs prova ad aprire un percorso provvisorio //This!

Come posso selettivamente impedire l' attivazione di find-file-at-point ? In questo caso, quando è la modalità principale verilog-mode, come faccio a NON fare find-file-at-pointquando il cursore si trova su una riga in cui sono i primi 2 caratteri non spaziali //?


Io non capisco il tuo caso d'uso ... hai rimappare C-x C-fa ffapo per un wrapper ffap?
T. Verron,

Controlla la funzione mappata per il tuo C-x C-f(da C-h kRET C-x C-f). Dovrebbe dire che "esegue il comando" find-file.
caisah,

Non riesco a riprodurlo sul mio Emacs GNU 24.3.1. Forse questo bug (come osserva @Sigma) è già stato risolto?
rimedi il

2
@remvee La find-file-at-pointfunzione è disabilitata per impostazione predefinita. L'ho abilitato tramite ido. Ho (setq ido-use-filename-at-point 'guess)nella mia configurazione.
Kaushal Modi,

Risposte:


9

Questo è un po 'deludente, perché ffap.elha del codice che dovrebbe fare proprio questo:

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

Ma sfortunatamente, si basa sull'esistenza di uno spazio dopo il separatore di commenti.

È anche molto deludente, perché i marcatori di commenti non dovrebbero mai far parte di nessuna stringa. Quindi, ecco una versione di patch ffap-string-at-pointche cerca di ignorare sistematicamente quei marcatori

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

Di contro effetto risolve il problema, ma è molto più generale. Mi chiedo se tale correzione dovrebbe essere integrata a monte.


Aggiunto il (require 'ffap). Mi sono reso conto che questa patch non era efficace in emacs init come ffapprobabilmente viene caricata automaticamente .. il che non accade fino a quando non lo faccio interattivamentefind-file
Kaushal Modi,

Gradirei una correzione a monte.
Wasamasa,


4

Grazie alla soluzione pubblicata da @Sigma . Ho avuto quella soluzione nella mia configurazione per più di 2 anni e alla fine l'ho inviata come patch a emacs a monte.

Commettere in emacs master: e472cfe8


Ecco cosa fa efficacemente la patch:

(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

Credo che l'hacking find-file-at-pointè facile, si può utilizzare defadvicesu find-file-at-point.

Il punto chiave è rilevare se il cursore si trova in un commento. Ho avuto un problema simile durante lo sviluppo evil-nerd-commenter. Ecco la funzione che puoi riutilizzare. Il trucco è rilevare la faccia del carattere corrente.

(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

So che questo non si rivolge esattamente a ciò che l'OP ha chiesto, ma un modo semplice per ottenere ffap per fare ciò che vuoi è dare solo un piccolo consiglio.

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

Modifica: corretta virgoletta lambda errata (# '=> solo') Capisco che i moderni emacsen preferiscono '# ma quelli che non lo preferiscono, non lo capiscono.

Per me ha funzionato. Ho davvero apprezzato le intuizioni di Kaushal Modi, Sigma, Chen bin e Giles.

Uso le stringhe estese di //// per spezzare la pagina, e spesso sono nell'intestazione quando provo a trovare la directory corrente o un file in essa. So che questo consiglio non servirà a tutti; L'ho messo qui perché una ricerca su ffap mi ha portato qui. Altri potrebbero avere diversi consigli personali per fornire la funzione. Sulla base di ciò che ho letto qui, ho scritto il codice sopra.

Uso Emacs dal 1984 e alcune delle nuove funzionalità non entrano nel mio radar fino a quando non vedo del codice. Raccomando la sezione Informazioni sui consigli. O in emacs (Info-goto-node "(elisp)Advising Functions").

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.