(ELisp) automatically nesting next line using brace return - emacs

I'm completely new to both Lisp and Emacs. In Emacs, when coding in Java for example, I want to be able to type "{" then hit "ENTER" and have the next line be ready for whatever is nested in the braces. For example, if I have the following line:
public void method()
and I type "{" then hit return I should get this:
public void method() {
// indentation applied, no additional tabbing necessary
}
I'm already able to insert by pairs, for example, typing "{" gives "{}" with my cursor between the braces. I did this by adding these lines to the emacs init file:
;; insert by pairs (parens, quotes, brackets, braces)
(defun insert-pair (leftChar rightChar)
(if (region-active-p)
(let (
(p1 (region-beginning))
(p2 (region-end))
)
(goto-char p2)
(insert rightChar)
(goto-char p1)
(insert leftChar)
(goto-char (+ p2 2))
)
(progn
(insert leftChar rightChar)
(backward-char 1) ) )
)
(defun insert-pair-brace () (interactive) (insert-pair "{" "}") )
(global-set-key (kbd "{") 'insert-pair-brace)
To get the auto-nesting I described above, I added these lines:
;; automatically nest next line
(defun auto-nest ()
(insert "\n\n")
(backward-char 1)
(insert "\t")
)
(defun auto-nest-brace () (interactive) (auto-nest) )
(global-set-key (kbd "{ RET") 'auto-nest-brace)
When I start up Emacs, however, I get this message:
error: Key sequence { RET starts with non-prefix key {
What am I doing wrong, and what can I do to fix it? I don't want to use a different key combination to do this. There are a lot of text editors in which this auto-nesting is standard, and it should be easy enough to code up in ELisp.

It's great that you are trying to add this functionality to Emacs yourself, but there's no need to reinvent the wheel here. Emacs already has a command for the purpose of auto-indenting; it's called newline-and-indent. It is bound to C-j by default, but you can rebind it to RET
globally:
(global-set-key (kbd "RET") 'newline-and-indent)
for a specific mode only:
(require 'cc-mode)
(define-key java-mode-map (kbd "RET") 'newline-and-indent)
java-mode-map is defined in cc-mode.el and not available by default, that's why you have to require cc-mode before you can modify java-mode-map.
Note that newline-and-indent indents according to major mode. That is, if you're e.g. in java-mode and press RET in some random location that's not meaningful w/r/t Java syntax, it won't insert additional whitespace at the beginning of the new line.
To read all there is to know about newline-and-indent do
C-h f newline-and-indent RET

I have something similar in my emacs config which I have been using for a while. It calls 'newline-and-indent twice then moves the point one line up before indenting correctly. Here is the snippet of code to do this from my config file:
;; auto indent on opening brace
(require 'cc-mode)
(defun av/auto-indent-method ()
"Automatically indent a method by adding two newlines.
Puts point in the middle line as well as indent it by correct amount."
(interactive)
(newline-and-indent)
(newline-and-indent)
(forward-line -1)
(c-indent-line-or-region))
(defun av/auto-indent-method-maybe ()
"Check if point is at a closing brace then auto indent."
(interactive)
(let ((char-at-point (char-after (point))))
(if (char-equal ?} char-at-point)
(av/auto-indent-method)
(newline-and-indent))))
(define-key java-mode-map (kbd "RET") 'av/auto-indent-method-maybe)
Pretty straightforward as you can see. Hopefully it will work for you. I have not used it in any other modes except java.

You want a combination of auto pairs (or alternatives) plus auto indentation. Check out the emacswiki on the former: http://www.emacswiki.org/emacs/AutoPairs
And on the latter:
http://www.emacswiki.org/emacs/AutoIndentation

Related

lexical-binding not being enabled when evaluating .emacs

Here are some excerpts from my .emacs:
(setq lexical-binding t)
;; .emacs
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(diff-switches "-u")
'(tab-always-indent (quote complete)))
;...
(require 'dired)
;...
(dotimes (i 12) (define-key dired-mode-map (kbd (concat "<f" (number-to-string (1+ i)) ">"))
(lambda ()
(interactive)
(goto-char (point-min))
(forward-line (+ 4 i)))))
This should bind keys f1 to f12 in dired-mode to commands that jump to particular files in the list of files (ignoring . and ..). However, initially, after starting emacs, these keys don't work - I get an error message forward-line: Symbol's value as variable is void: i. However, when I go to the top line of my .emacs and press C-x C-e to evaluate that line, and then go to the last line quoted above and press C-x C-e to evaluate that dotimes expression, those function keys start working!
Why is that?
By the way, it also doesn't work if I evaluate the whole buffer.
It turns out that it is necessary to replace
(setq lexical-binding t)
with
;; -*- lexical-binding: t -*-
The manual hints suggestively at this, but does not actually say so outright.

Insert text string into ido minibuffer using non-interactive defun

Need to insert some text in the ido mini-buffer during ido-find-file using a defun bound to a key chord. This behavior is the same as if the following sequence was typed interactively, C-x C-f, followed by C-e to edit the mini-buffer, followed by deleting the current text then typing or yanking the text that I want to insert. To that end I have run this defun and just after ido-find-file:
(global-set-key [f10] 'mytest)
(defun mytest ()
(interactive)
(ido-edit-input) ;#1
(delete-minibuffer-contents) ;#2
(insert "C:/users/family/" )) ;#3
My expectation is that the mini-buffer would contain the given string (#3) after one invocation of mytest. However it seems as if I need to run mytest 2x to get the inserted string into the mini-buffer. After the first invocation the ido mini-buffer is in edit mode, however is as if only the #1 was run (the original text is still present). After the 2nd invocation of mytest the ido mini-buffer seems as if #1, #2 and #3 have been executed.
I am using a stand-alone mini-buffer which is part of the one-on-one library.
Running GNU emacs 24.4 on Windows.
Here is my custom configuration of ido, which I run at emacs startup.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;IDO Config
(setq ido-enable-flex-matching t)
;
(setq ido-everywhere t)
(ido-everywhere 1)
;
(require 'ido)
(ido-mode 1)
;
(setq ido-auto-merge-work-directories-length -1)
;
;https://github.com/gempesaw/ido-vertical-mode.el/blob/master/ido-vertical-mode.el
;; Display ido results vertically, rather than horizontally
(setq ido-decorations (quote ("\n-> " "" "\n " "\n ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
(defun ido-disable-line-trucation ()
(set (make-local-variable 'truncate-lines) nil))
(add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-trucation)
;
(setq ido-ignore-buffers '("\\` " "^\*Mess" "^\*Back" ".*Completion"
"^\*Ido" "^\*trace" "^\*compilation" "^\*GTAGS" "^\*Help" "^session\.*" "^\*"))
;
;use IDO for more things
(setq recentf-max-saved-items 100)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
I have confirmed that the logic is somewhat sound by binding the individual commands then running them interactively. It seems as if running the same defs from lisp is acting differently than running the same interactively.
Ido-edit-input is C-e during ido-find-file
(global-set-key [f11] 'delete-minibuffer-contents)
(global-set-key [f12] (lambda () (interactive) (insert "C:/users/family")))
Also tried inserting (sit-for 1) in the mytest defun on the possibility that there is some timing issue.
How can the defun mytest be modified to insert a string (#3) with a single invocation?
This isn't the answer to the question in the title, but it does do what you apparently want:
(defun my-ido-find-file-in-dir ()
(interactive)
(let ((default-directory "C:/users/family"))
(call-interactively 'ido-find-file)))
(global-set-key [f10] 'my-ido-find-file-in-dir)

Emacs Copy Current Line

For some reason, copying lines in Emacs is very unintuitive and difficult. If I'm doing something wrong here, please let me know. It is surprising that Emacs does not have this by default somewhere.
I am trying to write a function that copies a line. I always used to have:
(global-set-key (kbd "C-x c") "\C-a\C- \C-n\M-w")
This is a little annoying since it copies any new line after the line. I decided to change it to:
(global-set-key (kbd "C-x c") "\M-m\C- \C-e\M-w")
Now, I saw: http://www.emacswiki.org/emacs/CopyingWholeLines and it appears that their copy-line function prints a message with the number of lines it copied. I am trying to insert that message into my global-set-key above but it is not working. Basically, I am unable to run a raw sequence as above in a function. So I conveyed each keystroke into a function and did this:
(defun copy-line ()
(interactive)
(kill-ring-save
(back-to-indentation)
(move-end-of-line 1))
(message "1 line copied"))
;; optional key binding
(global-set-key "\C-c\C-k" 'copy-line)
This however, throws a wrong number of arguments error.
My first question: How can I put (message "1 line copied") into my global-set-key above?
My second question: using the standard copy-line found in the link above:
(defun copy-line (arg)
"Copy lines (as many as prefix argument) in the kill ring"
(interactive "p")
(kill-ring-save (line-beginning-position)
(line-beginning-position (+ 1 arg)))
(message "%d line%s copied" arg (if (= 1 arg) "" "s")))
From the message, it appears that you can have multiple lines copied. However, when selecting multiple lines and copying, only one is copied. Why is the message structured in this way? How can it select multiple lines?
Here's your function, fixed:
(defun copy-line ()
(interactive)
(save-excursion
(back-to-indentation)
(kill-ring-save
(point)
(line-end-position)))
(message "1 line copied"))
The problem was that back-to-indentation doesn't return point.
As for the other function, it will copy multiple lines when called with
a prefix argument, e.g. C-u or M-5.
Here's a shorter version of the simple function:
(defun copy-line ()
(interactive)
(kill-ring-save (point-at-bol) (point-at-eol))
(message "1 line copied"))
For the multiline copy version that you cited, use the prefix to indicate how many lines you want copied (as the other answer suggests). So, with your keybinding of C-c C-k, do the following to copy, say, 3 lines: C-u 3 C-c C-k.

Using 2 consecutive control key in Emacs [duplicate]

Let's say I bind the key to a certain function as follows:
(global-set-key (kbd "C-c =") 'function-foo)
Now, I want the key binding to work as:
After I press C-c = for the first time, if I want to repeat the function-foo, I don't need to press C-c again, but simply repeat pressing =. Then, after I call the function-foo for enough times, I can just press keys other than = (or explicitly press C-g) to quit.
How to do this?
This may be the thing you are looking for:
(defun function-foo ()
(interactive)
(do-your-thing)
(set-temporary-overlay-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "=") 'function-foo)
map)))
There's a smartrep.el package that does exactly what you need. The documentation is a bit scarce but you can get a grip of how it's supposed to be used by looking into numerous emacs configs found on github. For example (taken from here):
(require 'smartrep)
(smartrep-define-key
global-map "C-q" '(("n" . (scroll-other-window 1))
("p" . (scroll-other-window -1))
("N" . 'scroll-other-window)
("P" . (scroll-other-window '-))
("a" . (beginning-of-buffer-other-window 0))
("e" . (end-of-buffer-other-window 0))))
This is what I use. I like it because you don't have to specify the repeating key.
(require 'repeat)
(defun make-repeatable-command (cmd)
"Returns a new command that is a repeatable version of CMD.
The new command is named CMD-repeat. CMD should be a quoted
command.
This allows you to bind the command to a compound keystroke and
repeat it with just the final key. For example:
(global-set-key (kbd \"C-c a\") (make-repeatable-command 'foo))
will create a new command called foo-repeat. Typing C-c a will
just invoke foo. Typing C-c a a a will invoke foo three times,
and so on."
(fset (intern (concat (symbol-name cmd) "-repeat"))
`(lambda ,(help-function-arglist cmd) ;; arg list
,(format "A repeatable version of `%s'." (symbol-name cmd)) ;; doc string
,(interactive-form cmd) ;; interactive form
;; see also repeat-message-function
(setq last-repeatable-command ',cmd)
(repeat nil)))
(intern (concat (symbol-name cmd) "-repeat")))
You want your function-foo to use set-temporary-overlay-map.
In addition to what #juanleon suggested, which uses set-temporary-overlay-map, here is an alternative that I use quite a bit. It uses standard library repeat.el.
;; This function builds a repeatable version of its argument COMMAND.
(defun repeat-command (command)
"Repeat COMMAND."
(interactive)
(let ((repeat-previous-repeated-command command)
(last-repeatable-command 'repeat))
(repeat nil)))
Use that to define different repeatable commands. E.g.,
(defun backward-char-repeat ()
"Like `backward-char', but repeatable even on a prefix key."
(interactive)
(repeat-command 'backward-char))
Then bind such a command to a key with a repeatable suffix, e.g., C-c = (for C-c = = = =...)
See this SO post for more information.

Delete a word without adding it to the kill-ring in Emacs

When switching files using the minibuffer (C-x C-f), I often use M-Backspace to delete words in the path. Emacs automatically places what I delete into the kill ring. This can be annoying, as sometime I am moving to another file to paste something, and I end up pasting part of the file path. I know there are workarounds, and the other code is still in the kill ring, etc, but I would just like to disable this functionality.
Emacs doesn't have a backward-delete-word function, but it's easy enough to define one:
(defun backward-delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-region (point) (progn (backward-word arg) (point))))
Then you can bind M-Backspace to backward-delete-word in minibuffer-local-map:
(define-key minibuffer-local-map [M-backspace] 'backward-delete-word)
See a discussion of this topic at help-gnu-emacs#gnu.org:
http://lists.gnu.org/archive/html/help-gnu-emacs/2011-10/msg00277.html
The discussion boils down to this short solution:
(add-hook 'minibuffer-setup-hook'
(lambda ()
(make-local-variable 'kill-ring)))
You just have to replace the function called by M-<backspace>, namely backward-kill-word, with backward-delete-word, which you can easily define using the source definition of backward-kill-word found in lisp source for emacs. You do this by substituting kill-region for delete-regionas in the following code, which also defines delete-word (delete word after the cursor). You can just paste this code in your .emacs file.
(defun delete-word (arg)
"Delete characters forward until encountering the end of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-region (point) (progn (forward-word arg) (point))))
(defun backward-delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-word (- arg)))
(global-set-key (kbd "M-<backspace>") 'backward-delete-word)
(global-set-key (kbd "M-<delete>") 'delete-word)