Emacs Lisp search-backward - search

Preamble
Using VTK library with C++, quite often I have to write something like this:
vtkInteractorStyleRubberBandZoom *isrbz = vtkInteractorStyleRubberBandZoom::New();
Furthermore, every time I need to use a new VTK class in my program, I have to go somewhere up the source file and add #include "vtkInteractorStyleRubberBandZoom.h"
How do I automate it, so I have to type each of the excruciatingly long class names one time instead of three?
I tried writing an Emacs minor mode for it. There are probably existing solutions out there already (YaSnippet?), but I thought that writing it myself would be a good excercise, too.
Code
;vtk-mode.el
;add to .emacs:
;(load "vtk-mode")
;(global-set-key [(control =)] 'expand-vtk)
(defun expand-vtk ()
(interactive)
(setq now (point))
(setq vtkstart (search-backward "vtk"))
(setq vtkend (- (search-forward " ") 1))
(setq vtkname (buffer-substring vtkstart vtkend))
;check for #include "vtkBlah.h"
(setq includename (format "#include \"%s.h\"\n" vtkname))
(search-backward includename nil (append-include-vtk includename))
(goto-char (+ now (length includename)))
(insert (format "= %s::New();" vtkname)))
(defun append-include-vtk (incname)
(goto-char 0)
(insert incname))
Problem
Basically, it works, except that searching for an include name always fails, e. g.:
vtkSomething *smth /*press C-= here, it looks backward for
#include "vtkSomething.h", can't find it and
calls append-include-vtk, adding it to the beginning
of the file, then comes back here and expands this line into: */
vtkSomething *smth = vtkSomething::New();
//and let's add another instance of vtkSomething...
vtkSomething *smth2 /*press C-= again, it looks backward for
#include "vtkSomething", and fails, despite the fact
that it was added by the previous command. So it adds it again."*/
What am I doing wrong here with search-backward?
(there's another (at least one) bug in the code, I shouldn't add the (length includename) if the search-backward for it was successful, but for now I am more interested in how to make it successful, in the first place)

OK, I got it. Somehow I got an idea that the third argument of search-backward (noerror) is a callback, which it isn't. Therefore it is evaluated every time, not just when the search fails. It should be something like this instead:
(defun expand-vtk ()
(interactive)
(setq now (point))
(setq vtkstart (search-backward "vtk"))
(setq vtkend (- (search-forward " ") 1))
(setq vtkname (buffer-substring vtkstart vtkend))
;check for #include "vtkBlah.h"
(setq includename (format "#include \"%s.h\"\n" vtkname))
(if (search-backward includename nil t)
(goto-char now)
(progn (append-include-vtk includename)
(goto-char (+ now (length includename)))))
(insert (format "= %s::New();" vtkname)))
(defun append-include-vtk (incname)
(goto-char 0)
(insert incname))

A command that's built into Emacs and will help you avoid typing excruciatingly long class names is dabbrev-expand (bound to M-/):
(dabbrev-expand ARG)
Expand previous word "dynamically".
Expands to the most recent, preceding word for which this is a prefix.
If no suitable preceding word is found, words following point are
considered. If still no suitable word is found, then look in the
buffers accepted by the function pointed out by variable
`dabbrev-friend-buffer-function'.
Having typed vtkInteractorStyleRubberBandZoom once, the next time you need it you just type vtkI M-/.

Related

How to pass current-prefix-arg to this-command

I want to reuse current-prefix-arg when calling this-command. I can imagine ways of capturing its value and passing it to modified functions. But, this doesn't seem like a great solution. How can I reuse it (eg. push it back onto a sort of call stack, or whatever emacs uses)?
The example is a simple function to increment/decrement numbers in region I was just writing where I want to temporarily bind i to increment or decrement if it was called with prefix. Can I do this without adding another argument to the function, but just using the original prefix?
(defun my-toggle-increment-numbers (start end)
"Simple function to increment numbers in region. Decrement with prefix."
(interactive "r")
(let (deactivate-mark)
(goto-char start)
(while (re-search-forward "\\([[:digit:]]+\\)" end 'move)
(replace-match (number-to-string
(+ (if current-prefix-arg -1 1)
(string-to-number (match-string 1))))
nil nil nil 1))
;; what is good way to reused the current-prefix-argument value when
;; calling this-command?
(set-transient-map
(let ((km (make-sparse-keymap)))
(define-key km "i" this-command)
km)
t)))
Try this:
(defun my-toggle-increment-numbers (start end &optional decrement)
"Simple function to increment numbers in region. Decrement with prefix."
(interactive "r\nP")
(let (deactivate-mark)
(setq start (copy-marker start)
end (copy-marker end))
(goto-char start)
(while (re-search-forward "\\([-]?[[:digit:]]+\\)" end 'move)
(replace-match (number-to-string (+ (if decrement -1 1)
(string-to-number (match-string 1))))
nil nil nil 1))
(set-transient-map
(let ((km (make-sparse-keymap)))
(define-key km "i" `(lambda ()
(interactive)
(my-toggle-increment-numbers ',start ',end ',decrement)))
km)
t)))
You forgot to include the minus sign preceding your [[:digit:]].
You need to either use lexical binding or construct a command that binds the current values of start, end and current-prefix-arg (or decrement - see next).
It's a bit simpler if you use an argument instead of current-prefix-arg.
(You ask if you can just use current-prefix-arg instead of adding an arg for it. Yes. In that case, let-bind current-prefix-arg in the constructed command that gets invoked for subsequent calls.)
Since replacement can change the number of digits in a numeral (e.g. from 9 to 10, you need to use a marker instead of the number value of end in subsequent calls.
I think the cleanest way is to create a command which calls this-command passing it the prefix arg:
;; This relies on -*- lexical-binding:t -*-
(defun my-toggle-increment-numbers (start end)
[...]
(set-transient-map
(let ((km (make-sparse-keymap))
(tc this-command)
(cpa current-prefix-arg))
(define-key km "i"
(lambda () (interactive)
(let ((current-prefix-arg cpa))
(call-interactively tc))))
km)
t)))
It's probably more verbose than what you were imagining, but I think it's the closest there is to what you're asking. A simpler way to get almost the same result could be:
(defun my-toggle-increment-numbers (start end)
[...]
(setq prefix-arg current-prefix-arg)
(set-transient-map
(let ((km (make-sparse-keymap)))
(define-key km "i" this-command)
km)
t)))

