行の最初の2つの非スペース文字が「//」である場合、ffap(ポイントでファイルを検索)を無効にするにはどうすればよいですか?


8

Verilog / C / C ++では、コメントはで始めることができます//

これはコメントの例です、 //This is a comment

find-file-at-point機能を使用したい。カーソルがのファイル名にある場合`include "some_file.v"

しかし、カーソルが上の例のコメントの上にあり、ヒットした場合C-x C-f、emacsは仮のパスを開こうとします//This

find-file-at-pointがアクティブになるのを選択的に防ぐにどうすればよいですか?この場合、メジャーモードがのときに、カーソルが最初の2つの非スペース文字がある行にある場合verilog-mode、どうすればよいですか?find-file-at-point//


私はあなたのユースケースを完全に理解していません...あなたは周りのラッパーにリマップC-x C-fffapましたffapか?
T.バーロン2014

マッピングされた関数を確認しますC-x C-fC-h kRET によってC-x C-f)。「コマンドを実行する」と表示されfind-fileます。
caisah

私の24.3.1 GNU Emacsではこれを再現できません。(@Sigmaのように)このバグはすでに解決されているのでしょうか?
2014

2
@remveeこのfind-file-at-point機能はデフォルトで無効になっています。で有効にしていidoます。私は(setq ido-use-filename-at-point 'guess)私の設定にあります。
Kaushal Modi 2014

回答:


9

これは、ビットdisppointingあるffap.elいくつかのコードがあるはずですちょうどそれをします:

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

しかし、残念ながら、それはコメントセパレータの後にスペースがあることに依存しています。

コメントマーカーを文字列アットポイントの一部にすることはできませんので、これも非常に残念です。だからここにffap-string-at-pointそれらのマーカーを体系的に無視しようとするパッチを当てたバージョンがあります

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

副作用により、問題は修正されますが、より一般的です。そのような修正を上流に統合する必要があるかどうか疑問に思っています。


を追加しました(require 'ffap)ffapおそらく自動ロードされるため、このパッチはemacs initで効果的ではなかったことに気づきました。対話的に実行するまで、この問題は発生しませんfind-file
Kaushal Modi

上流の修正を歓迎します。
ワサマサ2014年


4

@Sigmaによって投稿されソリューションに感謝します。私は2年以上私の構成でそのソリューションを持っていて、最終的にそれをパッチとしてemacsアップストリームに送信しました。

emacsマスターでコミット:e472cfe8


これはパッチが効果的に行うことです:

(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

私はハッキングが思うfind-file-at-pointあなたが使用できる、簡単であるdefadvicefind-file-at-point

重要なのは、カーソルがコメント内にあるかどうかを検出することです。開発中にも同様の問題がありましたevil-nerd-commenter。こちらが再利用できる機能です。トリックは、現在のフォントフェースを検出することです。

(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

これは、OPが要求した内容に正確に対応しているわけではないことを知っていますが、やりたいことを実行するための簡単な方法は、少しだけアドバイスを与えることです。

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

編集:誤ったラムダ引用を修正(# '=>ただ')私は現代のemacsenが '#を好むが、それを好まないものは理解しないことを理解しています。

私にとっては、これでうまくいきました。Kaushal Modi、Sigma、Chen bin、Gilesの洞察に本当に感謝しました。

////の拡張文字列を使用してページを分割します。現在のディレクトリまたはその中のファイルを検索しようとすると、ヘッダーに頻繁にアクセスします。私はこのアドバイスがすべてに役立つわけではないことを知っています。ffapの検索でここに来たので、ここに配置しました。他の人は、機能を提供するために別の個人的なアドバイスがあるかもしれません。ここで読んだ内容に基づいて、上記のコードを書きました。

私は1984年からEmacsを使用していますが、いくつかの新機能は、コードを見るまでレーダーに表示されません。私はお勧め情報アドバイスのセクションを。 またはemacsで(Info-goto-node "(elisp)Advising Functions")

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.