unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Anyone have a 'move-line' function?
@ 2006-05-02 18:44 Joe Smith
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Smith @ 2006-05-02 18:44 UTC (permalink / raw)


I'd like a function that moves the current line up (or down) in a 
buffer. I just make do with kill/yank or transpose-lines, but sometimes 
I'd just like to hit a key and move the line, preferably without losing 
point.

As an exercise, I played with writing such a function, and I have 
something that works but it turns out to be fairly tricky to get it 
exactly right. So if there's something already done, or I've missed 
something obvious (most likely), I'll study that before I keep banging away.

<Joe

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

* Re: Anyone have a 'move-line' function?
       [not found] <mailman.1234.1146610060.9609.help-gnu-emacs@gnu.org>
@ 2006-05-02 23:33 ` Bastien
  2006-05-03  3:46   ` Joe Smith
       [not found]   ` <mailman.1250.1146628814.9609.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 10+ messages in thread
From: Bastien @ 2006-05-02 23:33 UTC (permalink / raw)


Joe Smith <jes@martnet.com> writes:

> So if there's something already done, or I've missed something
> obvious (most likely), I'll study that before I keep banging 
> away.

Is C-o what you want?  It moves down a line, keeping the point where
it is.  Strangely enough, C-u - 1 C-o seems not to move up a line.

,----[ open-line ]
| open-line is an interactive compiled Lisp function in `simple.el'.
| It is bound to C-o, <insertline>.
| (open-line N)
| 
| Insert a newline and leave point before it.
| If there is a fill prefix and/or a `left-margin', insert them
| on the new line if the line would have been blank.
| With arg N, insert N newlines.
`----

-- 
Bastien

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

* Re: Anyone have a 'move-line' function?
  2006-05-02 23:33 ` Anyone have a 'move-line' function? Bastien
@ 2006-05-03  3:46   ` Joe Smith
       [not found]   ` <mailman.1250.1146628814.9609.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 10+ messages in thread
From: Joe Smith @ 2006-05-03  3:46 UTC (permalink / raw)


Bastien wrote:
> 
> Is C-o what you want?  It moves down a line, keeping the point where
> it is.  Strangely enough, C-u - 1 C-o seems not to move up a line.

Not quite.

If I start with this (^=point):

one
two
th^ree
four

And I run 'move-line-up' (say by M-up), I want this:

one
th^ree
two
four

Then run 'move-line-down' twice (say by M-down M-down) to get this:

one
two
four
th^ree

Thanks.

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

* Re: Anyone have a 'move-line' function?
       [not found]   ` <mailman.1250.1146628814.9609.help-gnu-emacs@gnu.org>
@ 2006-05-03  8:17     ` Mathias Dahl
  2006-05-03 21:03     ` liyer.vijay
  1 sibling, 0 replies; 10+ messages in thread
From: Mathias Dahl @ 2006-05-03  8:17 UTC (permalink / raw)


Joe Smith <jes@martnet.com> writes:

> If I start with this (^=point):
>
> one
> two
> th^ree
> four
>
> And I run 'move-line-up' (say by M-up), I want this:
>
> one
> th^ree
> two
> four

The following is quite ugly but seems to work. I am sure someone else
can come up with something much cleaner:

(defun move-line-up ()
  (interactive)
  (let ((col (current-column)))
    (beginning-of-line) 
    (kill-line 1)
    (previous-line 1)
    (yank)
    (previous-line 1)
    (beginning-of-line)
    (forward-char col)))