Invalid function in Emacs Lisp

I'm creating a function in Emacs Lisp that will read that whole buffer aloud if there is no active region. Otherwise, it reads the active region.
(defun speak-my-text () "Speaks text in buffer."
(interactive)
(if (equal mark-active t)
(
(kill-ring-save (point-min) (point-max))
(start-process-shell-command "speakbuffvar" nil
"bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
)
(
(kill-ring-save (region-beginning) (region-end))
(start-process-shell-command "speakbuffvar" nil
"bash -c \"killall espeak;xsel --clipboard|espeak -s 290\"")
)))
(global-set-key (kbd "C-z") 'speak-my-text)
I'm having trouble with the first line of the else clause:
(kill-ring-save (region-beginning) (region-end))
When I define the function, bind it, and run, I get "Invalid function" and it points to that line. I'm running Linux Mint.
Use C-h f progn to evaluate multiple expressions sequentially.
You're currently attempting to call a function named (kill-ring-save (region-beginning) (region-end)) and pass it the argument (start-process-shell-command ...)
Naturally, Emacs is telling you that (kill-ring-save (region-beginning) (region-end)) is not the name of a function.
In addition to phils' answer:
mark-active is not reliable in this context, as it might be
non-nil also if a region has no extend.
Function region-active-p would be usable, however depends on an
active transient-mark-mode, which might be unrelated - in most
cases it's useful and sufficient BTW.
Here is a example how to check for an valid region greater then
zero and surpassing transient-mark-mode issue:
(defun ar-region-active-p ()
"Check for and existing region of some extend.
Don't mix up that question with transient-mark-mode "
(interactive)
(and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))))
Based on this, your command might be written slightly differently:
(defun my-command-on-region ()
"If a region of some extend exists, use on it.
Otherwise use whole buffer.
Doesn't require `transient-mark-mode' being active"
(interactive)
(let ((beg (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-beginning))
(point-min)))
(end (or (and (ignore-errors (region-beginning))(region-end) (< (region-beginning)(region-end))(region-end))
(point-max))))
(DO-SOMETHING beg end)))

Emacs, Linux and international keyboard layouts

