Emacs Command to Delete Up to Non-Whitespace Character

Viewed 17040

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?

10 Answers

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.

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.

Related