Delete until whitespace in Emacs - emacs

Is there an Emacs function to delete (forward or backwards) until the first whitespace? For example, I have the following line, and the cursor is marked by the caret:
someword ?(&)!* morewords
^
I want to delete the backwards the sequence of non-alphanumeric characters, but not the word someword. Using backward-delete-word will wipe out the word as well. The same is with the cursor before the weird characters and kill-word.

emacs has the function zap-to-char which will delete everything up to a specific character. So, this won't work for all whitespace but if your specific problem is everything up to a space you can use this function. Give the function a negative argument to zap backwards.

I don't know of any function, but it's easy enough to make one:
(defun my-delete-backward-to-ws ()
(interactive)
(delete-region (point) (save-excursion (skip-syntax-backward "^ ") (point))))

Related

How to instruct Emacs auto-capitalize-mode to automatically lowercase any word that follows e.g. or i.e.?

Emacs auto-capitalize-mode misinterprets the words i.e. and e.g. to signify the end of a sentence, and, accordingly, erroneously capitalizes any word that follows them.
Does anyone have a function that can be called by entering, say, eg or ie, that will insert the characters e.g. and i.e. and then automatically lowercase whatever word gets typed next?
Bonus: Do the same thing... for ellipses.
Add this to your .emacs:
(setq auto-capitalize-predicate
(lambda () (not (looking-back
"\\([Ee]\\.g\\|[Ii]\\.e\\)\\.[^.]*" (- (point) 20)))))
Remember that the I in i.e. will be capitalized to I.e if your
auto-capitalize-words variable is set to contain “I”.
(setq auto-capitalize-words '()) This sets it to nothing.
Here’s a version that also deals with ellipses:
(setq auto-capitalize-predicate
(lambda () (not (looking-back
"\\([Ee]\\.g\\|[Ii]\\.e\\|\\.\\.\\)\\.[^.]*" (- (point) 20)))))
But you might want to look into some abbrev magic that turns three periods into a unicode ellipsis instead. It's up to you.
From auto-capitalize.el:
;; To prevent a word in the `auto-capitalize-words' list from being
;; capitalized or upcased in a particular context (e.g.
;; "GNU.emacs.sources"), insert the following whitespace or
;; punctuation character with `M-x quoted-insert' (e.g. `gnu C-q .').
I use it and it is a comfortable approach.

Elisp: Old variable values seem to stick

