I have extended org-cdlatex-mode to expand the pmatrix environment using pma as my keyword (config below). This works perfectly the first time I want to insert a pmatrix, but not the second time within the same math environment.
Consider the following example:
\begin{align}
pma
\end{align}
If I press the TAB key with the cursor after pma, I get the wanted expansion
\begin{align}
\begin{pmatrix}
\end{pmatrix}
\end{align}
However, if I want to insert a second pmatrix environment, it does not work:
\begin{align}
\begin{pmatrix}
x & y
\end{pmatrix}
=
pma
\end{align}
Pressing the TAB key at the end of the pma line only moves the cursor forward to the end of the next line.
Can someone explain why and suggest a fix?
Emacs version 24.4.1, Org mode 8.2.10.
EDIT: Same behaviour for Org mode 9.0.9.
EDIT #2: I get the same behaviour for default template expansions, e.g. fr.
Content of minimal .emacs:
(add-hook 'org-mode-hook 'turn-on-org-cdlatex)
(setq cdlatex-env-alist
'(("pmatrix" "\\begin{pmatrix}\n?\n\\end{pmatrix}" nil)))
(setq cdlatex-command-alist
'(("pma" "Insert pmatrix env" "" cdlatex-environment ("pmatrix") nil t)))
I am having the same problem, although not a complete answer but a hint on how to solve it:
Have you tried typing "equ" and then do M-x cdlatex-tab.
In my case this works, as stated in the cdlatex documentary. It seems that TAB is not bound to "cdlatex-tab" in my case.
Related
In many languages, the line comment starts with a single symbol, for example # in Python and R.
I find that in Emacs, when writing such line comments, I have to repeat the comment symbol twice to make the correct indentation.
See the following example:
(setq x-select-enable-clipboard t)
;using a single comment symbol indents wrongly
;; repeating the comment symbol indents fine
(setq-default c-basic-offset 4)
With a single ; at the beginning of the line cannot get the correct indentation. How to get the correct setting? Thanks!
EDIT:
I found the solution myself. In ESS's document:
Comments are also handled specially by ESS, using an idea borrowed
from the Emacs-Lisp indentation style. By default, comments beginning
with ‘###’ are aligned to the beginning of the line. Comments
beginning with ‘##’ are aligned to the current level of indentation
for the block containing the comment. Finally, comments beginning with
‘#’ are aligned to a column on the right (the 40th column by default,
but this value is controlled by the variable comment-column,) or just
after the expression on the line containing the comment if it extends
beyond the indentation column. You turn off the default behavior by
adding the line (setq ess-fancy-comments nil) to your .emacs file.
So I put this in my .emacs:
(setq ess-fancy-comments nil) ; this is for ESS
I think for Python mode, it has a similar variable.
Your example use Emacs Lisp, in this language the standard convention is that a single ; is indented to the right, whereas two ;; is indented like code would be indented at that point. I strongly recommend that you stick to this convention, otherwise your code would stand out as being different. And three ;;; is indented to the left. Four ;;;; is left indented, and used for major sections. (See https://www.gnu.org/software/emacs/manual/html_node/elisp/Comment-Tips.html)
For Ruby, comments always indent as code, as far as I know.
The major mode should take care of this properly. If not, consider filing an enhancement request or bug report to the maintainers. Of course, "properly" might be in the eye of the beholder. You can try to make your preferences known, however. And check whether the major-mode code might already have user options for this.
Beyond that, the function that is the value of variable comment-indent-function governs this. Normally, this is set by the major mode. You can set it to any function you want (e.g. on the mode hook, so that your definition overrides the one provided by the major-mode code).
It accepts no arguments, and it returns the column you want the comment to be indented to.
Here is code that indents a comment to column 0, for example:
(defun foo () (setq comment-indent-function (lambda () 0)))
(add-hook 'SOME-MODE-HOOK 'foo 'APPEND)
For Emacs-Lisp mode, for example, you would use (add-hook 'emacs-lisp-mode-hook 'foo 'APPEND).
Main goal: making a smart "uncomment" function suitable for any mode.
(defun uncomment-mode-specific ()
(interactive)
(if (region-active-p)
(comment-region (region-beginning) (region-end) -1) ; so far so good
(if (= ";" (line-beginning-position)) ; here is the problem
(message "successful")
(message "unsuccessful"))
))
In the if statement, I would like to check for the value of the first character of the line, and if it equals the variable comment-start (which would return ";" in emacs lisp), goto beginning-of-line and delete the character. Ideas?
EDIT: More clarification as requested in a comment below follows. I would like a function to do:
1) If a region is selected, remove the comments (here that uncomment-region or comment-dwim would work as pointed out by Patrick)
ELSE:
2) If the first character of the line at point is a comment character, remove the comment character.
ELSE:
3) Search current line for comment (excluding \% or \;, mode dependent), move up to comment and kill the line starting with the comment sign.
I could not see how you would want this to work differently. It could then be bound to one key to simply remove comments, depending on the mode, using comment-start to identify the comment character.
I'm posting this as an alternative answer, since what you are trying to do is partly done already with the comment-dwim command. From the docs (you can find it using C-h f comment-dwim)
comment-dwim is an interactive compiled Lisp function in
`newcomment.el'.
It is bound to M-;.
(comment-dwim ARG)
Call the comment command you want (Do What I Mean).
If the region is active and transient-mark-mode is on, call
comment-region (unless it only consists of comments, in which
case it calls uncomment-region).
Else, if the current line is empty, call comment-insert-comment-function
if it is defined, otherwise insert a comment and indent it.
Else if a prefix ARG is specified, call comment-kill.
Else, call comment-indent.
You can configure comment-style to change the way regions are commented.
So in order to use it, simply select a region with C-SPC (set-mark-command) and move the caret to the other point and run comment-dwim.
I've decided to get my toes wet with a bit of lisp, since I want to make emacs behave a little better when I hit TAB. My command works fine. It just performs indent-for-tab-command and if nothing happens, it performs tab-to-tab-stop, on the assumption that it's unlikely I was hitting TAB just to have the point refuse to budge when I'm inside a multi-line string or some such. After the first TAB press, it continues to do tab-to-tab-stop until either editing resumes, or the point is moved elsewhere. AFAIK, my logic is ok, though my lisp code probably isn't!
Originally I just hacked this into my emacs dot files by doing (local-set-key (kbd "TAB") 'tab-dwim) for major modes where I wanted this behaviour. That worked as expected.
Then I decided that what I was doing was basically a minor mode, so I tried to move the key-binding into a minor-mode. For some reason, even though the minor mode is enabled (as indicated in the mode line, and just from toggling it on and off), my tab-dwim function isn't being invoked when I hit the TAB key. I can still invoke it with M-x as expected.
What am I doing wrong with my minor mode's :keymap?
;;;
;; TAB DWIM
; buffer-local before/after point tracking
(setq point-before-tab nil)
(setq point-after-tab nil)
(make-local-variable 'point-before-tab)
(make-local-variable 'point-after-tab)
(defun tab-dwim ()
"Indents normally once, then switches to tab-to-tab-stop if invoked again.
tab-dwim will always perform tab-to-tab-stop if the first TAB press does not
cause the point to move."
(interactive)
(print "in tab-dwim now") ; THIS LINE IS NEVER INVOKED ON TAB?
(setq point-before-tab (point))
(if (eq point-before-tab point-after-tab) ; pressed TAB again
(tab-to-tab-stop)
(indent-for-tab-command))
(if (eq (point) point-before-tab) ; point didn't move
(tab-to-tab-stop))
(setq point-after-tab (point)))
(define-minor-mode tab-dwim-mode
"Toggle tab-dwim-mode.
With a non-nil argument, turns on tab-dwim-mode. With a nil argument, turns it
off.
When tab-dwim-mode is enabled, pressing the TAB key once will behave as normal,
but pressing it subsequent times, will continue to indent, using
tab-to-tab-stop.
If tab-dwim determines that the first TAB key press resulted in no movement of
the point, it will indent according to tab-to-tab-stop instead."
:init-value nil
:lighter " DWIM"
:keymap
'(([TAB] . tab-dwim)))
(provide 'tab-dwim)
Cheers,
Chris
I think you are very close.
Try this for your keymap:
'(("\t" . tab-dwim)))
Yes, use "\t" or the vector format "[(tab)]".
Some additional notes for your elisp development:
Avoid making global variables as much as possible. In this case, I think dynamically binding with let is appropriate. Also have a look at let*.
Understand the difference between make-local-variable and make-variable-buffer-local. The way you've written your code, the buffer-local variable would only exist in the buffer that loads your package.
As Nemo mentioned, it's extemely extremely extremely recommended that you use a common prefix for all variables/functions related to each package. Emacs has only one namespace, this is the "hacky" way to keep it somewhat organized.
Question:
How do I create custom keybindings for minor modes? Something like this.
Here is what I have so far. I'm trying to get just one custom keybinding to work:
(define-minor-mode num-mode
"Toggle the Num pad keys.
With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode.
When Num mode is enabled, the num pad inserts the
keys you see on the pad. This may over ried existing
definitions, and is probably only usefule if you aref
running Emacs through a terminal."
;; The initial value.
nil
;; The indicator for the mode line.
" NumPad"
;; The minor mode bindings.
;; This doesn't work right now!!!!
'(((kbd "<kp-1>") . "a"))
:global 1
)
When I hit "1" on the num pad after calling my custom minor mode, "num-mode" and verifying it is on in the mini buffer, I get the error <kp-1> is undefined. What I want to happen is a is printed out where the pointer is when I hit <kp-1>. (just a test)
Context:
So, I usually use my num pad to move between buffers (the arrow keys move me the appropriate directions). This is set globally. I want to create a minor mode that I can call when I want to use my num-pad to simply enter numbers.
By default, the keys on my num-pad are undefined. I use <kp-0> to <kp-9> to define the keybindings for the numpad keys.
I can create a minor mode that I can call, but I can't attach any keybindings. This is true for all keybindings, including one not defined anywhere else.
Thanks for any help!
Short Answer
Problem line:
'(((kbd "<kp-1>") . "a"))
Solution (force the evaluation of the macro):
;; Single quote changed to back-quote and added a comma
`((,(kbd "<kp-1>") . "a"))
Long Answer
The define-minor-mode macro allows you to create minor modes relatively easily (as far as Emacs) goes.
First I'll show how it's done, then I'll explain how it works:
In general form:
(define-minor-mode NAME-mode
"DOCUMENTATION"
INIT-VALUE
"LIGHTER"
;; keymap
'(
(KEY-SEQUENCE . DEFINITION)
(KEY-SEQUENCE . DEFINITION)
... ETC ...
)
;; other options
:KEYWORD-ARG VALUE
:KEYWORD-ARG VALUE
... ETC ...
)
Specific example with forced evaluation of macros in the alist:
;; Custom Minor Mode
(define-minor-mode custom-mode
"Doc description, yada yada yada."
;; The initial value - Set to 1 to enable by default
nil
;; The indicator for the mode line.
" CustomMode"
;; The minor mode keymap
`(
(,(kbd "C-c C-a") . some-command)
(,(kbd "C-c C-b") . other-command)
("\C-c\C-c" . "This works too")
)
;; Make mode global rather than buffer local
:global 1
)
An alternative way, if you wish to use a variable for the keymap is to define the keymap variable and the keymap before the minor mode declaration something like this:
(defvar custom-mode-keymap (make-keymap) "num-mode keymap.")
(define-key custom-mode-keymap (kbd "C-c C-a") 'some-command)
And then, in your minor mode definition, simple list the variable name for your keymap, instead of the alist
(define-key custom-mode-keymap (kbd "C-c C-b") 'other-command)
;; Num pad enable
(define-minor-mode custom-mode
...
;; The minor mode bindings.
custom-mode-keymap
How it all works
From top to bottom, right after define-minor-mode we define a command name to toggle the minor mode. custom-mode in this case (M-x custom-mode to toggle the mode). This also defines a variable of the same name.
Right after the command name, we list the documentation string for the minor mode in quotes. This can pretty much be as long as you want.
Next we have several choices. The simplest choice is to simply list three things and then any additional options. The three things have to be listed in the order below. These three things are:
The initilization value for the minor mode variable. nil will have the mode off by default. Something other than nil will have it on by default.
The lighter. The lighter is simply what is display in the mode line at the bottom when your minor mode is on. This should be short, and it'll often help, in terms of formatting, to start it with a space.
The keymap. The keymap can either be defined as a variable or an alist (association list). Since using an alist is simpler and shorter, that's what I used in the example. The alist should be in the form (key-sequence . definition).
If you define the keymap as an alist, there's a few things to watch out for, especially if you're used to defining global keybindings. First, command names are not quoted. Second, if you want to use a macro, you have to force it to evaluate (and on SO). This is done with a combination of the back-quote (not single quote) and comma. You can see how this is done in the example with the kbd macro. I also included a keystroke definition if you don't use the kbd macro. If you simply quote a string in your keymap, that'll print out when the defined key combination is pressed (just like for defining global key bindings).
The keymap will not work with kbd macros if you do not force the evaluation of the kbd macros with a combination of the back quote and comma. Like this:
`((,(kbd "C-c C-a") . some-command))
Finally, you can add additional options using keyword-args of the form :blah. In the example I used :global. We could have defined the entire mode with keyword-args, but it's shorter to just list the init value, lighter, and keymap in the right order.
You need to have code like this in your minor mode definition:
(defvar your-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map parent-mode-shared-map)
(define-key map "\C-c\C-a" 'some-defun)
(define-key map "\C-c\C-b" 'some-other-sexp)
map)
(use-local-map your-mode-map)
You could have a look at the many modes available in EmacsWiki for reference.
Have a look at this (just for information about keybindings):
http://www.gnu.org/software/emacs/manual/html_node/emacs/Key-Bindings.html#Key-Bindings
http://www.gnu.org/software/emacs/manual/html_node/emacs/Local-Keymaps.html#Local-Keymaps
From Link:
Well written major modes will run hook at the end. So, you can use a hook to define your keybinding. Minor modes usually do not have hooks. In that case, you can call “(require ‹minor mode feature symbol›)” first, then define your keybinding.
Also you might have a look at:
http://www.cs.utah.edu/dept/old/texinfo/emacs19/emacs_35.html#SEC347
Maybe the accepted answer here also helps you.
I am having a problem with doxygen style multi-line comments with emacs indent feature in c-mode. According to doxygen manual (http://www.doxygen.nl/manual/docblocks.html) the form below is accepted.
/********************************************//**
* ... text
***********************************************/
I am trying to use this format in emacs but when I tab in on the line '* ... text' the * ends up below the /** at the end of the first line like so:
/********************************************//**
* ... text
***********************************************/
Any suggestions on how to fix this? Still learning all the in-and-outs of emacs.
The reason it is indenting as such is that (by default) multi-line comments are lined up with the start of the comment on the previous line. In this case, the start of the containing comment is in column 47.
Now, how to fix it. Here's how I figured out how to fix it, the solution is at the end.
First, there's the cc-mode manual, specifically the section on customizing indentation. A useful key is C-c C-s which tells you which syntax is being used for indentation. In this case it is ((c 61)) - the c is the important part for now.
To customize it interactively, you can type C-c C-o (when the point is on the line whose indentation you want to fix). You'll be prompted for which syntax entry you want to customize (defaults to c in this case b/c that's the current syntax), then you'll be prompted for what you want to change the syntax entry to (default is c-lineup-C-comments).
Now we can look at that function to see how we might customize it to meet your needs. M-x find-function c-lineup-C-comments.
That's where it gets more difficult. You can customize the way cc-mode handles comment indentation, but what it looks like you want it to do (in this case) is to recognize that the c-comment you're in is immediately preceded by another c-comment, and that comment is the one you want to align indentation to.
How do you do that? The easiest way I can think of is to advise 'c-lineup-C-comments to recognize this special case and change the value of its first argument to be what you want. My limited testing shows this works for your example:
(defadvice c-lineup-C-comments (before c-lineup-C-comments-handle-doxygen activate)
(let ((langelm (ad-get-arg 0)))
(save-excursion
(save-match-data
(goto-char (1+ (c-langelem-pos langelem)))
(if (progn
(beginning-of-line)
;; only when the langelm is of form (c . something)
;; and we're at a doxygen comment line
(and (eq 'c (car langelm))
(looking-at "^\\(\\s-*\\)/\\*+//\\*\\*$")))
;; set the goal position to what we want
(ad-set-arg 0 (cons 'c (match-end 1))))))))
The end result of this advice should be that the argument passed into c-lineup-C-comments should be transformed from (c . 61) to (c . 17) (or something like that), essentially fooling the routine into lining up with the comment at the beginning of the line, and not the comment which you're currently modifying.
Which version of emacs are you using? My emacs 22 has this problem, but on another machine with emacs 23 does not. This is probalby due to some "electric" indentation. Try M-x describe-key RET RET and also M-x describe-mode to get a nice place to start searching for clues. There is also http://doxymacs.sourceforge.net/ but I have not tesed it personally.