Comment désactiver ffap (rechercher le fichier au point) lorsque les deux premiers caractères non-espace d'une ligne sont '//'?

8

Dans Verilog / C / C ++, les commentaires peuvent commencer par //.

Voici un exemple de commentaire, //This is a comment

J'aime utiliser la fonction find-file-at-point . Si mon curseur se trouve sur le nom du fichier dans `include "some_file.v".

Mais si mon curseur se trouve sur l'exemple de commentaire ci-dessus et si je frappe C-x C-f, emacs essaie d'ouvrir un chemin provisoire //This!

Comment empêcher sélectivement l' activation de find-file-at-point ? Dans ce cas, lorsque le mode principal est verilog-mode, comment ne PAS faire find-file-at-pointlorsque mon curseur est sur une ligne où se trouvent les 2 premiers caractères non-espace //?

Kaushal Modi
la source
Je ne comprends pas tout à fait votre usecase ... Est-ce que vous remappez C-x C-fà ffapou à une enveloppe autour ffap?
T. Verron
Vérifiez la fonction mappée pour votre C-x C-f(par C-h kRET C-x C-f). Il devrait dire qu'il "exécute la commande" find-file.
caisah
Je ne peux pas reproduire cela sur mes 24.3.1 GNU Emacs. Peut-être que ce bug (comme le note @Sigma) a déjà été résolu?
remvee
2
@remvee La find-file-at-pointfonctionnalité est désactivée par défaut. Je l'ai activé via ido. J'ai (setq ido-use-filename-at-point 'guess)dans ma config.
Kaushal Modi

Réponses:

9

C'est un peu décevant, car il y ffap.ela du code qui devrait faire exactement cela:

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

Mais malheureusement, cela dépend de la présence d'un espace après le séparateur de commentaires.

C'est également très décevant, car les marqueurs de commentaires ne doivent jamais faire partie d'une chaîne au point. Voici donc une version corrigée ffap-string-at-pointqui essaie d'ignorer systématiquement ces marqueurs

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

Par effet secondaire, il résout votre problème, mais c'est beaucoup plus général. Je me demande si un tel correctif devrait être intégré en amont.

Sigma
la source
Ajouté le (require 'ffap). J'ai réalisé que ce correctif n'était pas efficace dans emacs init car il est ffapprobablement chargé automatiquement .. ce qui ne se produit que lorsque je le fais interactivementfind-file
Kaushal Modi
J'accueillerais volontiers un correctif en amont.
wasamasa
2
@wasamasa Fait: git.savannah.gnu.org/cgit/emacs.git/commit/…
Kaushal Modi
4

Merci à la solution proposée par @Sigma . J'avais cette solution dans ma config depuis plus de 2 ans, et j'ai finalement envoyé ça comme un patch à emacs en amont.

Valider dans emacs master: e472cfe8


Voici ce que fait le 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)
Kaushal Modi
la source
2

Je pense que le piratage find-file-at-pointest facile, vous pouvez utiliser defadvicesur find-file-at-point.

Le point clé est de détecter si le curseur se trouve dans un commentaire. J'ai eu un problème similaire lors du développement evil-nerd-commenter. Voici la fonction que vous pouvez réutiliser. L'astuce consiste à détecter la police actuelle.

(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))))
chen bin
la source
0

Je sais que cela ne répond pas exactement à ce que le PO a demandé, mais un moyen simple pour que ffap fasse ce que vous voulez est de lui donner juste un petit conseil.

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

Edit: correction d'une citation lambda incorrecte (# '=> juste') Je comprends que les emacsen modernes préfèrent '# mais ceux qui ne le préfèrent pas, ne le comprennent pas.

Pour moi, cela a fonctionné. J'ai vraiment apprécié les idées de Kaushal Modi, Sigma, Chen bin et Giles.

J'utilise des chaînes étendues de //// pour briser la page, et je suis souvent dans l'en-tête lorsque j'essaie de trouver le répertoire actuel ou un fichier. Je sais que ce conseil ne servira pas à tous; Je l'ai mis ici parce qu'une recherche sur ffap m'a amené ici. D'autres pourraient avoir des conseils personnels différents pour assurer la fonction. Sur la base de ce que j'ai lu ici, j'ai écrit le code ci-dessus.

J'utilise Emacs depuis 1984 et certaines des nouvelles fonctionnalités n'apparaissent sur mon radar que lorsque je vois du code. Je recommande la section Info sur les conseils. Ou dans emacs (Info-goto-node "(elisp)Advising Functions").

ElderDelp
la source