get and set line content in emacs buffer programmatically - emacs

I would like to translate the following function from vim script to emacs elisp (I use it to set the email recipients when writing emails).
My question is mainly how to get and set line contents in emacs, because with quick googling I could not find this out (probably I just did not know the right terms to google for, "getline" and "setline" in any case did show any results).
function! G_set_to()
let address = system('my-address-script') "shell command to choose addresses
let line = getline (2)
if strlen(line) == 4
call setline(2, line . address)
else
call setline(2, line . "; " . address)
endif
endfunction
Sorry if the answer is obvious, I am am completely new to emacs and don't even know how to use its in-built help system.
Cheers
Arian

Give this a shot, obviously customizing the variable G-address-script to suit your needs.
(require 'sendmail)
(defvar G-address-script "echo hi#google.com")
(defun G-set-to ()
"execute script in G-address-script and populate the To: line with the results"
(interactive)
(save-excursion
(mail-to)
(unless (= (current-column) 4)
(insert "; "))
(insert (shell-command-to-string G-address-script))
(when (looking-at "^$") ; when shell command has extra newline, delete it
(delete-backward-char 1))))
As far as using the help, there's a reasonable introduction to Emacs lisp here. But the quick intro is:
C-h i (that's control-h then i to see the info pages, there is one for Emacs and one for Emacs Lisp.
M-x apropos searches for terms
C-h f gives you help on a function
C-h v gives you help on a variable
In the *scratch* buffer, C-j will evaluate the expression right before the point (cursor)
M-x edebug-defun when the point is in a emacs lisp function will turn the debugger on, and the next time a function is run you'll step through it (M-x eval-defun in the function will turn the debugger off)
M-x eldoc-mode will turn on automatic documentation for emacs lisp functions and variables as you type them, read more here.

I took Trey's code and changed a few things and now it seems to work:
(defvar G-address-script "goobook_dmenu_with_cache")
(defun G-set-to ()
"execute script in G-address-script and populate the To: line with the results"
(interactive)
(save-excursion
(goto-line 2)
(re-search-forward "$")
(unless (= (current-column) 4)
(insert "; "))
(insert (shell-command-to-string G-address-script))))
Some remaining questions:
The bit where Trey's code checks if the string returned from G-address-script is empty doesn't work at the moment, what do I have to change?
Is there really no function to get the content of a specified line as a string?
Is there a better/more elegant way to do this? The vim script solution looks so much simpler, surely I am missing something.
Anyway, I'll mark this as solved in a day or so if there are no more answers as Trey solution basically does what I wanted. Thank you Trey!

Related

How to set a keybinding to create and jump to the next line in emacs?

I have the following code that attempts to create a new line and then jump to it. The idea is that move-end-of-line will jump to the end of the current line, and ["C-m"] would act as return/enter. Yet executing this command gives the error: "wrong number of arguments". How do I fix this?
(global-set-key (kbd "C-.") 'new-line)
(defun new-line ()
(interactive)
(move-end-of-line)
["C-m"]
)
I think you need to read the Emacs & elisp manuals: these questions are pretty easy to answer. Here's one way to do it.
(defun insert-line-after-line (&optional n)
(interactive "p")
(end-of-line 1) ;end of current line
(open-line n) ;open n new lines
(forward-line 1)) ;go to start of first of them
But seriously: Emacs has very extensive self-documentation, it is easy to find out how to do these things.
An option is to record a macro and use that.
M-x kmacro-start-macro
C-e
C-m
M-x kmacro-end-macro
If you don't care about the macro persisting, just run it:
C-x e
But if you want it to persist you would save it:
M-x name-last-kbd-macro new-line
M-x insert-kbd-macro new-line
and paste the output into your initialisation file (with your shortcut definition):
(global-set-key (kbd "C-.") 'new-line)
(fset 'new-line
[end return])
["C-m"] is like the way you specify a key for doing a key binding, but this is not the same as how you programmatically tell Emacs to insert a character into a document. You could use (insert-char ?\^M) (see ref here), but that would result in a literal ^M character (try it; another way to do the same thing interactively is Ctrl-Q followed by Ctrl-M). (insert "\n") seems to be what you're looking for.
Also, the reason you're getting the message "wrong number of arguments" is because (move-end-of-line) requires an argument when called out of interactive context. (move-end-of-line 1) works.
That said, possibly an easier way to achieve the result you're looking for is with the following setting:
(setq next-line-add-newlines t)
This will allow you to just do C-n at the end of the file and not worry about the distinction between moving and inserting.

A quick way to repeatedly enter a variable name in Emacs?

I was just typing in this sort of code for Nth time:
menu.add_item(spamspamspam, "spamspamspam");
And I'm wondering if there's a faster way to do it.
I'd like a behavior similar to yasnippet's mirrors, except
I don't want to create a snippet: the argument order varies from
project to project and from language to language.
The only thing that's constant is the variable name that needs to be
repeated several times on the same line.
I'd like to type in
menu.add_item($,"")
and with the point between the quotes, call the shortcut and start typing,
and finally exit with C-e.
This seems advantageous to me, since there's zero extra cursor movement.
I have an idea of how to do this, but I'm wondering if it's already done,
or if something better/faster can be done.
UPD The yasnippet way after all.
Thanks to thisirs for the answer. This is indeed the yasnippet code I had initially in mind:
(defun yas-one-line ()
(interactive)
(insert "$")
(let ((snippet
(replace-regexp-in-string
"\\$" "$1"
(substring-no-properties
(delete-and-extract-region
(line-beginning-position)
(line-end-position))))))
(yas/expand-snippet snippet)))
But I'm still hoping to see something better/faster.
yasnippet can actually be used to create a snippet on-the-fly:
(defun yas-one-line ()
(interactive)
(let ((snippet (delete-and-extract-region
(line-beginning-position)
(line-end-position))))
(yas-expand-snippet snippet)))
Now just type:
menu.add_item($1,"$1")
and call yas-one-line. The above snippet is expanded by yasnippet!
You could try
(defvar sm-push-id-last nil)
(defun sm-push-id ()
(interactive)
(if (not sm-push-id-last)
(setq sm-push-id-last (point))
(text-clone-create sm-push-id-last sm-push-id-last
t "\\(?:\\sw\\|\\s_\\)*")
(setq sm-push-id-last nil)))
after which you can do M-x sm-push-id RET , SPC M-x sm-push-id RET toto and that will insert toto, toto. Obviously, this would make more sense if you bind sm-push-id to a convenient key-combo. Also this only works to insert a duplicate pair of identifiers. If you need to insert something else, you'll have to adjust the regexp. Using too lax a regexp means that the clones will tend to overgrow their intended use, so they may become annoying (e.g. you type foo") and not only foo but also ") gets mirrored on the previous copy).
Record a macro. Hit F3 (or possibly C-x (, it depends) to begin recording. Type whatever you want and run whatever commands you need, then hit F4 (or C-x )) to finish. Then hit F4 again the next time you want to run the macro. See chapter 17 of the Emacs manual for more information (C-h i opens the info browser, the Emacs manual is right at the top of the list).
So, for example, you could type the beginning of the line:
menu.add_item(spamspamspam
Then, with point at the end of that line, record this macro:
F3 C-SPC C-left M-w C-e , SPC " C-y " ) ; RET F4
This copies the last word on the line and pastes it back in, but inside of the quotes.

How can I open a temporary buffer

For very long time I have done: C-x b and then some "unique" name like xbxb. So I use switch-to-buffer with a non-existent buffer. You can imagine what C-x C-b shows me: Lots of such names. xbxb, xbxbxxx .... It really gets annoying after some time (a week or so), since I discover that I have already used all good names.
Is there a more canonical way of opening a new buffer? If I want to run a shell a further time, I say C-u M-x shell. Something along that line would be ideal.
You can use make-temp-name to generate a name for a file or buffer with a random postfix. With that as a base, you can write something like this:
(defun generate-buffer ()
(interactive)
(switch-to-buffer (make-temp-name "scratch")))
where "scratch" can be replaced by whatever prefix you'd like.
make it so:
(defun new-scratch ()
"open up a guaranteed new scratch buffer"
(interactive)
(switch-to-buffer (loop for num from 0
for name = (format "blah-%03i" num)
while (get-buffer name)
finally return name)))
I signed up just to answer this question (because I use this function a lot, so I thought it'd be useful to share it here):
(defun tmpbuf (buf)
"open a buffer,
if it doesn't exist, open a new one"
(interactive "sBuffer name: ")
(switch-to-buffer
(get-buffer-create (concat "*" buf "*"))))
I'm not really sure what you want. You say that "I discover that I have already used all good names", so letting Emacs generate the names isn't going to be any good, but if you are going to specify the name yourself, it doesn't get any more canonical than C-xb name RET.
Otherwise, one of the functions already suggested to let you enter a string and use that with some kind of "tmp buffer" pattern to create a new name would seem sensible.
Or scratch.el might prove useful, if what you actually wanted was a single temp buffer per major mode.
You could almost certainly benefit from binding C-xC-b to ibuffer, and using filters and/or groups to separate out the temporary buffers from the more important ones. That would deal with the list getting cluttered.
You seem oddly resistant to writing a new function? Even if there did turn out to be something built in, there's nothing wrong with using custom functions -- that's generally how you go about customising Emacs to your liking.
(defun yashi/new-scratch-buffer-in-org-mode ()
(interactive)
(switch-to-buffer (generate-new-buffer-name "*temp*"))
(org-mode))
(bind-key "<f7>" 'yashi/new-scratch-buffer-in-org-mode)
I'm using deft for a quick note-taking but sometimes I know I won't need the content but need a buffer in Org mode. For that, it's been serving me well. Hit F7 again will create a buffer with similar name, *temp*<2> in my case, acording to Uniquify.
BTW, here is a command to launch a new buffer with a new deft file, if you are interested. F6 to launch it.
(defun yashi/deft-new-file ()
(interactive)
(let ((deft-filter-regexp nil))
(deft-new-file)))
(bind-key "<f6>" 'yashi/deft-new-file)
I use this to open up a temporary buffer. Good thing? Helps me track which buffers I'd opened, and when.
(defun tmp-buffer()
"Make a temporary buffer and switch to it - Like C-n for Sublime etc"
(interactive)
(switch-to-buffer (get-buffer-create (concat "tmp-" (format-time-string "%m.%dT%H.%M.%S")))))
You are given access to someone else's Emacs and you want to open a new buffer. If you are lucky, this someone has set enable-recursive-minibuffers to t. If not, you can temporarily do M-: to eval this Emacs Lisp expression (don't forget to restore this parameter later):
(setq enable-recursive-minibuffers t)
Now, you open a new buffer:
C-xb prompts for a buffer name
C-uM-: will eval and print the result of the expression to the minibuffer prompt:
(random)
This gives you a random number in the full range of representable integers (including negative ones), which is very unlikely to be already taken. Press Return to conclude to switch to the new buffer.
I was looking for a solution for which I have the freedom to give a name or it randomly generates a name. I merged the andswer of #dotemacs and the answer of R. P. Dillon. I'm a n00b in elisp so it took me some half an hour to resolve some of my stupid mistakes.
(defun mm/generate-temp-buffer (buf)
"A function to generate temprory buffers using either
a random name or given name"
(interactive "sNew temp buffer name: ")
(switch-to-buffer
(get-buffer-create
(concat "*tmp*"
(if (equal buf "")
(make-temp-name "")
buf)
"*")
)))
This is how it works:
you run the function (M-x mm/generate-temp-buffer)
you are asked for a name.
2.1. if you type something it will create a buffer named *tmp*YOUR_STRING*
2.2. if you don't give an input and just press RET, it will create a buffer named something like *tmp*o8f4Mf*
Hopefully this is useful to others and save someone's time.

before defadvice not executing before the function?

[I apologize for the poor title, but couldn't come up with a better one.]
bin chen asked on Google+:
How to input relative path of (buffer-file-name) in minibuffer after M-! in #emacs?
I thought if the buffer-file-name is saved in a register, it should be accessible by invoking insert-register (C-x r i) while at the shell-command prompt.
(defun save-buffer-file-name-in-register ()
(set-register ?F (buffer-file-name))
(set-register ?D (file-name-directory buffer-file-name)))
(defadvice shell-command (before save-buffer-file-name)
"Save buffer-file-name to register F before running shell-command"
(save-buffer-file-name-in-register))
(ad-activate 'shell-command)
When I invoke shell-command (M-!) followed by insert-register (C-x r i), I get the error message: Register does not contain any text.
But when I run list-registers I do see that the registers F and D are set with the appropriate values. If I run the shell-command again, I can access the values from the registers previously saved.
Is it possible that the registers are being set too late for the first time? How can I fix the code to do what I want?
Edit: Changed around to before (Thanks to #phils)
n.b. You have defined around advice, not before advice.
Around advice acts as a wrapper, and must include the token ad-do-it to execute the code of the function it is wrapping.
You have effectively replaced the body of the shell-command function with a call to save-buffer-file-name-in-register
As to your main question, I'd need to check the documentation, but I suspect that because the arguments to the advised function are available to advice, the original function's interactive declaration probably executes before the advice does, which would explain why your register values are not visible at the interactive shell-command prompt.
(If the around in the above code is indeed what you were using, the fact that you were still being prompted for a shell command would seem to verify this sequence.)
When the interactive form runs, your advice hasn't executed yet. See: this question
You need to specify an interactive form in your advice that redefines the original if you want to stick with this approach. However, this approach is a little fancy-pants for the sake of fancy-pants-ness.
Just define your own interactive function which does what you want without registers.
(defun insert-cur-dir ()
(interactive)
(let ((dir-name (file-name-directory (buffer-file-name (window-buffer (minibuffer-selected-window))))))
(insert (or dir-name ""))))
(define-key minibuffer-local-map (kbd "C-c i") 'insert-cur-dir)
An alternative, but way awesomer approach is to use yasnippet.

How can I easily reload Emacs lisp code as I am editing it?

As an Emacs beginner, I am working on writing a minor mode. My current (naive) method of programming elisp consists of making a change, closing out Emacs, restarting Emacs, and observing the change. How can I streamline this process? Is there a command to refresh everything?
You might try using M-C-x (eval-defun), which will re-evaluate the top-level form around point. Unlike M-x eval-buffer or C-x C-e (exal-last-sexp), this will reset variables declared with defvar and defcustom to their initial values, which might be what's tripping you up.
Also try out C-u C-M-x which evaluates the definition at point and sets a breakpoint there, so you get dropped into the debugger when you hit that function.
M-x ielm is also very useful as a more feature-rich Lisp REPL when developing Emacs code.
M-x eval-buffer should do it.
What Sean said. In addition, I have (eval-defun) bound to a key, along with a test. The development loop then becomes: 1) edit function, 2) press eval-and-test key, 3) observe results, 4) repeat. This is extremely fast.
During development I write a test, bind it to jmc-test, then use the above key to run it on my just-edited function. I edit more, then press key again, testing it again. When the function works, I zap jmc-test, edit another function, and write another jmc-test function. They're nearly always one line of code, so easy to just bang out.
(defun jmc-eval-and-test ()
(interactive)
(eval-defun nil)
(jmc-test))
(define-key emacs-lisp-mode-map (kbd "<kp-enter>") 'jmc-eval-and-test)
(when t
(defun myfunc (beer yum)
(+ beer yum))
(defun jmc-test () (message "out: %s" (myfunc 1 2))))
When editing "myfunc", if I hit keypad enter, it prints "out: 3".
It all depends on what you're writing and how you've written it. Toggling the mode should get you the new behavior. If you're using [define-minor-mode][1], you can add code in the body of the macro that keys off the mode variable:
(define-minor-mode my-minor-mode
"doc string"
nil
""
nil
(if my-minor-mode
(progn
;; do something when minor mode is on
)
;; do something when minor mode is off
)
But, another way to check it quickly would be to spawn a new Emacs from your existing one:
M-x shell-command emacs&
I just define a function called ldf (short for load-file) in my .emacs file,
like this:
(defun ldf (arg) (interactive "P") (load-file (buffer-file-name)))
As you can see, this little function looks up the filename of the current buffer and then loads the file. Whenever I need to reload the current buffer elisp file, just type "M-x ldf"