Wednesday, March 23, 2011

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?

From stackoverflow
  • 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.

  • 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.

    This function is typically bound to M-Space.

    Chris Conway : M-SPACE is "just-one-space" not "fixup-whitespace". They seem to do pretty much the same thing, though.
  • 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.

  • 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 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 ,

  • 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.

  • If you want all of your deletes to act that way, you might check out greedy-delete.

  • 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')
    
  • 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 ? ])
    
  • 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.

0 comments:

Post a Comment