How to make the tilde overwrite a space in Emacs? - emacs

I'd like (in TeX-related modes) the tilde key to insert itself as usual if point is on anything (in particular a line end), but if a point is on space, I'd like the tilde to overwrite it. (This would be a quite useful feature after pasting something into TeX source file.) I hacked something like this:
(defun electric-tie ()
"Inserts a tilde at point unless the point is at a space
character, in which case it deletes the space first."
(interactive)
(while (equal (char-after) 32) (delete-char 1))
(while (equal (char-before) 32) (delete-char -1))
(insert "~"))
(add-hook 'TeX-mode-hook (lambda () (local-set-key "~" 'electric-tie)))
My questions are simple: is it correct (it seems to work) and can it be done better? (I assume that if the answer to the first question is in the affirmative, the latter is a question of style.)

As mentioned, it's better to use a "character" literal than a number literal. You have the choice between ? , ?\ , and ?\s where the last one is only supported since Emacs-22 but is otherwise the recommended way, since it's (as you say) "more easily visible" and also there' no risk that the space char will be turned into something else (or removed) by things like fill-paragraph or whitespace trimming.
You can indeed use eq instead of equal, but the difference is not important.
Finally, I'd call (call-interactively 'self-insert-command) rather than insert by hand, but the difference is not that important (e.g. it'll let you insert 3 tildes with C-u ~).

Some points:
Instead of 32 use ?  (question-mark space) to express character literal.
Instead of defining keys in the major-mode hooks, do it in an eval-after-load block. The difference is that major-mode hook runs every time you use the major-mode, but there is only one keymap per major-mode. So there is no point in repeatedly redefining a key in it.
see: https://stackoverflow.com/a/8139587/903943
It looks like this command should not take a numeric argument, but it's worth understanding interactive specs to know how other commands you write can be made to be more flexible by taking numeric arguments into consideration.
One more note about your new modifications:
Your way to clear spaces around point is not wrong, but I'd do this:
(defun foo ()
(interactive)
(skip-chars-forward " ")
(delete-region (point) (+ (point) (skip-chars-backward " "))))

Related

End function on successful function call, or evaluate for function

I apologize for the title.
I have a control flow issue. I would like to call just one of two functions. I put calls to both inside another function. If I could evaluate for either's value, then I could call or not call the next based on that value; if there were a return value associated with each call based on whether or not they actually did something it could be used in a conditional branch. Alternatively, if I knew a value for the character preceding the carat, that could act as an argument for the function.
I don't know how to do find these values.
My actual code is nearly simplest case. It is as follows:
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(delete-horizontal-space 4)
(delete-backward-char))
(global-set-key "\d" 'rad-delete-backward-char-indent)
I would like to delete either one character, or all preceding white-space up to four spaces worth. Currently, I am deleting up to four white-spaces and a character. i.e.
"foo___^" << "fo^"
As opposed to:
"foo___" << "foo^"
Drew answered the essential question. The solution I used was to evaluate for the preceding character to the pointer using preceding-char generic function.
(defun rad-delete-backward-char-indent ()
"Delete one character or up to one tab worth of white space"
(interactive)
(setq first_char (string (preceding-char)))
(setq i 0)
(while (not (= i 4))
(if (string= " " (string (preceding-char)))
(delete-backward-char 1))
(setq i (1+ i)))
(unless (string= " " first_char)
(delete-backward-char 1)))
(global-set-key "\d" 'rad-delete-backward-char-indent)
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(if <SOMETHING>
(delete-horizontal-space 4)
(delete-backward-char))
But it's not clear what the <SOMETHING> is that you want to test.
You say "If I could evaluate for either's value, then I could call or not call the next based on that value." I don't understand that sentence. Could you say it another way? Just what do you want to test, to know which code to evaluate?
What do you mean by evaluate for either's value?
While I think Drew's answer is your better choice, another solution, maybe closer to what you thought you wanted, is to check whether the first function changed something:
(defun rad-delete-backward-char-indent ()
"Delete one character or up to indent's worth of white space"
(interactive)
(let ((start (buffer-chars-modified-tick)))
(delete-horizontal-space 4)
(when (eq (buffer-chars-modified-tick) start)
(delete-backward-char))))
By the way, I don't think the 4 above does what you want. It does the same as any other non-nil value: it tells delete-horizontal-space to only delete backwards, but it doesn't bound the number of spaces it will remove.

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.

Emacs: Assign a function to a keybinding, and with repeated presses, undo the last press and redo at a wider setting

Here's the bigger picture of what I'm trying to do:
With a keypress, it will insert an opening and closing parenthesis right after/before the innermost closing/opening delimiter (bracket, brace, parenthesis, whatever).
But if it is pressed immediately after, it will undo the last insertions, seek out the next closing delimiter, and put it after that, and so on.
I have a working version of the first part, but am looking for "best practices" for the second part (where it undoes and moves outwards)
As a motivator and concrete example, this is a typical scenario when coding in Python. I work with list comprehensions a lot, and often I construct the list, and then decide I want to sum all elements, etc. So I would first type:
[x*x for x in some_lst if is_prime(x)]
and then I'll want to encapsulate this list with a "sum" command:
sum([x*x for x in some_lst if is_prime(x)])
I don't want to have to keep moving the cursor to both the beginning and the end just to insert the parentheses. I'd rather have the point in the list, press a keystroke, have it figure out the delimiters, and place the mark just before the opening inserted parenthesis so that I can type "sum". My function below seems to work (piggybacking on the "expand-region" package):
(defun add-paren ()
(interactive)
(er/mark-outside-pairs)
(exchange-point-and-mark)
(insert-string ")")
(exchange-point-and-mark)
(insert-string "(")
(left-char 1)
)
What's the best practice for the 2nd step?
(Any suggestions/improvements to the above would also be appreciated. This is my first "real" function in Elisp.)
Thanks.
Update: Thanks everyone for the tips. I'll probably use some of them in my final solution. My original question still stands: Is there a standard pattern of "undoing and redoing at a larger scale", or will each problem have its own custom solution? Suppose I use smartparens as suggested to do it all in one keystroke, but I want it to occur on the 3rd level out. What I want is to press the keystroke 3 times and have it place the parentheses there.
So after the first keystroke, it places the parentheses at the innermost level. Pressing it again should remove the inserted parentheses, and place them in the next level up, and so on...
(BTW, not trying to reinvent the wheel. I suspect some of the packages listed may have exactly what I need - I just want practice coding in Elisp).
Update 2:
I guess there is no best practice for this? Anyway, I solved the problem using both expand-region and smartparens:
(defun add-paren ()
(interactive)
(if (eq last-command 'add-paren)
;; (message "AAAA")
(delete-paren)
)
(setq currpoint (point))
(er/mark-outside-pairs)
(if (eq currpoint (point))
(er/mark-outside-pairs)
)
(sp-wrap-with-pair "(")
(left-char 1)
)
(global-set-key (kbd "<f5>") 'add-paren)
(defun delete-paren ()
(interactive)
(setq currloc (point))
(sp-unwrap-sexp)
(goto-char currloc)
(left-char 1)
)
You're already using expand-region. Why not combine that with one of the many "surround region with..." modes?
I personally like smartparens (available via Marmalade or MELPA), but there are many other similar tools.
Use er/expand-region until you've got an appropriate selection, then
( to wrap in parentheses.
When programming, there are several hundred slightly different edit-tasks of this kind. Therefor created a toolkit for it.
In example given, the form might be described as delimited, more precisely bracketed.
ar-bracketed-atpt would mark it.
It's set here like this:
(global-set-key [(super \])] 'ar-bracketed-atpt)
Then comes in another class of commands which do several things on active region. In this case:
M-x ar-parentize-or-copy-atpt RET
It is bound to C-c )
A tarball for all this stuff is available here:
https://launchpad.net/s-x-emacs-werkstatt/
FWIW, I'd do it as follows:
go before the open bracket.
type sum C-M-SPC (
The C-M-SPC selects the parenthesized (well, "bracketized") expression, and the subsequent ( wraps it in parens (because of electric-pair-mode).
I guess there is no best practice for this? Anyway, I solved the problem using both expand-region and smartparens:
(defun add-paren ()
(interactive)
(if (eq last-command 'add-paren)
;; (message "AAAA")
(delete-paren)
)
(setq currpoint (point))
(er/mark-outside-pairs)
(if (eq currpoint (point))
(er/mark-outside-pairs)
)
(sp-wrap-with-pair "(")
(left-char 1)
)
(global-set-key (kbd "<f5>") 'add-paren)
(defun delete-paren ()
(interactive)
(setq currloc (point))
(sp-unwrap-sexp)
(goto-char currloc)
(left-char 1)
)

difference between calling command directly and using keybinding

I'm new to elisp, so please forgive me if the following approach is totally clumsy.
In the team I'm currently working with, there is an usual convention of closing python blocks with a pass statement (if they aren't ended by closing keywords like else or except or such). While unusual, this has the advantage that one can always recover the original indentation of the program if it is unintentionally changed (using emacs indent-region).
To get existing code in line with this convention, I wrote a small elisp function:
(defun python-check-indent ()
"Check if automatic indentation changes current indent, insert pass keyword if it does."
(interactive)
(move-beginning-of-line 1)
(skip-chars-forward " ")
(if
(< 0
(let (original)
(setq original (point))
(indent-for-tab-command)
(- (point) original)
)
)
(progn
(insert "pass")
(newline)
(indent-for-tab-command)
)
)
(next-line)
)
(global-set-key (kbd "C-`") 'python-check-indent)
The idea is simply to test whether hitting TAB would change the indentation, and insert a pass statement in that case. To facilitate processing longer blocks of code, it then advances to the next line.
When I run it using M-x python-check-indent, it does what I want (except that it moves around empty lines slightly), also when running it repeatedly to process several lines. However, when I run it repeatedly using the C-` keybinding, it starts messing up the code from the second invocation on.
So here are my questions: What is the difference between invoking a command with M-x ... and using its keybinding? And how could I change the function to be not affected by this difference?
emacs-version: GNU Emacs 23.3.1 (x86_64-apple-darwin, NS apple-appkit-1038.35) of 2011-03-10 on black.porkrind.org
(edit) current workaround: I'm now wrapping it inside a keyboard-macro, so it's "bound" to C-x e, and behaves properly.
The general rule is that it is best to avoid complex interactive
commands in your functions because they could be affected by all sorts
of options.
(defun python-check-indent ()
"Check if automatic indentation changes current indent, insert pass keyword if it does."
(interactive)
(goto-char (line-beginning-position))
(skip-chars-forward " ")
(when (< 0
(let (original)
(setq original (point))
(python-indent-line)
(- (point) original)))
(insert "pass\n")
(python-indent-line))
(forward-line))
However, even this is probably not good because python-indent-line's behavior depends on last-command and python-indent-trigger-commands. I think it would be best if you replaced the first invocation of python-indent-line with the code which computes the target indentation instead of actually indenting, something like (nth python-indent-current-level python-indent-levels).
PS. If you still have problems, I suggest that you use edebug and step through the function.

Changing Paredit Formatting

When using paredit in programming modes such as C, typing ( will insert a space before the paren when I'm trying to call a function, leaving me with:
foo ()
Is there a way to disable the insertion of the space without changing paredit's source?
Well, the way paredit appears to work is that it checks the syntax tables to see if you're inserting a pair right after a word/symbol/etc., in which case it forces a space to be inserted. You need to override that functionality - which can be done a number of different ways: advice, redefine the function determining space, changing the syntax table, etc.
I'd try the straight forward:
(defun paredit-space-for-delimiter-p (endp delimiter)
(and (not (if endp (eobp) (bobp)))
(memq (char-syntax (if endp (char-after) (char-before)))
(list ?\" ;; REMOVED ?w ?_
(let ((matching (matching-paren delimiter)))
(and matching (char-syntax matching)))))))
This will obviously apply to all places where you use paredit. If you want something more mode specific, you can add some conditions to that and statement (e.g. (and ... (memq major-mode '(c-mode lisp-mode)))).
So... I guess I did change the "source", but you can do the same thing with a piece of defadvice ... it's all elisp, so the difference is minimal. There doesn't appear to be a setting to control this type of behavior.
See paredit-space-for-delimiter-predicates
Well, Paredit is ideal for editing languages built of S-expressions. If you just like how it automatically inserts the closing paren, use feature skeleton-pair.
(setq skeleton-pair t)
(global-set-key "(" 'skeleton-pair-insert-maybe)