I have this code that switch lines up/down:
;; Moving a line up or down
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
(global-set-key [M-S-down] 'move-text-down)
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
(global-set-key [M-S-up] 'move-text-up)
I was wondering if it is possible to tweak the move-text-internal function so it is possible to move part of line "after cursor" up or down.
Here is an example:
Before:
A X B W
Q E O P
If cursor was after X on the first line, after M-S-down:
A X O P
Q E B W
UPDATE:
Thanks to Jordan Biondo for the the his code and function.
I tweaked it to keep line moving as long as you keep invoking the command.
(defun flip-text (&optional arg)
"Flip the text from point to the end of the current line with the text
in the next line from the same column to the end of the next line.
With a prefix arg, flip text with the line above the current."
(interactive "p")
(save-excursion
(let ((tt (delete-and-extract-region (point) (point-at-eol)))
(c (current-column)))
(forward-line arg)
(move-to-column c)
(insert tt)
(let ((ot (delete-and-extract-region (point) (point-at-eol))))
(forward-line (- arg))
(goto-char (point-at-eol))
(insert ot)
))
)
(previous-line (- arg))
)
(global-set-key (kbd "C-M-z") (lambda ()
(interactive)
(flip-text 1)))
(global-set-key (kbd "C-M-c") (lambda ()
(interactive)
(flip-text -1)))
This will do what you specified but does not do multiple lines.
(defun flip-text-to-eol (&optional up)
"Flip the text from point to the end of the current line with the text
in the next line from the same column to the end of the next line.
With a prefix arg, flip text with the line above the current."
(interactive "P")
(save-excursion
(let ((tt (delete-and-extract-region (point) (point-at-eol)))
(c (current-column)))
(forward-line (if up -1 1))
(move-to-column c)
(insert tt)
(let ((ot (delete-and-extract-region (point) (point-at-eol))))
(forward-line (if up 1 -1))
(goto-char (point-at-eol))
(insert ot)))))
Related
I have this snippet of code in my .emacs file that should move lines of code up or down. This works fine on 24.3.1 but not fully on 24.4.
moving lines down work, as the line would be swapped with the bottom line and the "cursor" would move as well.
Moving the line up however, it will swap but the cursor stay on the same line without moving up along with the line.
Is there a reason for that?
;; Moving a line up or down
(defun move-text-internal (arg)
(cond
((and mark-active transient-mark-mode)
(if (> (point) (mark))
(exchange-point-and-mark))
(let ((column (current-column))
(text (delete-and-extract-region (point) (mark))))
(forward-line arg)
(move-to-column column t)
(set-mark (point))
(insert text)
(exchange-point-and-mark)
(setq deactivate-mark nil)))
(t
(let ((column (current-column)))
(beginning-of-line)
(when (or (> arg 0) (not (bobp)))
(forward-line)
(when (or (< arg 0) (not (eobp)))
(transpose-lines arg))
(forward-line -1))
(move-to-column column t)))))
(defun move-text-down (arg)
"Move region (transient-mark-mode active) or current line
arg lines down."
(interactive "*p")
(move-text-internal arg))
;(global-set-key [M-S-down] 'move-text-down)
(global-set-key [A-M-down] 'move-text-down)
(defun move-text-up (arg)
"Move region (transient-mark-mode active) or current line
arg lines up."
(interactive "*p")
(move-text-internal (- arg)))
;(global-set-key [M-S-up] 'move-text-up)
(global-set-key [A-M-up] 'move-text-up)
I'd like to be able to toggle the case of the letter under the point. To that end, I wrote this:
(defun toggle-case-next-letter ()
"Toggles the case of the next letter, then moves the point forward one character"
(interactive)
(let* ((p (point))
(upcased (upcasep (char-after)))
(f (if upcased 'downcase-region 'upcase-region)))
(progn
(f p (+ 1 p))
(forward-char))))
However, when I run it (I've bound it to M-#), I get progn: Symbol's function definition is void: f. I assume this means f isn't bound, but I'm not sure.
Upcasep is defined as:
(defun upcasep (c) (eq c (upcase c)))
Is the problem in the let binding, or something else? (Also, if there's a better way to do this, that'd be nice as well).
Note that originally I had (upcased (upcasep (buffer-substring-no-properties p (+ 1 p)))), which I've corrected to (upcased (upcasep (char-after)), because using upcasep as defined above is always nil for strings (so I couldn't downcase again).
You've got a typical case of lisp-1 / lisp-2 confusion. Here's a fix (just a funcall):
(defun toggle-case-next-letter ()
"Toggles the case of the next letter, then moves the point forward one character"
(interactive)
(let* ((p (point))
(upcased (char-upcasep (buffer-substring-no-properties p (+ 1 p))))
(f (if upcased 'downcase-region 'upcase-region)))
(progn
(funcall f p (+ 1 p))
(forward-char))))
And here's what I have:
(global-set-key (kbd "C->") 'upcase-word-toggle)
(global-set-key (kbd "C-z") 'capitalize-word-toggle)
(defun char-upcasep (letter)
(eq letter (upcase letter)))
(defun capitalize-word-toggle ()
(interactive)
(let ((start (car
(save-excursion
(backward-word)
(bounds-of-thing-at-point 'symbol)))))
(if start
(save-excursion
(goto-char start)
(funcall
(if (char-upcasep (char-after))
'downcase-region
'upcase-region)
start (1+ start)))
(capitalize-word -1))))
(defun upcase-word-toggle ()
(interactive)
(let ((bounds (bounds-of-thing-at-point 'symbol))
beg end
regionp)
(if (eq this-command last-command)
(setq regionp (get this-command 'regionp))
(put this-command 'regionp nil))
(cond
((or (region-active-p) regionp)
(setq beg (region-beginning)
end (region-end))
(put this-command 'regionp t))
(bounds
(setq beg (car bounds)
end (cdr bounds)))
(t
(setq beg (point)
end (1+ beg))))
(save-excursion
(goto-char (1- beg))
(and (re-search-forward "[A-Za-z]" end t)
(funcall (if (char-upcasep (char-before))
'downcase-region
'upcase-region)
beg end)))))
I couldn't get #abo-abo's answer working for me but using his comments I was able to google better and found the following at http://chneukirchen.org/dotfiles/.emacs
(defun chris2-toggle-case ()
(interactive)
(let ((char (following-char)))
(if (eq char (upcase char))
(insert-char (downcase char) 1 t)
(insert-char (upcase char) 1 t)))
(delete-char 1 nil)
(backward-char))
(global-set-key (kbd "M-#") 'chris2-toggle-case)
This answers the original question if you remove (backward-char).
I realize this is a very old question, but having stumbled upon the same problem recently, I'd like to suggest a simpler solution.
I start with a pure function for toggling character case, based on char code property inspection:
(cl-defun toggle-char-case (c)
(cl-case (get-char-code-property c 'general-category)
(Lu (downcase c))
(Ll (upcase c))
(t c)))
I then use it from within an interactive function operating at point:
(cl-defun toggle-char-case-at-point ()
(interactive)
(let ((new (toggle-char-case (char-after))))
(delete-char 1)
(insert new)))
I then bound this interactive function to a keybinding of my choice:
(global-set-key (kbd "C-M-c") 'toggle-char-case-at-point)
The way this function operates is, after toggling the case it advances the point by one. So calling it repeatedly will toggle the cases of a sequence of chars. One could make it keep the point unchanged - that would require adding (backward-char) to the body.
I have been unable to come up with a method to test for a syntax condition without moving the cursor -- e.g., skip-syntax-forward and skip-chars-forward both move the cursor in order to return t or a positive value. How can I return t or nil without moving the cursor?
(defun lawlist-kill-word ()
"Mark word / symbol + whitespace to the right of the cursor, and kill same."
(interactive)
(let* (
(symbol-regexp "\\s.\\|\\s_")
(word-regexp "\\sw"))
(modify-syntax-entry ?' "_") ;; apostrophe = symbol constituent
(cond
((< 0 (skip-syntax-forward "_."))
(let ((end (point)))
(set-mark end)
(while (looking-back symbol-regexp)
(backward-char))
(let ((beg (point)))
(delete-region beg end)
(setq beg (point))
(cond
((skip-chars-forward " \t")
(setq end (point))
(set-mark end)
(delete-region beg end))))))
((< 0 (skip-syntax-forward "w"))
(let ((end (point)))
(set-mark end)
(while (looking-back word-regexp)
(backward-char))
(let ((beg (point)))
(delete-region beg end)
(setq beg (point))
(cond
((skip-chars-forward " \t")
(setq end (point))
(set-mark end)
(delete-region beg end))))))
(t
(let ((beg (point)))
(set-mark beg)
(skip-chars-forward " \t")
(let ((end (point)))
(delete-region beg end)))
(deactivate-mark)))
(modify-syntax-entry ?' "w") )) ;; apostrophe = word constituent
EDIT: lawlist-kill-word is a work in progress -- any updates to this function will be posted to a thread related to that issue -- i.e.,: Emacs: delete whitespaces or a word
As #Tobias said: wrap cursor movements in save-excursion. Save any values you want (e.g., of (point)) in variables and return them as needed.
E.g., if you want the position four lines ahead, do something like this:
(let ((posn (save-excursion (forward-line 4) (point))))
posn)
I want to define two key-bindings to indent/unindent region by 4 spaces.
Before:
hello
world
foo
bar
Visually select world and foo.
Type >
After:
hello
world
foo
bar
I also want to bind < to unindent region.
I'm not familiar with emacs, please help.
There are already keyboard shortcuts for that:
Indent: C-u 4 C-x TAB
Unindent C-u - 4 C-x TAB
If you find that too long to type, you could put the following in your .emacs file:
(defun my-indent-region (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N 4))
(setq deactivate-mark nil))
(self-insert-command N)))
(defun my-unindent-region (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N -4))
(setq deactivate-mark nil))
(self-insert-command N)))
(global-set-key ">" 'my-indent-region)
(global-set-key "<" 'my-unindent-region)
With this code the greater than (>) and less than (<) keys will indent/unindent a marked region by 4 spaces each.
(defun keyboard-indent (&optional arg)
(interactive)
(let ((deactivate-mark nil)
(beg (or (and mark-active (region-beginning))
(line-beginning-position)))
(end (or (and mark-active (region-end)) (line-end-position))))
(indent-rigidly beg end (* (or arg 1) tab-width))))
(defun keyboard-unindent (&optional arg)
(interactive)
(keyboard-indent (* -1 (or arg 1))))
In addition to what #Thomas already wrote, you might not want to use the keys < and > for indenting or unindenting. Just image you need to write some HTML and can't enter those characters anymore. This is why I inserted the following in my init file, as key settings:
(global-set-key (kbd "C-<") 'my-indent-region)
(global-set-key (kbd "C->") 'my-unindent-region)
Note: It doesn't work without the (kbd ...). You will get an error:
global-set-key: Key sequence C - > starts with non-prefix key C
You can use replace 4 with tab-width as
(defun indent-region-shift-right-n (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N tab-width))
(setq deactivate-mark nil))
(self-insert-command N)))
(defun unindent-region-shift-left-n (N)
(interactive "p")
(if (use-region-p)
(progn (indent-rigidly (region-beginning) (region-end) (* N (- tab-width)))
(setq deactivate-mark nil))
(self-insert-command N)))
(global-set-key ">" 'indent-region-shift-right-n)
(global-set-key "<" 'unindent-region-shift-left-n)
right now I have a keyboard macro defined and named, and i want to make a lisp function which goes to the top of the buffer, and does:
i = 1
do{
run macro
if macro hit the end of the buffer, break out of the loop
insert i
i++
}while(true)
here's what's in my .emacs
(fset 'next-id
(lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([19 73 68 61 34 13 67108896 19 34 13 2 23] 0 "%d")) arg)))
(global-set-key (kbd "C-x n") 'next-id)
how would I go about this?
Srsly. Here's how to do it: C-u 0 F4
This should do the trick:
(defun apply-macro-to-buffer (&optional macro)
"Apply last keyboard macro to the buffer"
(interactive "CEnter the name of the macro to apply: ")
(or macro
(progn
(if (null last-kbd-macro)
(error "No keyboard macro has been defined"))
(setq macro last-kbd-macro)))
(let ((end-marker (copy-marker (point-max)))
(i 1))
(save-excursion
(goto-char (point-min))
(while (and (< (point) end-marker))
(let ((mark-active nil))
(execute-kbd-macro macro))
(insert (format "%d\n" i))
(setq i (1+ i))))))
To do the same for a regular command, try this:
(defun apply-command-to-buffer (command)
"Apply a command to the buffer"
(interactive "CEnter the name of the command to apply: ")
(let ((end-marker (copy-marker (point-max)))
(i 1))
(save-excursion
(goto-char (point-min))
(while (and (< (point) end-marker))
(call-interactively command)
(insert (format "%d\n" i))
(setq i (1+ i))))))