If you don't have `current-column' in your Emacs (for some reason, I
actually don't know why I believe this would be the case...), the
following does the same thing:

(defun move-line-up ()
  (interactive)
  (let ((col (- (point) 
                (save-excursion
                  (beginning-of-line)
                  (point)))))
    (beginning-of-line)
    (kill-line 1)
    (previous-line 1)
    (yank)
    (previous-line 1)
    (beginning-of-line)
    (forward-char col)))

/Mathias

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

* Re: Anyone have a 'move-line' function?
       [not found]   ` <mailman.1250.1146628814.9609.help-gnu-emacs@gnu.org>
  2006-05-03  8:17     ` Mathias Dahl
@ 2006-05-03 21:03     ` liyer.vijay
  2006-05-04 15:29       ` Joe Smith
       [not found]       ` <mailman.1411.1146756636.9609.help-gnu-emacs@gnu.org>
  1 sibling, 2 replies; 10+ messages in thread
From: liyer.vijay @ 2006-05-03 21:03 UTC (permalink / raw)


Joe Smith wrote:
> If I start with this (^=point):
>
> one
> two
> th^ree
> four
>
> And I run 'move-line-up' (say by M-up), I want this:
>
> one
> th^ree
> two
> four
>
> Then run 'move-line-down' twice (say by M-down M-down) to get this:
>
> one
> two
> four
> th^ree

Here's a solution that doesn't add to the kill-ring (not that we'll
reach the kill ring limit :-)

(defun move-line-up (&optional n)
  "Moves current line up leaving point in place.  With a prefix
argument, moves up N lines."
  (interactive "p")
  (if (null n) (setq n 1))
  (let ((col (current-column)))
    (beginning-of-line)
    (next-line 1)
    (transpose-lines (- n))
    (previous-line 1)
    (forward-char col)))

Cheers
Vijay

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

* RE: Anyone have a 'move-line' function?
@ 2006-05-04 12:11 Bourgneuf Francois
  0 siblings, 0 replies; 10+ messages in thread
From: Bourgneuf Francois @ 2006-05-04 12:11 UTC (permalink / raw)


I think the transpose-line command may be what you're looking for.

It is bound to C-x C-t.

Exchange current line and previous line, leaving point after both.
With argument ARG, takes previous line and moves it past ARG lines.
With argument 0, interchanges line point is in with line mark is in.

Bour9

-----Message d'origine-----
De : help-gnu-emacs-bounces+francois.bourgneuf=groupe-mma.fr@gnu.org [mailto:help-gnu-emacs-bounces+francois.bourgneuf=groupe-mma.fr@gnu.org] De la part de liyer.vijay@gmail.com
Envoyé : mercredi 3 mai 2006 23:04
À : help-gnu-emacs@gnu.org
Objet : Re: Anyone have a 'move-line' function?

Joe Smith wrote:
> If I start with this (^=point):
>
> one
> two
> th^ree
> four
>
> And I run 'move-line-up' (say by M-up), I want this:
>
> one
> th^ree
> two
> four
>
> Then run 'move-line-down' twice (say by M-down M-down) to get this:
>
> one
> two
> four
> th^ree

Here's a solution that doesn't add to the kill-ring (not that we'll
reach the kill ring limit :-)

(defun move-line-up (&optional n)
  "Moves current line up leaving point in place.  With a prefix
argument, moves up N lines."
  (interactive "p")
  (if (null n) (setq n 1))
  (let ((col (current-column)))
    (beginning-of-line)
    (next-line 1)
    (transpose-lines (- n))
    (previous-line 1)
    (forward-char col)))

Cheers
Vijay

_______________________________________________
help-gnu-emacs mailing list
help-gnu-emacs@gnu.org
http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: Anyone have a 'move-line' function?
  2006-05-03 21:03     ` liyer.vijay
@ 2006-05-04 15:29       ` Joe Smith
  2006-05-04 16:24         ` John Conrad
       [not found]       ` <mailman.1411.1146756636.9609.help-gnu-emacs@gnu.org>
  1 sibling, 1 reply; 10+ messages in thread
From: Joe Smith @ 2006-05-04 15:29 UTC (permalink / raw)


Mathias Dahl wrote:
> The following is quite ugly but seems to work. ...

liyer.vijay@gmail.com wrote:
> Here's a solution that doesn't add to the kill-ring ...

Very nice. Thanks guys.

I like the idea of using current-column (new to me anyway) and not
adding to the kill-ring.

Here's what I came up with--after studying your suggestions and
adapting what I had; Vijay's is simpler but it goes a little weird at
the file edges: moving the last line down adds empty lines; moving the
first line up gives an error and leaves point on line 2.

Thanks again. Comments/corrections welcome.

(defun move-line (n)
   "Move the current line up or down by N lines."
   (interactive "p")
   (setq col (current-column))
   (beginning-of-line) (setq start (point))
   (end-of-line) (forward-char) (setq end (point))
   (let ((line-text (delete-and-extract-region start end)))
     (forward-line n)
     (insert line-text)
     ;; restore point to original column in moved line
     (forward-line -1)
     (forward-char col)))

(defun move-line-up (n)
   "Move the current line up by N lines."
   (interactive "p")
   (move-line (if (null n) -1 (- n))))

(defun move-line-down (n)
   "Move the current line down by N lines."
   (interactive "p")
   (move-line (if (null n) 1 n)))

(global-set-key (kbd "M-<up>") 'move-line-up)
(global-set-key (kbd "M-<down>") 'move-line-down)

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

* Re: Anyone have a 'move-line' function?
  2006-05-04 15:29       ` Joe Smith
@ 2006-05-04 16:24         ` John Conrad
  2006-05-04 20:03           ` Joe Smith
  0 siblings, 1 reply; 10+ messages in thread
From: John Conrad @ 2006-05-04 16:24 UTC (permalink / raw)


On 5/4/06, Joe Smith <jes@martnet.com> wrote:
> Mathias Dahl wrote:
> > The following is quite ugly but seems to work. ...
>
> liyer.vijay@gmail.com wrote:
> > Here's a solution that doesn't add to the kill-ring ...
>
> Very nice. Thanks guys.
>
> I like the idea of using current-column (new to me anyway) and not
> adding to the kill-ring.
>
> Here's what I came up with--after studying your suggestions and
> adapting what I had; Vijay's is simpler but it goes a little weird at
> the file edges: moving the last line down adds empty lines; moving the
> first line up gives an error and leaves point on line 2.
>
> Thanks again. Comments/corrections welcome.
>
> (defun move-line (n)
>    "Move the current line up or down by N lines."
>    (interactive "p")
>    (setq col (current-column))
>    (beginning-of-line) (setq start (point))
>    (end-of-line) (forward-char) (setq end (point))
>    (let ((line-text (delete-and-extract-region start end)))
>      (forward-line n)
>      (insert line-text)
>      ;; restore point to original column in moved line
>      (forward-line -1)
>      (forward-char col)))
>
> (defun move-line-up (n)
>    "Move the current line up by N lines."
>    (interactive "p")
>    (move-line (if (null n) -1 (- n))))
>
> (defun move-line-down (n)
>    "Move the current line down by N lines."
>    (interactive "p")
>    (move-line (if (null n) 1 n)))
>
> (global-set-key (kbd "M-<up>") 'move-line-up)
> (global-set-key (kbd "M-<down>") 'move-line-down)

I don't know if this is the sort of comment you are welcoming, but I
think your style would be improved by wrapping the col, start and end
variables in a let expression (with the effect of making them local)
instead of declaring and setting global variables simultaneously with
setq. After you've declared them in the let, you can then use setq on
them as needed. In the following variation on your function, I create
a local col variable and set it to (current-column), then I create
start and end local variables but I do not initialize them with any
particular value. Later, I use setq on them the same way as you did in
your original function.

(defun move-line (n)
   "Move the current line up or down by N lines."
   (interactive "p")
   (let ((col (current-column))
         start
         end)
     (beginning-of-line)
     (setq start (point))
     (end-of-line)
     (forward-char)
     (setq end (point))
     (let ((line-text (delete-and-extract-region start end)))
       (forward-line n)
       (insert line-text)
       ;; restore point to original column in moved line
       (forward-line -1)
       (forward-char col))))

John Emerson Conrad

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

* Re: Anyone have a 'move-line' function?
  2006-05-04 16:24         ` John Conrad
@ 2006-05-04 20:03           ` Joe Smith
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Smith @ 2006-05-04 20:03 UTC (permalink / raw)


John Conrad wrote:
> 
> I don't know if this is the sort of comment you are welcoming, but I
> think your style would be improved by wrapping the col, start and end
> variables in a let expression ...

That's exactly what I'm looking for, thanks!

I've used emacs for nearly 20 years (ack!) but never had time to learn 
elisp beyond a 'setq' or so in my .emacs. I have some time, so I'm just 
learning the basics.

I forgot you can declare variables in a let without setting them, and I 
needed the movements before I could set them. I was under the impression 
that any symbols created would be scoped dynamically and thus be local 
even though created by setq.

Much appreciated.

<Joe

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

* Re: Anyone have a 'move-line' function?
       [not found]       ` <mailman.1411.1146756636.9609.help-gnu-emacs@gnu.org>
@ 2006-05-05  0:09         ` liyer.vijay
  0 siblings, 0 replies; 10+ messages in thread
From: liyer.vijay @ 2006-05-05  0:09 UTC (permalink / raw)


Joe Smith wrote:
> Mathias Dahl wrote:
> > The following is quite ugly but seems to work. ...
>
> liyer.vijay@gmail.com wrote:
> > Here's a solution that doesn't add to the kill-ring ...
>
> Here's what I came up with--after studying your suggestions and
> adapting what I had; Vijay's is simpler but it goes a little weird at
> the file edges: moving the last line down adds empty lines; moving the
> first line up gives an error and leaves point on line 2.

Yes, I noticed that myself today.  transpose-lines has weird behaviour
at the end of the buffer: with one argument, it correctly transposes
but adds a newline.  With a prefix argument, it completely weirds
everything out.  I didn't know about this earlier.

> Thanks again. Comments/corrections welcome.
>
> delete-and-extract-region

This is a function I hadn't known about.  Thanks :-)

Cheers
Vijay

> Can we quote you on that?
A long time ago, someone in the Lisp industry told me it was poor form
quote people; it suggests that they lack value.
	-- Kent M Pitman <pitman@world.std.com> in comp.lang.lisp

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

end of thread, other threads:[~2006-05-05  0:09 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.1234.1146610060.9609.help-gnu-emacs@gnu.org>
2006-05-02 23:33 ` Anyone have a 'move-line' function? Bastien
2006-05-03  3:46   ` Joe Smith
     [not found]   ` <mailman.1250.1146628814.9609.help-gnu-emacs@gnu.org>
2006-05-03  8:17     ` Mathias Dahl
2006-05-03 21:03     ` liyer.vijay
2006-05-04 15:29       ` Joe Smith
2006-05-04 16:24         ` John Conrad
2006-05-04 20:03           ` Joe Smith
     [not found]       ` <mailman.1411.1146756636.9609.help-gnu-emacs@gnu.org>
2006-05-05  0:09         ` liyer.vijay
2006-05-04 12:11 Bourgneuf Francois
  -- strict thread matches above, loose matches on Subject: below --
2006-05-02 18:44 Joe Smith

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