From 9d912ef5fe082c81917cf65bbacbf4d23e1cd9f3 Mon Sep 17 00:00:00 2001 From: Jari Aalto Date: Fri, 19 Oct 2012 10:15:50 +0300 Subject: [PATCH] lisp/ffap.el: (ffap-string-at-point): v2 support spaces Organization: Private Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Signed-off-by: Jari Aalto --- lisp/ffap.el | 87 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/lisp/ffap.el b/lisp/ffap.el index 4c75609..a74f85b 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1036,6 +1036,17 @@ possibly a major-mode name, or one of the symbol ;; Added at suggestion of RHOGEE (for ff-paths), 7/24/95. "Last string returned by `ffap-string-at-point'.") +;; Test cases: +;; +;; c:/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program here.txt +;; c:/Program Files/Open Text Evaluation Media/Open Text Exceed 14 x86/Program Files/Hummingbird/ +;; +(defvar ffap-paths-with-spaces + (or (memq system-type '(ms-dos windows-nt)) + (string-match "cygwin" (emacs-version))) + "If non-nil, look for paths with spaces in `ffap-string-at-point'. +Enabled in W32 and Cygwin by default.") + (defun 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 @@ -1043,25 +1054,63 @@ 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. Sets `ffap-string-at-point' and `ffap-string-at-point-region'." - (let* ((args - (cdr - (or (assq (or mode major-mode) ffap-string-at-point-mode-alist) - (assq 'file ffap-string-at-point-mode-alist)))) - (pt (point)) - (str - (if (and transient-mark-mode mark-active) - (buffer-substring - (setcar ffap-string-at-point-region (region-beginning)) - (setcar (cdr ffap-string-at-point-region) (region-end))) - (buffer-substring - (save-excursion - (skip-chars-backward (car args)) - (skip-chars-forward (nth 1 args) pt) - (setcar ffap-string-at-point-region (point))) - (save-excursion - (skip-chars-forward (car args)) - (skip-chars-backward (nth 2 args) pt) - (setcar (cdr ffap-string-at-point-region) (point))))))) + (let* ((cygwin-p (string-match "cygwin" (emacs-version))) + (args + (cdr + (or (assq (or mode major-mode) ffap-string-at-point-mode-alist) + (assq 'file ffap-string-at-point-mode-alist)))) + (pt (point)) + space-p + end + (str + (if (and transient-mark-mode mark-active) + (buffer-substring + (setcar ffap-string-at-point-region (region-beginning)) + (setcar (cdr ffap-string-at-point-region) (region-end))) + (buffer-substring + (save-excursion + (if (and ffap-paths-with-spaces + (memq mode '(nil file))) + (if (string-match "^[ \t]*$" + (buffer-substring (line-beginning-position) + (point))) + ;; Nothing interesting before point. Move to the first character + (skip-chars-forward " \t" (line-end-position)) + ;; If at colon, move a little forward so that next + ;; `re-search-backward' can position at drive letter. + (if (looking-at ":/") + (forward-char 1)) + ;; Skip until drive path start or patch start letter + (while (re-search-backward "[a-zA-Z]:[\\\\/]\\|[/\\\\]" + (line-beginning-position) t) + (goto-char (match-beginning 0))))) + (skip-chars-backward (car args)) + (skip-chars-forward (nth 1 args) pt) + (when (and ffap-paths-with-spaces + (memq mode '(nil file))) + ;; Paths may contains spaces, allow those + (if (looking-at + "[^\t\r\n]*[/\\\\][^][<>()\"';:|\t\r\n]*[^][<>()\"';:|\r\n[:space:]]") + (setq space-p (match-end 0)))) + (setcar ffap-string-at-point-region (point))) + (save-excursion + (skip-chars-forward (car args)) + (skip-chars-backward (nth 2 args) pt) + (setq end (point)) + (if (and space-p + (> space-p end) + (memq mode '(file nil))) + (setq end space-p)) + (setcar (cdr ffap-string-at-point-region) end)))))) + ;; Under Cygwin, convert drive letters in paths. + (when (and cygwin-p + (memq mode '(nil file)) + (string-match "^\\([a-zA-Z]\\):[/\\\\]\\(.*\\)" str)) + (let ((drive (downcase (match-string 1 str))) + (path (match-string 2 str))) + (setq str (format "/cygdrive/%s/%s" + drive + (replace-regexp-in-string "[\\\\]" "/" path))))) (set-text-properties 0 (length str) nil str) (setq ffap-string-at-point str))) -- 1.7.10.4