unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Lars Ingebrigtsen <larsi@gnus.org>
To: jari <jari.aalto@cante.net>
Cc: 8439@debbugs.gnu.org, 6695@debbugs.gnu.org
Subject: bug#6695: bug#8439: [PATCH] ffap.el -- detect paths with spaces (v4)
Date: Fri, 14 Aug 2020 15:08:45 +0200	[thread overview]
Message-ID: <87tux574te.fsf@gnus.org> (raw)
In-Reply-To: <87mucmn2gs.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sat, 23 Nov 2019 14:31:47 +0100")

Lars Ingebrigtsen <larsi@gnus.org> writes:

> This was seven years ago, and not surprisingly, the patch doesn't apply
> any more.

I've respun the patch so that it now applies to Emacs 28, and the test
cases seem to kinda work?  The c: isn't included, but is that to be
expected?

I removed the Cygwin char translation stuff, because there was some
discussion about whether that was needed.

So what do people think?  Good or bad?  Does this work in any way
sensibly for people?

diff --git a/lisp/ffap.el b/lisp/ffap.el
index 4a506207d5..6d40fa8c45 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1109,6 +1109,123 @@ ffap-string-at-point
   ;; Added at suggestion of RHOGEE (for ff-paths), 7/24/95.
   "Last string returned by the function `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."
+  (unless dir-separator
+    (setq dir-separator "/"))
+  (let ((opoint (point))
+	point punct end whitespace-p)
+    (when (re-search-backward
+	   (regexp-quote dir-separator) (line-beginning-position) t)
+      ;; Move to the beginning of the match..
+      (forward-char 1)
+      ;; ... 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 extension
+	  (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.
+This includes spaces.
+Optional DIR-SEPARATOR defaults to \"/\".
+Call `ffap-search-backward-file-end' to refine the ending point."
+  (unless 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)
+    (when (looking-at ".*?/")
+      (setq str "/"
+	    pos (match-end 0)))
+    (when (and (looking-at ".*?\\\\")
+               (or (null pos)
+	           (< (match-end 0) pos)))
+      (setq str "\\"
+	    pos (match-end 0)))
+    (goto-char point)
+    (when (and (re-search-backward "/" (line-beginning-position) t)
+               (or (null pos)
+	           (< (- point (point)) (- pos point))))
+      (setq str "/"
+	    pos (1+ (point)))) ;1+ to keep cursor at the end of char
+    (goto-char point)
+    (when (and (re-search-backward "\\\\" (line-beginning-position) t)
+               (or (null pos)
+		   (< (- point (point)) (- pos point))))
+      (setq str "\\"
+	    pos (1+ (point))))
+    (when pos
+      (goto-char pos))
+    str))
+
 (defun ffap-string-at-point (&optional mode)
   "Return a string of characters from around point.
 
@@ -1128,7 +1245,8 @@ ffap-string-at-point
 
 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
+  (let* (dir-separator
+         (args
 	  (cdr
 	   (or (assq (or mode major-mode) ffap-string-at-point-mode-alist)
 	       (assq 'file ffap-string-at-point-mode-alist))))
@@ -1137,14 +1255,25 @@ ffap-string-at-point
          (beg (if region-selected
 		  (region-beginning)
 		(save-excursion
-		  (skip-chars-backward (car args))
-		  (skip-chars-forward (nth 1 args) pt)
+	          (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))
 		  (point))))
          (end (if region-selected
 		  (region-end)
 		(save-excursion
 		  (skip-chars-forward (car args))
 		  (skip-chars-backward (nth 2 args) pt)
+	          (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))
 		  (point))))
          (region-len (- (max beg end) (min beg end))))
 


-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





  reply	other threads:[~2020-08-14 13:08 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-07 15:24 bug#8439: [PATCH] ffap.el -- detect paths with spaces Jari Aalto
2011-07-03 23:29 ` Lars Magne Ingebrigtsen
2012-10-19  7:39 ` bug#8439: [PATCH] ffap.el -- detect paths with spaces (v2) Jari Aalto
2012-10-19  9:49   ` Eli Zaretskii
2012-10-19 10:05     ` jari
2012-10-19 11:15       ` Yigal Hochberg
2012-10-19 11:22       ` Eli Zaretskii
2012-10-19 12:15       ` Nicolas Richard
2012-10-19 21:47     ` Andrew W. Nosenko
2012-10-19 22:23       ` Eli Zaretskii
2012-10-19 22:36       ` Yigal Hochberg
2012-10-19 22:57         ` Andrew W. Nosenko
2012-10-19 23:24         ` Yigal Hochberg
2012-10-20  1:45       ` Stefan Monnier
2012-10-20 11:01       ` Juri Linkov
2012-10-19  8:35 ` Jari Aalto
2012-10-20  1:44   ` Stefan Monnier
2012-10-20  1:49     ` Daniel Colascione
2012-10-20  7:56     ` bug#8439: [PATCH] ffap.el -- detect paths with spaces (v3) jari
2012-10-20  8:45       ` bug#8439: [PATCH] ffap.el -- detect paths with spaces (v4) jari
2012-10-20 10:20         ` Eli Zaretskii
2012-10-21  0:18         ` Stefan Monnier
2012-10-21  8:07           ` Jari Aalto
2019-11-23 13:31         ` bug#6695: " Lars Ingebrigtsen
2020-08-14 13:08           ` Lars Ingebrigtsen [this message]
2020-08-15  9:07             ` Eli Zaretskii
2020-08-15 10:13               ` Lars Ingebrigtsen
2012-10-20  8:11     ` bug#8439: [PATCH] ffap.el -- detect paths with spaces (v2) Eli Zaretskii
2012-10-21  0:16       ` Stefan Monnier
     [not found] <<87pqoyaxu0.fsf@blue.sea.net>
     [not found] ` <<87zk3i7tbu.fsf@picasso.cante.net>
     [not found]   ` <<jwvzk3ihr2i.fsf-monnier+emacs@gnu.org>
     [not found]     ` <<20121020075601.GD29154@picasso.cante.net>
     [not found]       ` <<20121020084551.GE29154@picasso.cante.net>
     [not found]         ` <<87mucmn2gs.fsf@gnus.org>
     [not found]           ` <<87tux574te.fsf@gnus.org>
     [not found]             ` <<83v9hkjmzb.fsf@gnu.org>
2020-08-15 19:33               ` bug#6695: bug#8439: [PATCH] ffap.el -- detect paths with spaces (v4) Drew Adams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87tux574te.fsf@gnus.org \
    --to=larsi@gnus.org \
    --cc=6695@debbugs.gnu.org \
    --cc=8439@debbugs.gnu.org \
    --cc=jari.aalto@cante.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).