Làm cách nào để tắt ffap (tìm tệp tại điểm) khi hai ký tự không phải dấu cách đầu tiên trong một dòng là '//'?


8

Trong Verilog / C / C ++, các bình luận có thể bắt đầu bằng //.

Đây là một ví dụ bình luận, //This is a comment

Tôi thích sử dụng tính năng find-file-at-point . Nếu con trỏ của tôi nằm trên tên tập tin `include "some_file.v".

Nhưng nếu con trỏ của tôi ở trên nhận xét ví dụ trên và nếu tôi nhấn C-x C-f, emacs sẽ cố gắng mở một đường dẫn dự kiến //This!

Làm cách nào để tôi chọn lọc ngăn chặn find-file-at-point kích hoạt? Trong trường hợp này, khi chế độ chính là verilog-mode, làm thế nào để tôi KHÔNG làm gì find-file-at-pointkhi con trỏ của tôi nằm trên một dòng có 2 ký tự không phải dấu cách đầu tiên //?


Tôi hoàn toàn không hiểu usecase của bạn ... Bạn có remap C-x C-fđể ffaphoặc một wrapper xung quanh ffap?
T. Verron

Kiểm tra chức năng được ánh xạ cho C-x C-f(của C-h kRET C-x C-f). Nó sẽ nói nó "chạy lệnh" find-file.
caisah

Tôi không thể sao chép điều này trên GNU Emacs 24.3.1. Có lẽ lỗi này (như ghi chú @Sigma) đã được giải quyết?
thiệu

2
@remvee find-file-at-pointTính năng này bị tắt theo mặc định. Tôi đã kích hoạt nó thông qua ido. Tôi có (setq ido-use-filename-at-point 'guess)trong cấu hình của tôi.
Kaushal Modi

Câu trả lời:


9

Đây là một chút thất vọng, bởi vì ffap.elcó một số mã nên làm điều đó:

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

Nhưng thật không may, nó dựa vào việc có một khoảng trắng sau dấu phân cách nhận xét.

Điều này cũng rất đáng thất vọng, bởi vì các đánh dấu nhận xét không bao giờ là một phần của bất kỳ chuỗi điểm nào. Vì vậy, đây là phiên bản vá lỗi ffap-string-at-pointcố gắng bỏ qua một cách có hệ thống các điểm đánh dấu đó

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

Do tác dụng phụ, nó khắc phục vấn đề của bạn, nhưng nó chung chung hơn nhiều. Tôi tự hỏi nếu một sửa chữa như vậy nên được tích hợp ngược dòng.


Đã thêm (require 'ffap). Tôi nhận ra bản vá này không hiệu quả trong init emac vì ffapcó thể được tải tự động .. điều đó không xảy ra cho đến khi tôi tương tác làmfind-file
Kaushal Modi

Tôi sẽ hoan nghênh một sửa chữa ngược dòng.
wasamasa


4

Nhờ giải pháp được đăng bởi @Sigma . Tôi đã có giải pháp đó trong cấu hình của mình trong hơn 2 năm, và cuối cùng đã gửi nó như một bản vá để emacs ngược dòng.

Cam kết trong chủ nhân của emacs: e472cfe8


Đây là những gì bản vá có hiệu quả:

(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

Tôi nghĩ rằng hack find-file-at-pointlà dễ dàng, bạn có thể sử dụng defadvicetrên find-file-at-point.

Điểm chính là phát hiện xem con trỏ có trong một bình luận hay không. Tôi đã có một vấn đề tương tự khi phát triển evil-nerd-commenter. Đây là chức năng bạn có thể sử dụng lại. Bí quyết là phát hiện khuôn mặt phông chữ hiện tại.

(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

Tôi biết rằng đây không phải là giải quyết chính xác những gì OP yêu cầu, nhưng một cách đơn giản để có được ffap để làm những gì bạn muốn là chỉ cho nó một lời khuyên nhỏ.

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

Chỉnh sửa: đã sửa lỗi trích dẫn lambda không chính xác (# '=> chỉ') Tôi hiểu rằng emacsen hiện đại thích '# nhưng những người không thích nó, không hiểu nó.

Đối với tôi, điều này đã làm việc. Tôi thực sự đánh giá cao những hiểu biết của Kaushal Modi, Sigma, Chen bin và Giles.

Tôi sử dụng các chuỗi mở rộng của //// để chia trang và tôi thường ở trong tiêu đề khi cố gắng tìm thư mục hiện tại hoặc tệp trong đó. Tôi biết rằng lời khuyên này sẽ không phục vụ cho tất cả mọi người; Tôi đặt nó ở đây vì một tìm kiếm trên ffap đã đưa tôi đến đây. Những người khác có thể có lời khuyên cá nhân khác nhau để cung cấp chức năng. Dựa trên những gì tôi đọc ở đây, tôi đã viết mã ở trên.

Tôi đã sử dụng Emacs từ năm 1984 và một số tính năng mới không có trên radar của tôi cho đến khi tôi thấy một số mã. Tôi đề nghị phần Thông tin về lời khuyên. Hoặc trong emacs (Info-goto-node "(elisp)Advising Functions").

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.