Incorrect copying when duplicating line - key binding proble

Discussion of Emacs Lisp
Post Reply
mmi
Posts: 2
Joined: Thu May 19, 2011 10:34 am

Incorrect copying when duplicating line - key binding proble

Post by mmi » Thu May 19, 2011 10:39 am

hey guys,

I wrote code like this:

Code: Select all

(defun copy-char-from-line-above ()
  "Copies one character from same column but previous row"
  (interactive)
  (let (c)
    (save-excursion
       (previous-line)
       (setq c (buffer-substring-no-properties (point) (+ (point) 1)))
    )
    (insert c)
  )
)
(defalias 'cup 'copy-char-from-line-above)
(global-set-key "\C-i" 'copy-char-from-line-above)
When I run M-x cup many times it runs ok. Same, if I press C-i C-g C-i C-g ... . Problem is, when I press C-i C-i C-i ... which was my usage intention. It copies always the same letter. Why is it like so?

Duke
Posts: 38
Joined: Sat Oct 17, 2009 10:40 pm
Contact:

Re: Incorrect copying when duplicating line - key binding proble

Post by Duke » Thu May 19, 2011 5:40 pm

mmi wrote:When I run M-x cup many times it runs ok. Same, if I press C-i C-g C-i C-g ... . Problem is, when I press C-i C-i C-i ... which was my usage intention. It copies always the same letter. Why is it like so?
I've had the same problem with previous-line before, and now I think this is the reason:
previous-line Emacs help page wrote: If you are thinking of using this in a Lisp program, consider using
`forward-line' with a negative argument instead. It is usually easier
to use and more reliable (no dependence on goal column, etc.).
If the goal column only is reset to the point when you press C-i C-g, that would explain the problem. Forward line doesn't do what we want, but if we take the current-column, we can at least do a reasonable hack:

Code: Select all

(defun copy-char-from-line-above ()
  "Copies one character from same column but previous row"
  (interactive)
  (let ((c (current-column)))
    (save-excursion
     (forward-line -1)
     (forward-char c)
     (setq c (buffer-substring-no-properties (point) (+ (point) 1))))
    (insert c)))
HTH
"If you want to improve, be content to be thought foolish and stupid." -Epictetus

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Incorrect copying when duplicating line - key binding proble

Post by edgar-rft » Thu May 19, 2011 5:47 pm

It turns out that the problem is caused by the Emacs LINE-MOVE-VISUAL function in "simple.el". PREVIOUS-LINE calls LINE-MOVE which calls the LINE-MOVE-VISUAL function if the LINE-MOVE-VISUAL variable is true.

From the commentary in LINE-MOVE-VISUAL:

Code: Select all

;; Check if the previous command was a line-motion command, or if
;; we were called from some other command.
(if (and (consp temporary-goal-column)
    (memq last-command `(next-line previous-line ,this-command)))
    ;; If so, there's no need to reset `temporary-goal-column',
    ;; but we may need to hscroll.
This means that if you call the LINE-MOVE-VISUAL function from another function several times in a row then the TEMPORARY-GOAL-COLUMN variable doesn't get updated and the cursor moves always to the same position in the previous line (IMO this is a bug.)

A workaround would be either to set the TEMPORARY-GOAL-COLUMN variable explicitely to NIL inside the COPY-CHAR-FROM-LINE-ABOVE function or just simply shadow the variable with a local LET variable of the same name like shown below. Notice the additional TEMPORARY-GOAL-COLUMN variable in the LET form:

Code: Select all

(defun copy-char-from-line-above ()
  "Copies one character from same column but previous row"
  (interactive)
  (let (c temporary-goal-column)
    (save-excursion      
       (previous-line)
       (setq c (buffer-substring-no-properties (point) (+ (point) 1))))
    (insert c)))

(defalias 'cup 'copy-char-from-line-above)
(global-set-key "\C-i" 'copy-char-from-line-above)
With me and GNU Emacs 23.2.1 - x86_64-pc-linux-gnu, GTK+ Version 2.20.1, on Debian Squeeze this works as you wanted.

- edgar

mmi
Posts: 2
Joined: Thu May 19, 2011 10:34 am

Re: Incorrect copying when duplicating line - key binding proble

Post by mmi » Fri May 20, 2011 1:44 pm

Thanks,
both solutions work for me (Emacs 23.1.1, Ubuntu 10.10).

Post Reply