Problem writing a snippet containing Emacs Lisp code - emacs

I've been trying to make use of a cool feature of YASnippet: write snippets containing embedded Emacs Lisp code. There is a snippet for rst-mode that surrounds the entered text with "=" that is as long as the text such as in
====
Text
====
Based on this snippet, I decided to slightly modify it (with Elisp) so that it comments out these three lines depending on the major mode you are in (I thought that such a snippet would be useful to organize the source code). So I wrote this:
${1:`(insert comment-start)`} ${2:$(make-string (string-width text) ?\-)}
$1 ${2:Text}
$1 ${2:$(make-string (string-width text) ?\-)}
$0
This code works relatively well except for one problem: the indentation of these three lines gets mixed up, depending on the major mode I'm in (e.g., in emacs-lisp-mode, the second and the third lines move more to the right than the first line).
I think the source of the problem might have something to do with what comes after the string ${1: on the first line. If I add a character, I have no problem (i.e., all three lines are correctly aligned at the end of the snippet expansion). If I add a single space after this string, the misalignment problem still continues though.
So my question is: do you know of any way of rewriting this snippet so that this misalignment does not arise? Do you know what's the source of this behaviour?
Cheers,

From Writing snippets:
yas/indent-line
The variable yas/indent-line controls the indenting. It is bound to 'auto by default, which causes your snippet to be indented according to the mode of the buffer it was inserted in.
Another variable yas/also-auto-indent-first-line, when non-nil does exactly that :-).
To use the hard-coded indentation in your snippet template, set this variable to fixed.
To control indentation on a per-snippet basis, see also the directive # expand-env: in Writing Snippets.
For backward compatibility with earlier versions of YASnippet, you can also place a $> in your snippet, an (indent-according-to-mode) will be executed there to indent the line. This only takes effect when yas/indent-line is set to something other than 'auto.
for (${int i = 0}; ${i < 10}; ${++i})
{$>
$0$>
}$>

Related

Emacs highlighting: how to deal with highlighting messed up by unusual usage of special characters?

