A basic function for emacs - emacs

I have never written an emacs function before and was wondering if anyone could help me get started. I would like to have a function that takes a highlighted region parses it (by ",") then evaluates each chunk with another function already built into emacs.
The highlighted code may look something like this: x <- function(w=NULL,y=1,z=20){} (r code), and I would like to scrape out w=NULL, y=1, and z=20 then pass each one a function already included with emacs. Any suggestions on how to get started?

A lisp function is defined using defun (you really should read the elisp intro, it will save you a lot of time - "a pint of sweat saves a gallon of blood").
To turn a mere function into an interactive command (which can be called using M-x or bound to a key), you use interactive.
To pass the region (selection) to the function, you use the "r" code:
(defun my-command (beg end)
"Operate on each word in the region."
(interactive "r")
(mapc #'the-emacs-function-you-want-to-call-on-each-arg
;; split the string on any sequence of spaces and commas
(split-string (buffer-substring-no-properties beg end) "[ ,]+")))
Now, copy the form above to the *scratch* emacs buffer, place the point (cursor) on a function, say, mapc or split-string, then hit C-h f RET and you will see a *Help* buffer explaining what the function does.
You can evaluate the function definition by hitting C-M-x while the point is on it (don't forget to replace the-emacs-function-you-want-to-call-on-each-arg with something meaningful), and then test is by selecting w=NULL,y=1,z=20 and hitting M-x my-command RET.
Incidentally, C-h f my-command RET will now show Operate on each word in the region in the *Help* buffer.

Related

Get the content as string of a region in a buffer by elisp program

Here is the problem that I'm solving:
Convert a region of text into a string data structure for subsequent processing by elisp program. The challenge is that
I want to execute an elisp program interactively without affecting the selection of a region
store the string value into a variable so that I can further manipulate it.
By my understanding, a region is defined by a mark and the subsequent cursor position. And I usually execute elisp program in *scratch* buffer. Furthermore, the region is also in the *scratch* buffer.
But to write the function call and execute it in the buffer, I need to move the cursor away from the end of the text selection (region) in order to write the program of
(setq grabbed (buffer-substring-no-properties (region-beginning) (region-end)))
but then the region of selection would change due to the cursor movement.
So I wonder how I could execute the elisp program while keeping the selection intact and still can access the return value.
If you want to run the function from some Elisp code but as if the user had invoked it via a keybinding, you can use call-interactively:
(setq variable-to-keep-the-value (call-interactively 'lines-to-list))
But in most cases, what you want instead is to take yourself the responsibility to choose to which part of text the function should apply:
(setq variable-to-keep-the-value
(lines-to-list (region-beginning) (region-end)))
Notice that the region's boundaries are nothing magical, regardless if they've been set by the mouse or what.
Finally, I found a desirable solution! It's using ielm buffer, the real repl of elisp.
In the ielm buffer, I can set working buffer (by C-c C-b) to be a buffer where I have the text to be manipulated, for example, *scratch*.
I can then select a region of the working buffer to be processed, and in the ielm buffer then I can type and execute elisp code to extract the text in the selected region in the working buffer, for example,
ELISP> (setq grabbed (buffer-substring-no-properties (region-beginning) (region-end)))
"One\nTwo\nThre"
ELISP> grabbed
"One\nTwo\nThre"
ELISP> (split-string grabbed)
("One" "Two" "Thre")
I can then work with the value held by the set variable, grabbed.
Here is a very helpful description of ielm:
https://www.masteringemacs.org/article/evaluating-elisp-emacs

The lisp that convert string and grep in emacs?

I have a file formatted as
abc|<hoge>
a|<foo> b|<foo> c|<foo>
family|<bar> guy|<bar>
a|<foo> comedy|<bar> show|<foo>
action|<hoge>
and want to search search strings by raw (Like "a comedy show" instead of a|<foo> comedy|<bar> show|<foo>) on emacs.
I believe using grep on lisp would be the easiest answer but I have not yet figured out how. Would someone enlighten me?
Well, grep is a separate program (which you could also use). In Emacs, you'd use the function search-forward-regexp, which you can run using either M-x (hold Meta, usually Alt key, and press x) and then type search-forward-regexp and press Return.
You'll then need to key in the regexp to search. Put simply, it seems like you want to ignore |< something >, which in Emacs's variety of regexes is:
|<[a-z]+>
so you might search for e.g.
a|<[a-z]+> comedy|<[a-z]+> show|<[a-z]+>
You can create a Lisp function to convert a string this way, by splitting it on spaces and adding the regex sequences:
(defun find-string-in-funny-file (s) ; Define a function
"Find a string in the file with the |<foo> things in it." ; Document its purpose
(interactive "sString to find: ") ; Accept input if invoked interactively with M-x
(push-mark) ; Save the current location, so `pop-global-mark' can return here
; (usually C-u C-SPC)
(goto-char 0) ; Start at the top of the file
(let ((re (apply #'concat ; join into one string…
(cl-loop
for word in (split-string s " ") ; for each word in `s'
collect (regexp-quote word) ; collect that word, plus
collect "|<[a-z]+> ")))) ; also the regex bits to skip
(search-forward-regexp ; search for the next occurrence
(substring re 0 (- (length re) 2))))) ; after removing the final space from `re'
You can explore what those functions each do in the (online) Emacs Lisp manual; for example, pick from the menu "Help→Describe→Function" or press C-h f (Control+h, then f) and type interactive (RET) for the manual's documentation of that special form.
If you paste the above (defun) into the *scratch* buffer, and position the cursor after the final ) at the end, you can press C-j to evaluate it, and the function will remain with you until you close Emacs.
If you save it in a file named something .el, you can use M-x load-file to load it again in future.
If you then load your "funny" file, and type M-x find-string-in-funny-file, it'll search your file for your string, and leave the cursor on the string. If it's not found, you'll see a message to that effect.
BUGS: The function is less than spectacular style

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 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"

Usage of current-buffer in emacs?

I'm using emacs and I have written a script which uses "current-buffer". However the emacs system doesn't recognise "current-buffer". When I try "M - x current-buffer" i get the response:
no match
: Any idea what I'm doing wrong?
current-buffer is not an interactive function. That is, can't be invoked interactively via M-x as you've tried to do. You can execute non-interactive lisp-code directly by using eval-expression as follows:
M-: (current-buffer) RET
Notice that you have to enter a proper lisp expression. If you want to capture the value in a variable, something like this
M-: (setq xyzzy (current-buffer)) RET
will store the current buffer into the variable xyzzy.
Do I interpret you correct that you have created a function named current-buffer that you want to be available with M-x current-buffer?
To enable functions to be called by M-x function-name the function needs to be marked as interactive.
A sample from the emacs manual:
(defun multiply-by-seven (number) ; Interactive version.
"Multiply NUMBER by seven."
(interactive "p")
(message "The result is %d" (* 7 number)))
The (interactive "p") part makes the function callable from the minibuffer (through M-x).
I sounds like you would (also) like to know how to get the name of the current buffer interactively. Use M-: (buffer-name).