Is there an easy way to use Emacs key-bindings when you are using a not-English (Russian) keyboard layout?
Whenever an international layout is on, all keystrokes are interpreted literally, M-ф instead of M-a. As a result I can't use commands.
It would also be nice if Linux could interpret non-prefixed and shift-prefixed keys according according to an international layout, while keeping the rest English.
You can set input method (kudos go to kindahero) by typing
M-x set-input-method RET cyrillic-yawerty RET
or
M-x set-input-method RET cyrillic-jcuken RET
To store it permanently, add
(setq default-input-method "cyrillic-yawerty")
to ~/.emacs config (and use C-\ to switch between keyboard layouts).
Here is an alternative solution that uses the OS language, based on syndikat's answer.
Some key translations are missing, but it should be easy to add them.
;; USAGE:
;; Put in your .emacs:
;;
;; (translate-keystrokes-ru->en)
;; (add-hook 'text-mode-hook
;; (lambda () (literal-insert-mode 1)))
;;
;; Only buffers with literal-insert-mode active will be sensitive to the
;; environment language. Prefixed keybindings will still be usable.
(defun translate-keystrokes-ru->en ()
"Make emacs output english characters, regardless whether
the OS keyboard is english or russian"
(flet ((make-key-stroke (prefix char)
(eval `(kbd ,(if (and (string-match "^C-" prefix)
(string-match "[A-Z]" (string char)))
(concat "S-" prefix (string (downcase char)))
(concat prefix (string char)))))))
(let ((case-fold-search nil)
(keys-pairs (mapcar* 'cons
"йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
"qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
(prefixes '("" "s-" "M-" "M-s-"
"C-" "C-s-" "C-M-" "C-M-s-")))
(mapc (lambda (prefix)
(mapc (lambda (pair)
(define-key key-translation-map
(make-key-stroke prefix (car pair))
(make-key-stroke prefix (cdr pair))))
keys-pairs))
prefixes))))
(defun literal-insert ()
(interactive)
(insert-char last-input-event 1))
(define-minor-mode literal-insert-mode
"Make emacs output characters corresponging to the OS keyboard,
ignoring the key-translation-map"
:keymap (let ((new-map (make-sparse-keymap))
(english-chars "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
(mapc (lambda (char)
(define-key new-map (string char)
'literal-insert))
english-chars)
new-map))
Not sure, where did sabof got 150 billion. I ran this code (thanks to Yuri Khan, taken from EmacsWiki):
(loop
for from across "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
for to across "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"
do
(eval `(define-key key-translation-map (kbd ,(concat "C-" (string from))) (kbd ,(concat "C-" (string to)))))
(eval `(define-key key-translation-map (kbd ,(concat "M-" (string from))) (kbd ,(concat "M-" (string to))))))
It's only 128 combinations. Unfortunately, combinations with single letters like C-x b don't work. I'm still trying to find a better solution.
I use following snippet for Cyrillic keyboard and it works fine for me:
(defun reverse-input-method (input-method)
"Build the reverse mapping of single letters from INPUT-METHOD."
(interactive
(list (read-input-method-name "Use input method (default current): ")))
(if (and input-method (symbolp input-method))
(setq input-method (symbol-name input-method)))
(let ((current current-input-method)
(modifiers '(nil (control) (meta) (control meta))))
(when input-method
(activate-input-method input-method))
(when (and current-input-method quail-keyboard-layout)
(dolist (map (cdr (quail-map)))
(let* ((to (car map))
(from (quail-get-translation
(cadr map) (char-to-string to) 1)))
(when (and (characterp from) (characterp to))
(dolist (mod modifiers)
(define-key local-function-key-map
(vector (append mod (list from)))
(vector (append mod (list to)))))))))
(when input-method
(activate-input-method current))))
(reverse-input-method 'russian-computer)
Except:
The only issue I know is that recalculation of OrgTable formulas isn't
working in Russian layout because it is mapped to C-c-* and * change
its location.
source
If you want to keep using the Russian layout in Emacs (rather than use Emacs's own input methods), the only way I know of for now is to add bindings of the form:
(define-key function-key-map [?\M-ф] [?\M-a])
This will tell Emacs that in case M-ф is not bound, it should try to lookup M-a instead. Sadly, you'll need a lot of these bindings. If someone writes up a patch/package that can automatically provide all these bindings, I'd be happy to include it in Emacs.

getting standard input and storing it as a string in lisp

I realize this is probably a really stupid question but i have no idea why this isnt working and i pretty much gave up. basically i tried:
(setq answer (string (read)))
and
(setq answer 0)
(format answer "~s" (read))
and
(setq answer (read))
when i try to evaluate
(if (stringp answer)
(princ "works")
(princ "failed"))
on any of the above tries it always comes out failed.
what am i doing wrong?
Or you could just do:
(setq answer (read-line))
That gives you a string right there.
[1]> (setq answer (read))
3
3
[2]> (type-of answer)
(INTEGER 0 16777215)
[3]> (setq answer (read-line))
3
"3"
[4]> (type-of answer)
(SIMPLE-BASE-STRING 1)
[5]>
Start a fresh REPL, then try checking the return value of each of your steps:
T1> (read)
foo
FOO
T1> (read)
1
1
T1> (type-of (read))
foo
SYMBOL
T1> (type-of (read))
1
BIT
Now note, that STRING won't work on all input types:
T1> (string 'foo)
"FOO"
T1> (string 1)
Also note that, unlike setq, (format foo ...) won't set foo, but write to it, if it's a stream or a string with a fill-pointer. Take a look at its Documentation, and you'll see:
format destination control-string
&rest args => result
[...]
destination---nil, t, a stream, or a
string with a fill pointer.
[...]
format is useful for producing nicely
formatted text, producing good-looking
messages, and so on. format can
generate and return a string or output
to destination.
If destination is a string, a stream,
or t, then the result is nil.
Otherwise, the result is a string
containing the `output.'
Try it like this:
T1> (setq *answer*
(with-output-to-string (s)
(format s "~s" (read))))
1
"1"
T1> *answer*
"1"
Or like this:
T1> (setq *answer* (make-array 20 :element-type 'character :fill-pointer 0))
""
T1> (format *answer* "~s" (read))
1
NIL
T1> *answer*
"1"
Those are the only relevant errors I could find in your code. This definitely returns "works" in every conforming CL (you could also use prin1-to-string):
T1> (defvar *answer*)
*ANSWER*
T1> (setq *answer* (format nil "~s" (read)))
1
"1"
T1> (if (stringp *answer*)
(princ "works")
(princ "failed"))
works
"works"
Unless you are in a messed-up package (try (in-package cl-user) before evaluating your code), or redefined basic functionality, this will work. Give some more exact error descriptions, if it still won't.
ED:
Having read Bill's answer, who correctly pointed at read-line as a shorter solution, I should maybe mention that I didn't try to show the best, most succinct, or most idiomatic approaches in my answer, and that those will vary depending on what you are really trying to do. (The shortest possible solution would have been "works" :) They are just examples that should help explaining why your code failed.
Another thing I forgot to say is that you should keep in mind, that toplevel setqs on variables not defined with defvar or defparameter are generally to be avoided in anything but dabbling at the REPL, since the consequences are undefined. Also, those variables are, by convention, wrapped in asterisks (also called earmuffs) in order to prevent bugs caused by confusing specials with lexically scoped variables.

Searching with intelligent bracket counting (Elisp)

I have the following function that deletes the LaTeX command surrounding the current cursor position:
(defun remove-tex-cmd ()
(interactive)
(save-excursion
(let (cur-point beg-point end-point)
(setq cur-point (point))
(catch 'notexcmd
(if (not (re-search-backward "\\.*?{" nil t)) ; now the point is at the {
(throw 'notexcmd nil))
(search-backward "\\" nil t)
(setq beg-point (point))
(re-search-forward "}")
(setq end-point (point))
(if (> end-point cur-point)
(kill-region beg-point end-point))
(throw 'notexcmd nil)))
(if 'notexcmd
(message "no tex command at point"))))
It works well except for the following situation, because it simply matches the next closing }:
\test{a<cursor here>sdf ${bla}+1$}
results in
+1$}
I could, of course, count the opening and closing brackets. However, as this problem should occur frequently, I wonder whether there exists some more intelligent search function, or am I missing a totally different point?
Use list- or sexp- based operations:
(defun remove-tex-cmd ()
(interactive)
(backward-up-list 1)
(backward-sexp 1)
(kill-sexp 2))
To handle scan error when outside parentheses:
(defun remove-tex-cmd ()
(interactive)
(condition-case nil
(progn
(backward-up-list 1)
(backward-sexp 1)
(kill-sexp 2))
(scan-error (message "Outside parentheses."))))

Resources