Problem:
In Emacs configuration modes (e.g. conf-xdefaults-mode or conf-space-mode), some special characters are used in unusual ways, for instance when they define keybindings. This messes up the highlighting for the rest of the buffer.
Example:
The ranger rc.conf file uses conf-space-mode which greatly helps its readability. But lines such as:
map # console shell -p%space
map "<any> tag_toggle tag=%any
mess up the highlighting since # usually defines a comment and is followed by font-lock-comment-face until the end of the line and " defines the beginning of a string and is followed by font-lock-string-face until it encounters a closing quote.
Escaping those characters is not an option because it would prevent them from defining the keybindings.
Possible solution:
The best solution I can think of is to fiddle with font lock settings for those configuration modes to remove the highlighting after those special characters. But I will then loose the proper highlighting after those characters when it is suitable.
A compromise could be to keep highlighting after # since this only messes up one line and there are a lot of comments in those configuration files, while removing the highlighting after single and double quotes since those mess up the entire rest of the buffer and strings are not so common in configuration files.
Question:
What is the proper way to deal with these situations?
Is there a way to reset the highlighting at a point in the buffer? or to insert a character which would affect the highlighting (to fix it) without affecting the code? or is there a way to "escape" some characters for the highlighting only without affecting the code?
The easy way
It's probably easiest to just live with it but keep things constrained. Here, I took ranger's default rc.conf and re-arranged some of the font-lock errors.
Let's ignore the blue "map" for now. We have two visible font-lock errors. The map #... is font-locking as a comment, and the map "... font-locking as a string to the end of the buffer. The first error is self-constrained. Comments end at the end of the line. The second error we constrain by adding a comment. (I don't know if ranger would accept comments in the middle of the line, so I'm only using beginning-of-line comments here.)
The second error is now constrained to one line, but a couple more errors have popped up. Quickly adjusting these we get.
This is something that I could live with, as I'm not in conf files all day long (as opposed to say, source code.) It would be even neater if our new "comments" could be included on the same line.
The hard way
You'll want to use Emacs font-lock-add-keywords. Let's get back to that blue map in the first image. It's rendering blue because conf-space-mode thinks that a string, followed by any amount of whitespace, followed by an opening brace should be rendered in font-lock-type-face (the actually regexp that triggers this is ^[_space__tab_]*\\(.+?\\)[_space__tab_\n]*{[^{}]*?$ where _space_ and _tab_ are actual space and tab characters.)
We can override this in a simple fashion by evaluating
(font-lock-remove-keywords
'conf-space-mode
'(("^\\<\\(map\\)\\>" 1 font-lock-variable-name-face)))
and reloading the buffer with C-x C-v RET. Now, every time that the word "map" appears at the beginning of a line it's rendered as font-lock-variable-name-face (yellow in our example.)
You can make this change permanent by adding a hook to your init file.
(add-hook 'conf-space-mode-hook (lambda ()
(font-lock-remove-keywords
nil
'(("^\\<\\(map\\)\\>" 1 font-lock-variable-name-face)))))
This method doesn't appear to work for your comment (#) and string (' ") delimiters as they're defined in the syntax table. Modifying the syntax table to provide special cases is probably more effort than it's worth.

Emacs: auto-fill-mode weird indentation behaviour

I am currently working on a major mode derived from auto-fill-mode where I need the text to show in a special indented way (it's a derivation of the screenwriter.el project), and I just got stuck with a peculiar behaviour of the auto-fill when there are multi line indentations:
(NOTE: use-hard-newlines is nil, and left-margin is 0):
How I expect it to work:
DUDE <-- here I insert a newline
(sad) <-- here I insert another newline
Hello, look how good <-- here I let the auto-fill-mode fill the text automatically
of a day it is!
But what happens is the following:
DUDE <-- here I insert a newline
(sad) <-- here I insert another newline
Hello, look how good <-- here I let the auto-fill-mode fill the text automatically
of a day it is!
So basically the fill mode acts weirdly when there are multi indented paragraphs, indenting to the second line's left margin. I could not find anywhere how to avoid such a behaviour.
Even stranger, the following works just fine, indenting to the precedent line's margin.
DUDE <-- here I insert a newline
Hello, look how good <-- here I let the auto-fill-mode fill the text automatically
of a day it is!
I wonder if it's just a bug or if there is a way to avoid this since it's quite annoying. Could anyone test if it works differently on other versions of emacs, or at least give me a hint on how to work around this? Thank you very much.
Emacs version: 24.3.1 on Windows
EDIT: I just checked and the same behaviour happens with use-hard-newlines on, so I'm oblivous to how to solve this
You could customize the adaptive-fill-mode variable, which is what causes a prefix to be automatically determined when filling text. Set the variable to nil to disable that behaviour.
For details of how the prefix is worked out, see the fill-context-prefix function.

how to freely format comments in cc-mode

I'm quite new to cc-mode and I'd like to configure it to allow me to freely format and use tabs in multiline comments. This is important to me because I want to use cog.py in my source file and need to be able to format the python source in the comment correctly. I'd be ok with comments not beeing autoindented at all, however I'd like to keep auto indenting the rest of the source code.
Example:
...
/*
[[[cog
import cog
for x in ['a','b','c']:
>cog.outl(x)
]]]
*/
...
In the line marked with > I'd like to press TAB to indent the line. cc-mode simply does nothing at all if i do so. I could use spaces there (which is inconvenient) but every (semi-)automatic re-indentation of this block would cause the spaces to vanish and therefore the python code to be incorrectly indented (which is what happens if i happen to press tab somewhere on this line after indenting it with spaces).
I tried to start emacs without my .init to be sure this is default behavior and not modified by my configuration so far. I've done google searches and read the documentation of the cc-mode variables / functions I stumbled upon (cc-mode online docs) while searching for a solution (i.e. c-indent-comments-syntactically-p, c-indent-command, c-tab-always-indent,...) but none of these seemed to solve my question.
EDIT1:
Thanks to abo-abo's idea of a "multi-major-mode" setup i've stumbled upon mmm-mode and have set up automatic switching to python mode for a cog section, which fixes most of my problems.
The only remaining problem is reindenting the whole file or a region containing a cog section. Can I somehow tell cc-mode to not change anything in comments while reindenting the file? mmm-mode + that would be a perfect solution for me.
You can use M-i to force a tab indent on the lines that you want, so you can use it to indent your comments.
You can also change your comments to use // instead. Just select your python code snippet, and do M-x comment-region:
// def foo(x):
// print 'hi'
Then the autoindent won't mess up your indentation.

`hideshow` mode not working with lines starting with comments

I'm using emacs (24.3.1) along with cc-mode and hideshow for programming c++. I am working on a project, where the coding styles requires that any keywords present in the header file must be repeated in the source file. In case that this is not allowed by the standard, the keyword must be placed in comments. Let me give you and example:
/* virtual */ void MyAwesomeFunction( int arg, int optarg /* = 0 */ ){
// stuff
}
Obviously there is a comment starting the line. It seems that hideshow can't cope with this sort of formatting. When I call hs-hide-all all code blocks are folded correctly, the same is true if I call hs-hide-block from anywhere within the function. However, if I call hs-hide-block whith point beeing somewhere in the opening line of the function (the first line of my codesnippet) now folding occurs and the error message:
(not enough comment lines to hide)
is printed. The only explicit configuration of hideshow I have done so far is:
(setq hs-hide-comments nil)
However, removing this line makes it even worse: Afterwards not even calling hs-hide-all works properly: all inner blocks are folded, but folding at the function level does not occurs for functions with a leading comment.
Anyone knows how to fix this?
It might help to explicitly hide comments first, either just within the region or throughout the buffer. You can use library hide-comnt.el to do that. A description is here.

How do I auto-fill lines in brackets in emacs (markdown-mode)?

I'm relatively new to Emacs, but have been experimenting with it to see if it would be worth switching. I write in Markdown and use pandoc to convert to whatever I need. In case it matters, I'm running Emacs 23.3.1 on Ubuntu 12.04.
I'm a graduate student in the humanities, so my writing is heavy on the footnotes. Footnotes, in pandoc, are formatted within square brackets. The problem I'm having is that auto-fill mode seems to ignore text within brackets, so my footnotes end up snaking their way across the page--and the only fix I've been able to find is to manually break the lines myself, every time I edit the paragraph. That's obviously less than ideal. (I could also give up on inline footnotes, and leave them all separate references, but I'd prefer not to, and it doesn't seem like that should be necessary.)
So my question is, is there a way to make auto-fill mode operate on text within brackets, too? Is there a reason it doesn't by default?
Many thanks,
-- Brian
It turns out that markdown-mode, as of v. 1.7, deliberately avoids breaking lines in square brackets in order to avoid breaking links--which is the most common use of brackets for Markdown. See http://jblevins.org/projects/markdown-mode/rev-1-7.
Brian,
Add the following to your init file† to allow auto-fill in markdown-mode to break lines inside square brackets:
(require 'markdown-mode)
(defun markdown-nobreak-p () nil)
What we did is redefine the function "markdown-nobreak-p" (originally defined here: http://jblevins.org/git/markdown-mode.git/commit/?id=66566a55 ) to always return "nil" which means "yes you are allowed to break at this point". The original version of this function would return non-nil for points inside square brackets.
† http://www.gnu.org/software/emacs/manual/html_node/emacs/Find-Init.html
Auto-fill by itself does not prevent filling inside brackets. It can be told to do so by the major-mode, tho, so I guess the problem depends on your major mode. If you're using mardown-mode, then please report this problem to its maintainer. In any case, you may want to try and use M-q to explicitly fill the paragraph, since it does not always follow the same conventions as auto-filling: it's more explicit than auto-fill, but still more automatic than placing the newlines by hand.