help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Function to replace spaces with underscores


From: Pascal J. Bourguignon
Subject: Re: Function to replace spaces with underscores
Date: Tue, 17 Sep 2013 20:04:43 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.2 (gnu/linux)

pico77 <grammophonia@gmail.com> writes:

> Dear all, 
>
>
> at the end of this post there is a function that I load in my .emacs file.
> The main goal is to take a selected line and remove all spaces with
> underscore. This is very useful to produce file-names from copy/past
> consistently without spaces. But there is a problem with that. 
>
>
> If I open emacs select a line ad do M-x s2u then it works fine, but if I do
> it further it requires to apply the function 3 times before to get it done.
> So the problem is really that probably the function is programmed in a way
> that after the first applucation of s2u there is something which has to be
> cleaned up before to re-apply the same function. 
>
> I am not a lisp/emacs expert and the function was passed by a friend who is
> now not able to solve the problem. I hope somebody out there can help to
> find the bug!

Indeed, as Eli said, the specifications of this command are strange, and
rather impractical.  What if you make a different selection? You won't
be able to easily replace spaces to underscore on two different regions.

It would be better either to

1- select the target separator from a prefix argument.  
   Eg. C-u M-x s2u RET would use ?_ instead of ?- and
       C-- M-x s2u RET would use ?  instead of ?-, or

    (defun s2u (replacement start end)
      (interactive "*P\nr")
      (save-excursion
        (let ((repchar (cond
                         ((null   replacement) "-")
                         ((consp  replacement) "_")
                         ((eq '-  replacement) " ")
                         ((minusp replacement) " ")
                         ((zerop  replacement) "-")
                         (t                    "_"))))
          (goto-char start)
          (while (re-search-forward "[- _]" end t)
            (delete-region (match-beginning 0) (match-end 0))
            (insert repchar)))))



2- look at what separator is used in the region and select the next one
   from there.  The difficulty here being that there are several states:

     - the region contains various separators         -> ?-
     - the region contains no separator               -> no change
     - the region contains ?  but no ?- or ?_         -> ?-
     - the region contains ?- but no ?  or ?_         -> ?_
     - the region contains ?_ but no ?- or ?          -> ? 

   I'd propose the indicated transitions.

    (defun collect-substrings (regexp start end)
      (let ((results '()))
        (goto-char start)
        (while (re-search-forward regexp end t)
          (push (buffer-substring (match-beginning 0) (match-end 0)) results))
        (nreverse results)))

    (defun* s2u (start end)
      (interactive "*r")
      (save-excursion
        (let* ((separators (remove-duplicates (collect-substrings "[- _]" start 
end)
                                              :test (function string=)))
               (repchar (cond
                          ((null separators)                (return-from s2u))
                          ((rest separators)                "-")
                          ((string= (first separators) " ") "-")
                          ((string= (first separators) "-") "_")
                          ((string= (first separators) "_") " "))))
          (goto-char start)
          (while (re-search-forward "[- _]" end t)
            (delete-region (match-beginning 0) (match-end 0))
            (insert repchar)))))


-- 
__Pascal Bourguignon__
http://www.informatimago.com/


reply via email to

[Prev in Thread] Current Thread [Next in Thread]