aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/ffap.el74
-rw-r--r--test/lisp/ffap-tests.el22
3 files changed, 77 insertions, 25 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 5457ed3c4d4..b3c2287589a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2249,6 +2249,12 @@ useful when you want the face attributes to be absolute and not
2249'unspecified'. 2249'unspecified'.
2250 2250
2251--- 2251---
2252*** New user option 'ffap-prefer-remote-file'.
2253If non-nil, ffap always finds remote files in buffers with remote
2254'default-directory'. If nil, ffap finds local files first for absolute
2255filenames in above buffers. The default is nil.
2256
2257---
2252** Flymake 2258** Flymake
2253 2259
2254*** Windows without fringes now automatically use margin indicators. 2260*** Windows without fringes now automatically use margin indicators.
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 10afcd9514a..64c2c780672 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -199,6 +199,16 @@ Sensible values are nil, \"news\", or \"mailto\"."
199 ) 199 )
200 :group 'ffap) 200 :group 'ffap)
201 201
202(defcustom ffap-prefer-remote-file nil
203 "Whether to prefer remote files in remote context.
204If non-nil, ffap always finds remote files in buffers with remote
205`default-directory'. If nil, ffap finds local files first for absolute
206filenames in above buffers. Relative filenames are not affected by this
207option."
208 :type 'boolean
209 :group 'ffap
210 :version "31.1")
211
202(defvar ffap-max-region-length 1024 212(defvar ffap-max-region-length 1024
203 "Maximum active region length. 213 "Maximum active region length.
204When the region is active and larger than this value, 214When the region is active and larger than this value,
@@ -488,7 +498,7 @@ Returned values:
488(defvar ffap-compression-suffixes '(".gz" ".Z") ; .z is mostly dead 498(defvar ffap-compression-suffixes '(".gz" ".Z") ; .z is mostly dead
489 "List of suffixes tried by `ffap-file-exists-string'.") 499 "List of suffixes tried by `ffap-file-exists-string'.")
490 500
491(defun ffap-file-exists-string (file &optional nomodify) 501(defun ffap-file-exists-string (file &optional nomodify remote-host)
492 ;; Early jka-compr versions modified file-exists-p to return the 502 ;; Early jka-compr versions modified file-exists-p to return the
493 ;; filename, maybe modified by adding a suffix like ".gz". That 503 ;; filename, maybe modified by adding a suffix like ".gz". That
494 ;; broke the interface of file-exists-p, so it was later dropped. 504 ;; broke the interface of file-exists-p, so it was later dropped.
@@ -496,23 +506,33 @@ Returned values:
496 "Return FILE (maybe modified) if the file exists, else nil. 506 "Return FILE (maybe modified) if the file exists, else nil.
497When using jka-compr (a.k.a. `auto-compression-mode'), the returned 507When using jka-compr (a.k.a. `auto-compression-mode'), the returned
498name may have a suffix added from `ffap-compression-suffixes'. 508name may have a suffix added from `ffap-compression-suffixes'.
499The optional NOMODIFY argument suppresses the extra search." 509The optional NOMODIFY argument suppresses the extra search.
500 (cond 510
501 ((or (not file) ; quietly reject nil 511The optional argument REMOTE-HOST, if non-nil, should be a string
502 (zerop (length file))) ; and also "" 512returned by `file-remote-p'. If it is non-nil and FILE is absolute,
503 nil) 513check whether FILE exists on REMOTE-HOST. The returned name uses
504 ((file-exists-p file) file) ; try unmodified first 514REMOTE-HOST as the prefix if the file exists."
505 ;; three reasons to suppress search: 515 (let ((non-essential t))
506 (nomodify nil) 516 (cond
507 ((not (rassq 'jka-compr-handler file-name-handler-alist)) nil) 517 ((or (not file) ; quietly reject nil
508 ((member (file-name-extension file t) ffap-compression-suffixes) nil) 518 (zerop (length file))) ; and also ""
509 (t ; ok, do the search 519 nil)
510 (let ((list ffap-compression-suffixes) try ret) 520 ((and remote-host ; prepend remote host to file
511 (while list 521 (file-name-absolute-p file)
512 (if (file-exists-p (setq try (concat file (car list)))) 522 (setq file (concat remote-host file))
513 (setq ret try list nil) 523 nil))
514 (setq list (cdr list)))) 524 ((file-exists-p file) file)
515 ret)))) 525 ;; three reasons to suppress search:
526 (nomodify nil)
527 ((not (rassq 'jka-compr-handler file-name-handler-alist)) nil)
528 ((member (file-name-extension file t) ffap-compression-suffixes) nil)
529 (t ; ok, do the search
530 (let ((list ffap-compression-suffixes) try ret)
531 (while list
532 (if (file-exists-p (setq try (concat file (car list))))
533 (setq ret try list nil)
534 (setq list (cdr list))))
535 ret)))))
516 536
517(defun ffap-file-remote-p (filename) 537(defun ffap-file-remote-p (filename)
518 "If FILENAME looks remote, return it (maybe slightly improved)." 538 "If FILENAME looks remote, return it (maybe slightly improved)."
@@ -1465,6 +1485,8 @@ which may actually result in an URL rather than a filename."
1465 string)) 1485 string))
1466 (abs (file-name-absolute-p name)) 1486 (abs (file-name-absolute-p name))
1467 (default-directory default-directory) 1487 (default-directory default-directory)
1488 (remote-p (and ffap-prefer-remote-file
1489 (file-remote-p default-directory)))
1468 (oname name)) 1490 (oname name))
1469 (unwind-protect 1491 (unwind-protect
1470 (cond 1492 (cond
@@ -1484,10 +1506,11 @@ which may actually result in an URL rather than a filename."
1484 ;; Accept remote names without actual checking (too slow): 1506 ;; Accept remote names without actual checking (too slow):
1485 ((and abs (ffap-file-remote-p name))) 1507 ((and abs (ffap-file-remote-p name)))
1486 ;; Ok, not remote, try the existence test even if it is absolute: 1508 ;; Ok, not remote, try the existence test even if it is absolute:
1487 ((and abs (ffap-file-exists-string name))) 1509 ((and abs (ffap-file-exists-string name nil remote-p)))
1488 ;; Try stripping off line numbers. 1510 ;; Try stripping off line numbers.
1489 ((and abs (string-match ":[0-9]" name) 1511 ((and abs (string-match ":[0-9]" name)
1490 (ffap-file-exists-string (substring name 0 (match-beginning 0))))) 1512 (ffap-file-exists-string (substring name 0 (match-beginning 0))
1513 nil remote-p)))
1491 ;; If it contains a colon, get rid of it (and return if exists) 1514 ;; If it contains a colon, get rid of it (and return if exists)
1492 ((and (string-match path-separator name) 1515 ((and (string-match path-separator name)
1493 (let ((this-name (ffap-string-at-point 'nocolon))) 1516 (let ((this-name (ffap-string-at-point 'nocolon)))
@@ -1495,7 +1518,7 @@ which may actually result in an URL rather than a filename."
1495 ;; the empty string. 1518 ;; the empty string.
1496 (when (> (length this-name) 0) 1519 (when (> (length this-name) 0)
1497 (setq name this-name) 1520 (setq name this-name)
1498 (ffap-file-exists-string name))))) 1521 (ffap-file-exists-string name nil remote-p)))))
1499 ;; File does not exist, try the alist: 1522 ;; File does not exist, try the alist:
1500 ((let ((alist ffap-alist) tem try case-fold-search) 1523 ((let ((alist ffap-alist) tem try case-fold-search)
1501 (while (and alist (not try)) 1524 (while (and alist (not try))
@@ -1510,7 +1533,7 @@ which may actually result in an URL rather than a filename."
1510 (setq try (or 1533 (setq try (or
1511 (ffap-url-p try) ; not a file! 1534 (ffap-url-p try) ; not a file!
1512 (ffap-file-remote-p try) 1535 (ffap-file-remote-p try)
1513 (ffap-file-exists-string try)))))) 1536 (ffap-file-exists-string try nil remote-p))))))
1514 try)) 1537 try))
1515 ;; Try adding a leading "/" (common omission in ftp file names). 1538 ;; Try adding a leading "/" (common omission in ftp file names).
1516 ;; Note that this uses oname, which still has any colon part. 1539 ;; Note that this uses oname, which still has any colon part.
@@ -1543,17 +1566,18 @@ which may actually result in an URL rather than a filename."
1543 (string-match ffap-dired-wildcards name) 1566 (string-match ffap-dired-wildcards name)
1544 abs 1567 abs
1545 (ffap-file-exists-string (file-name-directory 1568 (ffap-file-exists-string (file-name-directory
1546 (directory-file-name name))) 1569 (directory-file-name name))
1570 nil remote-p)
1547 name)) 1571 name))
1548 ;; Try all parent directories by deleting the trailing directory 1572 ;; Try all parent directories by deleting the trailing directory
1549 ;; name until existing directory is found or name stops changing 1573 ;; name until existing directory is found or name stops changing
1550 ((let ((dir name)) 1574 ((let ((dir name))
1551 (while (and dir 1575 (while (and dir
1552 (not (ffap-file-exists-string dir)) 1576 (not (ffap-file-exists-string dir nil remote-p))
1553 (not (equal dir (setq dir (file-name-directory 1577 (not (equal dir (setq dir (file-name-directory
1554 (directory-file-name dir))))))) 1578 (directory-file-name dir)))))))
1555 (and (not (string= dir "/")) 1579 (and (not (string= dir "/"))
1556 (ffap-file-exists-string dir)))) 1580 (ffap-file-exists-string dir nil remote-p))))
1557 ) 1581 )
1558 (set-match-data data)))) 1582 (set-match-data data))))
1559 1583
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index ea5e745bfaf..2bf5d8c79cd 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -25,6 +25,7 @@
25 25
26(require 'cl-lib) 26(require 'cl-lib)
27(require 'ert) 27(require 'ert)
28(require 'tramp)
28(require 'ert-x) 29(require 'ert-x)
29(require 'ffap) 30(require 'ffap)
30 31
@@ -289,6 +290,27 @@ End of search list.
289 (should (member (expand-file-name "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include") 290 (should (member (expand-file-name "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include")
290 (ffap--c-path))))) 291 (ffap--c-path)))))
291 292
293(ert-deftest ffap-test-remote ()
294 (skip-unless
295 (ignore-errors
296 (and
297 (file-remote-p ert-remote-temporary-file-directory)
298 (file-directory-p ert-remote-temporary-file-directory)
299 (file-writable-p ert-remote-temporary-file-directory))))
300 (let* ((ffap-prefer-remote-file t)
301 (default-directory
302 (expand-file-name ert-remote-temporary-file-directory))
303 (test-file (expand-file-name "ffap-test" default-directory)))
304 (with-temp-buffer
305 (ignore-errors (make-empty-file test-file))
306 (insert (file-local-name test-file))
307 (should (equal (ffap-file-at-point) test-file))
308 (erase-buffer)
309 (insert (concat "/usr/bin:" (file-local-name test-file)))
310 (should (equal (ffap-file-at-point) test-file))
311 (delete-file test-file)
312 (should (equal (ffap-file-at-point) default-directory)))))
313
292(provide 'ffap-tests) 314(provide 'ffap-tests)
293 315
294;;; ffap-tests.el ends here 316;;; ffap-tests.el ends here