Incorrect copying when duplicating line - key binding proble

Discussion of Emacs Lisp

Incorrect copying when duplicating line - key binding proble

Postby 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?
mmi
 
Posts: 2
Joined: Thu May 19, 2011 10:34 am

Re: Incorrect copying when duplicating line - key binding proble

Postby 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
Duke
 
Posts: 38
Joined: Sat Oct 17, 2009 10:40 pm

Re: Incorrect copying when duplicating line - key binding proble

Postby 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
edgar-rft
 
Posts: 154
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Incorrect copying when duplicating line - key binding proble

Postby mmi » Fri May 20, 2011 1:44 pm

Thanks,
both solutions work for me (Emacs 23.1.1, Ubuntu 10.10).
mmi
 
Posts: 2
Joined: Thu May 19, 2011 10:34 am


Return to Emacs Lisp

Who is online

Users browsing this forum: No registered users and 1 guest

cron