Beginner question for emacs lisp.
In my .emacs I have written the following:
(defun line-text-up-with-parentheses-above()
(interactive)
(line-text-up-with-char-above "("))
(defun line-text-up-with-char-above(charval)
(interactive)
(setq now-point (point))
(previous-line)
(setq above-point (point))
(forward-char)
(search-forward charval (line-end-position) nil)
(setq above-paren (point))
(goto-char now-point)
(insert (make-string (- above-paren above-point) ? )))
(global-set-key (kbd "\<C-S-iso-lefttab>") 'line-text-up-with-parentheses-above)
The function intends to line the text at the point up with the character after the "(" on the line above it.
Everything seem to work fine, unless the function is called twice in a row. In this case, the text before the point advances exactly the same amount as last time.
Seems like the variables aren't being set the second time around.
Does anyone know how to fix this?
Many thanks!
You calculate the intended indentation. However, you always insert it regardless of how many spaces the current line contains.
You could either simply delete the spaces on the current line before inserting the new spaces, or you could try to calculate the number of spaces needed and insert or delete, as needed.
Some hints:
By using setq you are using global variables, try to bind them using let.
Instead of recording where the point is before you move it around and restore it afterwards, you could use the special construct save-excursion.
I think the variables are being set correctly (although Lindydancer is correct to suggest let instead of setq). And your function works fine for me if I call it with point at the first non-whitespace character on the line you want to 'line up'. The only problem I see is that the function lines up with wherever point is when you call it, which is not correct if point is not at the first non-whitespace character.
You can fix this be adding (back-to-indentation) immediately after (interactive) in line-text-up-with-char-above. Actually, once you wrap everything in save-excursion you'll want to add back-to-indentation as the first function within the save-excursion form.
Protip: align and specifically align-regexp.

Arbitrary characters for forward-word/backward-word in Emacs

How to add an arbitrary character (hyphen, for example) to forward/backward-word functionality, so Emacs would handle words like "k-vector" as a single word. The same question about double-click on the word.
Syntax tables define which character is considered a word constituent. You can read about it here.
Emacs's notion of "word" is rather fixed and doesn't quite match what you want. You can mess with the syntax-table, but it might break functionality of the major-mode.
AFAICT what you want is to handle what Emacs calls "symbols" rather than "words". E.g. use forward-symbol and backward-symbol commands.
The easiest way to use those other commands might be to enable superword-mode.
Add following to your .emacs file to make hyphen included in words for every major mode:
(add-hook 'after-change-major-mode-hook
(lambda ()
(modify-syntax-entry ?- "w")))
You can use this code it use regular expression it use space or parents as word separator
(defun backward-word-with-dash ()
(interactive)
(search-backward-regexp "[ ()][A-Za-z\-]+ *")
(forward-char))
(defun forward-word-with-dash ()
(interactive)
(search-forward-regexp " *[A-Za-z\-]+[ ()]")
(backward-char))
(global-set-key "\M-b" 'backward-word-with-dash)
(global-set-key "\M-f" 'forward-word-with-dash)
if you want other characters just add it to the regex

Emacs Command to Delete Up to Non-Whitespace Character

I often want to make a multiline function call and reduce it down to one line. For example, convert...
function_call(
'first_arg',
'second')
to
function_call('first_arg', 'second')
Does emacs have some commands to help with this. Specifically, is there a command that will delete all whitespace from the point to the first non-whitespace character?
You might try delete-indentation, my favorite command for joining multiple lines into one line. In your example, put the cursor on the line with "second" and hit M-^ twice. Here are the docs:
M-^ runs the command delete-indentation, which is an interactive compiled Lisp function in simple.el.
It is bound to M-^.
(delete-indentation &optional arg)
Join this line to previous and fix up whitespace at join. If there is a fill prefix, delete it from the beginning of this line. With argument, join this line to following line.
Take a look at the fixup-whitespace function. It comes with Emacs, in simple.el. Its docs are:
Fixup white space between objects around point.
Leave one space or none, according to the context.
A similar function, just-one-space, that
Deletes all spaces and tabs around point, leaving one space
is typically bound to M-SPC.
Specifically, is there a command that will delete all whitespace from the point to the first non-whitespace character?
There's a command that does almost that:
M-\ runs the command delete-horizontal-space
which is an interactive compiled Lisp function in `simple.el'.
It is bound to M-\.
(delete-horizontal-space &optional backward-only)
Delete all spaces and tabs around point.
If backward-only is non-nil, only delete them before point.
You can always use M-z to delete upto a character.
For eg in your case:
M-z ' to delete upto the single quote (unfortunately this will delete the single quote as well, but that is a minor inconvenience).
I use the following macro to "pull" the next line onto the end of the current line, compressing whitespace.
(defun pull-next-line()
(interactive)
(move-end-of-line 1)
(kill-line)
(just-one-space))
This is exactly the opposite of #jrockway's move-line-up and of delete-indentation, which I find more natural. The just-one-space command in the macro is exactly #Mike's M-SPACE.
I bind pull-next-line to M-J (in analogy with Vim's J, for "join", command) using the following in my .emacs.
(global-set-key (kbd "M-J") 'pull-next-line)
Example. Calling pull-next-line on the first line of
function_call(
'first_arg',
'second')
yields
function_call( 'first_arg',
'second')
Calling it a second time yields
function_call( 'first_arg', 'second')
Alt-space will reduce a string of whitespace to a single space character, but it won't delete the newline. Still, that should help a little.
To delete everything from point to the first non-whitespace (or newline), type a non-whitespace char, Alt-space, backspace (to remove final whitespace char), then backspace (to delete the char you added.
To turn the multi-line function declaration into a single-line declaration, use a combination of Alt-space, backspace, and Alt-E (goto-endofline) commands.
A rather drastic way of doing this is Hungry-Delete mode:
Hungry-Delete is a minor-mode that causes deletion to delete all whitespace in the direction you are deleting.
A slightly different approach would be creating a keyboard macro to do the job for you.
so, for creating the macro stage a general scenario like so:
foo
bar
[a line with "foo" then a couple of lines later and with some white spaces, write "bar"]
then standing anywhere between foo and bar, do the following:
C-x ( ; start recording macro
M-b ; move backwards to the beginning of foo
END ; move to the end of foo
C-space ; place mark
C-M-f ; move to the end of bar
HOME ; move to the beginning of the line
C-w ; yank out all the white space
M-SPACE ; leave only one space
C-x ) ; end recording the macro
M-x name-last-kbd-macro ; name it, call it jline or something
Now you can always remove all whitespace between two words with M-x one-line
Make sure you remember to save your keyboard macro by issuing M-x insert-kbd-macro somewhere in your .emacs file - this is how it looks:
(fset 'jline
[?\M-b end ?\C- ?\C-\M-f home ?\C-w escape ? ])
I do this:
(defun move-line-up ()
"Removes leading spaces from the current line, and then moves
the current line to the end of the previous line."
(interactive)
(let (start end)
(save-excursion
(beginning-of-line)
; get first non-space character, only look on this line
(let ((search-end (save-excursion (end-of-line) (point))))
(re-search-forward "[^[:space:]]" search-end))
(setq end (1- (point)))
(previous-line)
(end-of-line)
(setq start (point))
(delete-region start end))
(goto-char start)))
(defun move-next-line-up ()
"Moves the next line to the end of the current line"
(interactive)
(next-line)
(move-line-up))
And bind these as:
(global-set-key (kbd "C-x ,") 'move-line-up)
(global-set-key (kbd "C-x .") 'move-next-line-up)
So to solve your problem, on the line that says "second)", just run C-x , C-x ,
If you want all of your deletes to act that way, you might check out greedy-delete.

Smart home in Emacs

Can you have smart behavior for the home key in Emacs? By smart I mean that instead of going to the character number 0, it should go to the first non-blank character, and go to 0 on a second pressing, and back to the first non-blank in a third and so on.
Having smart end would be nice as well.
(defun smart-beginning-of-line ()
"Move point to first non-whitespace character or beginning-of-line.
Move point to the first non-whitespace character on this line.
If point was already at that position, move point to beginning of line."
(interactive "^") ; Use (interactive) in Emacs 22 or older
(let ((oldpos (point)))
(back-to-indentation)
(and (= oldpos (point))
(beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
I'm not quite sure what smart end would do. Do you normally have a lot of trailing whitespace?
Note: The major difference between this function and Robert Vuković's is that his always moves to the first non-blank character on the first keypress, even if the cursor was already there. Mine would move to column 0 in that case.
Also, he used (beginning-of-line-text) where I used (back-to-indentation). Those are very similar, but there are some differences between them. (back-to-indentation) always moves to the first non-whitespace character on a line. (beginning-of-line-text) sometimes moves past non-whitespace characters that it considers insignificant. For instance, on a comment-only line, it moves to the first character of the comment's text, not the comment marker. But either function could be used in either of our answers, depending on which behavior you prefer.
This works with GNU Emacs, I didn't tried it with XEmacs.
(defun My-smart-home () "Odd home to beginning of line, even home to beginning of text/code."
(interactive)
(if (and (eq last-command 'My-smart-home)
(/= (line-beginning-position) (point)))
(beginning-of-line)
(beginning-of-line-text))
)
(global-set-key [home] 'My-smart-home)
Thanks for this handy function. I use it all the time now and love it. I've made just one small change:
(interactive)
becomes:
(interactive "^")
From emacs help:
If the string begins with ^' andshift-select-mode' is non-nil, Emacs first calls the function `handle-shift-select'.
Basically this makes shift-home select from the current position to the start of the line if you use shift-select-mode. It's especially useful in the minibuffer.
Note that there is already a back-to-indentation function which does what you want the first smart-home function to do, i.e. go to the first non-whitespace character on the line. It is bound by default to M-m.
There is now a package that does just that, mwim (Move Where I Mean)
My version: move to begining of visual line, first non-whitespace, or beginning of line.
(defun smart-beginning-of-line ()
"Move point to beginning-of-line or first non-whitespace character"
(interactive "^")
(let ((p (point)))
(beginning-of-visual-line)
(if (= p (point)) (back-to-indentation))
(if (= p (point)) (beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
(global-set-key "\C-a" 'smart-beginning-of-line)
The [home] and "\C-a" (control+a) keys:
Move the cursor (point) the the beginning of the visual line.
If it is already at the beginnng of the visual line, then move it to first non-whitespace character of the line.
If it is already there, then move it to the beginning of the line.
While moving, keep the region (interactive "^").
This is taken from #cjm and #thomas; then I add the visual line stuff. (Sorry for my broken English).
I adapt #Vucovic code to jump to beggining-of-line first:
(defun my-smart-beginning-of-line ()
"Move point to beginning-of-line. If repeat command it cycle
position between `back-to-indentation' and `beginning-of-line'."
(interactive "^")
(if (and (eq last-command 'my-smart-beginning-of-line)
(= (line-beginning-position) (point)))
(back-to-indentation)
(beginning-of-line)))
(global-set-key [home] 'my-smart-beginning-of-line)