aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoam Postavsky2017-01-08 18:19:32 -0500
committerNoam Postavsky2017-01-15 13:04:54 -0500
commitfd6b829d91da73a945643b5916ee6d79c992e030 (patch)
tree5759b3099ad52bdf3fb80948a12973d349981b2f
parentaf3db69ee640d9a1e9027c04ba3b5bec7c2681ab (diff)
downloademacs-fd6b829d91da73a945643b5916ee6d79c992e030.tar.gz
emacs-fd6b829d91da73a945643b5916ee6d79c992e030.zip
Improve ffap-gopher-at-point handling of long lines
* lisp/ffap.el (ffap-gopher-regexp): Only match the KEY part. Note setting to nil is now supported. (ffap--gopher-var-on-line): New function. (ffap-gopher-at-point): Use it instead of the old ffap-gopher-regexp which could overflow the regexp stack on long lines (Bug#25391). Use `let-alist' instead of calling `set' on local variables. * test/lisp/ffap-tests.el (ffap-gopher-at-point): New test.
-rw-r--r--lisp/ffap.el66
-rw-r--r--test/lisp/ffap-tests.el17
2 files changed, 52 insertions, 31 deletions
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 8144d41f3a1..068897b21b8 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -76,6 +76,7 @@
76;; (setq ffap-machine-p-known 'accept) ; no pinging 76;; (setq ffap-machine-p-known 'accept) ; no pinging
77;; (setq ffap-url-regexp nil) ; disable URL features in ffap 77;; (setq ffap-url-regexp nil) ; disable URL features in ffap
78;; (setq ffap-shell-prompt-regexp nil) ; disable shell prompt stripping 78;; (setq ffap-shell-prompt-regexp nil) ; disable shell prompt stripping
79;; (setq ffap-gopher-regexp nil) ; disable gopher bookmark matching
79;; 80;;
80;; ffap uses `browse-url' (if found, else `w3-fetch') to fetch URL's. 81;; ffap uses `browse-url' (if found, else `w3-fetch') to fetch URL's.
81;; For a hairier `ffap-url-fetcher', try ffap-url.el (same ftp site). 82;; For a hairier `ffap-url-fetcher', try ffap-url.el (same ftp site).
@@ -1194,43 +1195,46 @@ Sets the variable `ffap-string-at-point-region' to the bounds of URL, if any."
1194 val)))) 1195 val))))
1195 1196
1196(defvar ffap-gopher-regexp 1197(defvar ffap-gopher-regexp
1197 "^.*\\<\\(Type\\|Name\\|Path\\|Host\\|Port\\) *= *\\(.*\\) *$" 1198 "\\<\\(Type\\|Name\\|Path\\|Host\\|Port\\) *= *"
1198 "Regexp matching a line in a gopher bookmark (maybe indented). 1199 "Regexp matching a key in a gopher bookmark.
1199The two subexpressions are the KEY and VALUE.") 1200Set to nil to disable matching gopher bookmarks.")
1201
1202(defun ffap--gopher-var-on-line ()
1203 "Return (KEY . VALUE) of gopher bookmark on current line."
1204 (save-excursion
1205 (let ((eol (progn (end-of-line) (skip-chars-backward " ") (point)))
1206 (bol (progn (beginning-of-line) (point))))
1207 (when (re-search-forward ffap-gopher-regexp eol t)
1208 (let ((key (match-string 1))
1209 (val (buffer-substring-no-properties (match-end 0) eol)))
1210 (cons (intern (downcase key)) val))))))
1200 1211
1201(defun ffap-gopher-at-point () 1212(defun ffap-gopher-at-point ()
1202 "If point is inside a gopher bookmark block, return its URL. 1213 "If point is inside a gopher bookmark block, return its URL.
1203 1214
1204Sets the variable `ffap-string-at-point-region' to the bounds of URL, if any." 1215Sets the variable `ffap-string-at-point-region' to the bounds of URL, if any."
1205 ;; `gopher-parse-bookmark' from gopher.el is not so robust 1216 ;; `gopher-parse-bookmark' from gopher.el is not so robust
1206 (save-excursion 1217 (when (stringp ffap-gopher-regexp)
1207 (beginning-of-line) 1218 (save-excursion
1208 (if (looking-at ffap-gopher-regexp) 1219 (let* ((beg (progn (beginning-of-line)
1209 (progn 1220 (while (and (not (bobp)) (ffap--gopher-var-on-line))
1210 (while (and (looking-at ffap-gopher-regexp) (not (bobp))) 1221 (forward-line -1))
1211 (forward-line -1)) 1222 (point)))
1212 (or (looking-at ffap-gopher-regexp) (forward-line 1)) 1223 (bookmark (cl-loop for keyval = (ffap--gopher-var-on-line)
1213 (setq ffap-string-at-point-region (list (point) (point))) 1224 while keyval collect keyval
1214 (let ((type "1") path host (port "70")) 1225 do (forward-line 1))))
1215 (while (looking-at ffap-gopher-regexp) 1226 (when bookmark
1216 (let ((var (intern 1227 (setq ffap-string-at-point-region (list beg (point)))
1217 (downcase 1228 (let-alist (nconc bookmark '((type . "1") (port . "70")))
1218 (buffer-substring (match-beginning 1) 1229 (if (and .path (string-match "\\`ftp:.*@" .path))
1219 (match-end 1))))) 1230 (concat "ftp://"
1220 (val (buffer-substring (match-beginning 2) 1231 (substring .path 4 (1- (match-end 0)))
1221 (match-end 2)))) 1232 (substring .path (match-end 0)))
1222 (set var val) 1233 (and (= (length .type) 1)
1223 (forward-line 1))) 1234 .host ;; (ffap-machine-p host)
1224 (setcdr ffap-string-at-point-region (list (point))) 1235 (concat "gopher://" .host
1225 (if (and path (string-match "^ftp:.*@" path)) 1236 (if (equal .port "70") "" (concat ":" .port))
1226 (concat "ftp://" 1237 "/" .type .path)))))))))
1227 (substring path 4 (1- (match-end 0)))
1228 (substring path (match-end 0)))
1229 (and (= (length type) 1)
1230 host;; (ffap-machine-p host)
1231 (concat "gopher://" host
1232 (if (equal port "70") "" (concat ":" port))
1233 "/" type path))))))))
1234 1238
1235(defvar ffap-ftp-sans-slash-regexp 1239(defvar ffap-ftp-sans-slash-regexp
1236 (and 1240 (and
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index 1ba5f86a887..a3fe3502461 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -49,6 +49,23 @@ index 3d7cebadcf..ad4b70d737 100644
49 (should (equal '(1 1) ffap-string-at-point-region))))) 49 (should (equal '(1 1) ffap-string-at-point-region)))))
50 (and (file-exists-p file) (delete-file file))))) 50 (and (file-exists-p file) (delete-file file)))))
51 51
52(ert-deftest ffap-gopher-at-point ()
53 (with-temp-buffer
54 (insert "\
55Type = 1
56Name = foo
57Path = /the/path
58Port = 7070
59Host = example.com\n")
60 (should-not (ffap-gopher-at-point))
61 (goto-char (point-min))
62 (should (equal (ffap-gopher-at-point)
63 "gopher://example.com:7070/1/the/path"))
64 (should (equal ffap-string-at-point-region
65 (list (point-min) (point-max))))
66 (let ((ffap-gopher-regexp nil))
67 (should-not (ffap-gopher-at-point)))))
68
52(provide 'ffap-tests) 69(provide 'ffap-tests)
53 70
54;;; ffap-tests.el ends here 71;;; ffap-tests.el ends here