unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Function to replace spaces with underscores
@ 2013-09-17  7:39 pico77
  2013-09-17  8:20 ` Eli Zaretskii
  0 siblings, 1 reply; 4+ messages in thread
From: pico77 @ 2013-09-17  7:39 UTC (permalink / raw)
  To: Help-gnu-emacs


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!


Best Regards
Pietro



;; SPACE TO UNDERSCORE
;; Usage: select a line than do M-x s2u 
;;
 (defun s2u ()
  "Cyclically replace {underscore, space, hypen} chars current line or text
selection.
When called repeatedly, this command cycles the {“ ”, “_”, “-”} characters."
  (interactive)
  ;; this function sets a property 「'state」. Possible values are 0 to length
of charArray.
  (let (mainText charArray p1 p2 currentState nextState changeFrom
             changeTo startedWithRegion-p )

    (if (region-active-p)
        (progn
          (setq startedWithRegion-p t )
          (setq p1 (region-beginning))
          (setq p2 (region-end))
          )
      (progn (setq startedWithRegion-p nil ) 
             (setq p1 (line-beginning-position))
             (setq p2 (line-end-position)) ) )

    (setq charArray [" " "_" "-"])

    (setq currentState
          (if (get 's2u 'state) 
              (get 's2u 'state)
            0))
    (setq nextState (% (+ currentState 1) (length charArray)))

    (setq changeFrom (elt charArray currentState ))
    (setq changeTo (elt charArray nextState ))

    (setq mainText (replace-regexp-in-string changeFrom changeTo
(buffer-substring-no-properties p1 p2)) )
    (delete-region p1 p2)
    (insert mainText)
    
    (put 's2u 'state nextState)

    (when startedWithRegion-p 
      (goto-char p2)
      (set-mark p1)
      (setq deactivate-mark nil) ) ) )




--
View this message in context: http://emacs.1067599.n5.nabble.com/Function-to-replace-spaces-with-underscores-tp297516.html
Sent from the Emacs - Help mailing list archive at Nabble.com.



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Function to replace spaces with underscores
  2013-09-17  7:39 pico77
@ 2013-09-17  8:20 ` Eli Zaretskii
  0 siblings, 0 replies; 4+ messages in thread
From: Eli Zaretskii @ 2013-09-17  8:20 UTC (permalink / raw)
  To: Help-gnu-emacs

> Date: Tue, 17 Sep 2013 00:39:35 -0700 (PDT)
> From: pico77 <grammophonia@gmail.com>
> 
> 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. 

As the doc string says, the function _cycles_ through a list of 3
characters, using a state variable.  It records the state variable and
applies it on the next invocation.  So it's a little wonder you need
to invoke the function several times, until it does what you want --
this is how this code was programmed to work.

(I don't really understand the need for such a function, given that
you have the 'replace-regexp' command, which works directly on a
region of the current buffer, instead of -- God forbid! -- extracting
a string from the buffer, changing it, then replacing buffer text with
the modified string.  This code is almost as un-Emacs-Lispy as it
gets.)



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Function to replace spaces with underscores
       [not found] <mailman.2297.1379403955.10748.help-gnu-emacs@gnu.org>
@ 2013-09-17 18:04 ` Pascal J. Bourguignon
  2013-09-17 19:27   ` Barry Margolin
  0 siblings, 1 reply; 4+ messages in thread
From: Pascal J. Bourguignon @ 2013-09-17 18:04 UTC (permalink / raw)
  To: help-gnu-emacs

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/


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Function to replace spaces with underscores
  2013-09-17 18:04 ` Function to replace spaces with underscores Pascal J. Bourguignon
@ 2013-09-17 19:27   ` Barry Margolin
  0 siblings, 0 replies; 4+ messages in thread
From: Barry Margolin @ 2013-09-17 19:27 UTC (permalink / raw)
  To: help-gnu-emacs

In article <87ob7r729w.fsf@informatimago.com>,
 "Pascal J. Bourguignon" <pjb@informatimago.com> wrote:

> 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.

Usually commands that operate like this also check whether the last 
command was this one, or if the region is the same as it was the last 
time. If not, they reset themselves to the initial behavior.

Although since this command just rotates among 3 different behaviors, 
none of them can really be considered "initial". It seems like you're 
just supposed to repeat the command until it does the substitution you 
want this time. You should bind it to a key, so repeating it is easy.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-09-17 19:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.2297.1379403955.10748.help-gnu-emacs@gnu.org>
2013-09-17 18:04 ` Function to replace spaces with underscores Pascal J. Bourguignon
2013-09-17 19:27   ` Barry Margolin
2013-09-17  7:39 pico77
2013-09-17  8:20 ` Eli Zaretskii

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).