>From 7b52dadb3c1901d3c19b0a75854648e660fa4ac8 Mon Sep 17 00:00:00 2001 From: Jari Aalto Date: Sat, 20 Oct 2012 11:29:27 +0300 Subject: [PATCH] lisp/ffap.el: Detect patchs with spaces. Organization: Private Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit 2012-10-19 Fri Jari Aalto * ffap.el (ffap-file-name-with-spaces-flag): New variable. (ffap-cygwin-convert): New function. (ffap-search-forward-file-end): New function. (ffap-search-backward-file-end): New function. (ffap-dir-separator-near-point): New function. (ffap-string-at-point): If `ffap-file-name-with-spaces-flag' is set, allow spaces in file names. Signed-off-by: Jari Aalto --- lisp/ffap.el | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 159 insertions(+), 19 deletions(-) diff --git a/lisp/ffap.el b/lisp/ffap.el index 4c75609..02dbab5 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1036,6 +1036,125 @@ 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: (let ((ffap-file-name-with-spaces-flag t)) (ffap-string-at-point)) +;; +;; 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/ +;; c:\Program Files\Open Text Evaluation Media\Open Text Exceed 14 x86\Program Files\Hummingbird\ +;; c:\Program Files\Freescale\CW for MPC55xx and MPC56xx 2.10\PowerPC_EABI_Tools\Command_Line_Tools\CLT_Usage_Notes.txt +;; C:\temp\program.log on Windows or /var/log/program.log on Unix. + +(defvar ffap-file-name-with-spaces-flag (memq system-type '(ms-dos windows-nt)) + "If non-nil, enable looking for paths with spaces in `ffap-string-at-point'. +Enabled in W32 by default.") + +(defun ffap-search-backward-file-end (&optional dir-separator end) + "Search backward position point where file would probably end. +Optional DIR-SEPARATOR defaults to \"/\". The search maximum is +`line-end-position' or optional END point. + +Suppose the cursor is somewhere that might be near end of file, +the guessing would position point before punctuation (like comma) +after the file extension: + + C:\temp\file.log, which contain .... + =============================== (before) + ---------------- (after) + + + C:\temp\file.log on Windows or /tmp/file.log on Unix + =============================== (before) + ---------------- (after) + +The strategy is to search backward until DIR-SEPARATOR which defaults to +\"/\" and then take educated guesses. + +Move point and return point if an adjustment was done." + (or dir-separator + (setq dir-separator "/")) + (let ((opoint (point)) + point + puct + end + whitespace-p) + (when (re-search-backward + (regexp-quote dir-separator) (line-beginning-position) t) + (forward-char 1) ;move to the beginning of match + ;; until typical punctuation + (when (re-search-forward "\\([][<>()\"'`,.:;]\\)" + (or end + (line-end-position)) + t) + (setq end (match-end 0)) + (setq punct (match-string 1)) + (setq whitespace-p (looking-at "[ \t\r\n]\\|$")) + (goto-char end) + (cond + ((and (string-equal punct ".") + whitespace-p) ;end of sentence + (setq point (1- (point)))) + ((and (string-equal punct ".") + (looking-at "[a-zA-Z0-9.]+")) ;possibly file extensionl + (setq point (match-end 0))) + (t + (setq point (point))))) + (goto-char opoint) + (when point + (goto-char point) + point)))) + +(defun ffap-search-forward-file-end (&optional dir-separator) + "Search DIR-SEPARATOR and position point at file's maximum ending (including spaces). +Optional DIR-SEPARATOR defaults to \"/\". +Call `ffap-search-backward-file-end' to refine the ending point." + (or dir-separator + (setq dir-separator "/")) + (let* ((chars ;expected chars in file name + (concat "[^][^<>()\"'`;,#*|" + ;; exclude the opposite as we know the separator + (if (string-equal dir-separator "/") + "\\\\" + "/") + "\t\r\n]")) + (re (concat + chars "*" + (if dir-separator + (regexp-quote dir-separator) + "/") + chars "*"))) + (when (looking-at re) + (goto-char (match-end 0))))) + +(defun ffap-dir-separator-near-point () + "Search backward and forward for closest slash or backlash in line. +Return string slash or backslash. Point is moved to closest position." + (let ((point (point)) + str + pos) + (if (looking-at ".*?/") + (setq str "/" + pos (match-end 0))) + (if (looking-at ".*?\\\\") + (if (or (null pos) + (< (match-end 0) pos)) + (setq str "\\" + pos (match-end 0)))) + (goto-char point) + (if (re-search-backward "/" (line-beginning-position) t) + (if (or (null pos) + (< (- point (point)) (- pos point))) + (setq str "/" + pos (1+ (point))))) ;1+ to keep cursor at the end of char + (goto-char point) + (if (re-search-backward "\\\\" (line-beginning-position) t) + (if (or (null pos) + (< (- point (point)) (- pos point))) + (setq str "\\" + pos (1+ (point))))) + (if pos + (goto-char pos)) + str)) + (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,26 +1162,47 @@ 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))) + dir-separator + beg + end + (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 + (if (and ffap-file-name-with-spaces-flag + (memq mode '(nil file))) + (when (setq dir-separator (ffap-dir-separator-near-point)) + (while (re-search-backward + (regexp-quote dir-separator) + (line-beginning-position) t) + (goto-char (match-beginning 0))))) + (skip-chars-backward (car args)) + (skip-chars-forward (nth 1 args) pt) + (setcar ffap-string-at-point-region (point)) + (setq beg (point))) + (save-excursion + (skip-chars-forward (car args)) + (skip-chars-backward (nth 2 args) pt) + (setq end (point)) + (when (and ffap-file-name-with-spaces-flag + (memq mode '(nil file))) + (ffap-search-forward-file-end dir-separator) + (ffap-search-backward-file-end dir-separator) + (setq end (point))) + (setcar (cdr ffap-string-at-point-region) end)))))) (set-text-properties 0 (length str) nil str) + (if (and (eq system-type 'cygwin) + (fboundp 'cygwin-convert-path-from-windows)) + (setq str (cygwin-convert-path-from-windows str))) (setq ffap-string-at-point str))) (defun ffap-string-around () -- 1.7.10.4