I'd like to quickly generate text in a buffer that looks like this:
(fact "This is some text which will hang out
only on this part of the screen, ideally
automatically flowing to the correct
margins as I type."
(+ 1 1) => 2
;; more Clojure tests...
)
I have an Elisp keybinding which quickly spits out a starting template and puts my cursor in the right place:
(global-set-key "\C-of" (lambda ()
(interactive)
(insert "(fact \"\"\n\n )")
(backward-char 6)))
Now, when I am typing in the string portion ("This is some text..."), it'd be awesome if I could get Emacs to automatically flow text to the "correct" margins. Is there some way Emacs can be made to adjust margins and wraparound behavior based on where you're typing? At least, the first time you are typing there?
Barring that, for a given selection of text, how can I do the equivalent of fill-region, but with the desired left and right margins? Currently fill-region deletes all space between fact and "This is...., and left-justifies the rest.
There might be a simpler way that I'm overlooking now, but I would just do this:
Configure the text block in a temporary buffer, by doing this there:
a. Set fill-column to the width of the text block that you want.
b. Put the text at the beginning of the line, i.e., not indented.
c. Fill the text.
d. Use indent-rigidly to indent the text to the column you want, except for the first line.
Insert into your target buffer (fact followed by the indentation you want for the first line of the text block. Then insert the contents of the temporary buffer. Then insert whatever other text/code you need.
IOW, I would separate filling the text block from indenting it.
The following seems to work for the moment for my alternative (weaker) case:
;; Set up Midje fact with mark inserted at beginning of comment text
;; (refill as needed in appropriate columns, using C-oF).
(global-set-key "\C-of" (lambda ()
(interactive)
(insert "(fact \"\"\n\n )")
(backward-char 6)
(set-mark (point))))
;; Perform the refill operation to properly reformat the text string
;; in a Midje fact, started with C-of:
(global-set-key "\C-oF" (lambda ()
(interactive)
(set-left-margin (mark) (point) 37)
(fill-region (mark) (point))))
I expect I'll have to tweak this as I get experience using it, but it is pretty close. Still, it'd be nice to figure out how to have this happen automatically, while I'm typing inside the string.
this is my first question, so apologies for breaking any rules.
I've just started writing some functions in elisp to help me navigate certain types of text files more efficiently. To make these accessible, I've added some buttons to the tool-bar. As it's now becoming busy, I'd like to either: 1) move some of these additional buttons to a second line; or 2) instantiate a second tool-bar that could be placed somewhere else in the frame (either under the existing tool-bar, or perhaps vertically along the side where the scrollbar is).
I've searched high and low but am unable to find an existing example of this and, as I don't yet really know what I'm doing, I wonder if somebody has a code snippet from which I might start to hack a solution together.
Many thanks in advance.
System: CentOS 5/6, emacs for linux 23.1
Edit:
Thanks for the comment, William. Here's a simple example representing what my tool-bar code might do:
;
; functions used by the toolbar
;
;
(defun copy-paste-whole-line ()
"copies and pastes the whole of the current into a new line underneath"
(interactive)
(beginning-of-line)
(set-mark (point))
(end-of-line)
(setq temp (buffer-substring (region-beginning) (region-end)))
(message " copying: %s" temp )
(newline)
(insert temp))
;
;
; population of the toolbar:
;
;
(when (find-image '((:type xpm :file "copy_paste_line.xpm")))
(unless tool-bar-mode (tool-bar-mode 1))
; (setq tool-bar-map (make-sparse-keymap)) ; <- uncomment this line to have only this button present
(tool-bar-add-item
"copy_paste_line"
'copy-paste-whole-line
'copy-paste-whole-line
:help "copies and pastes the whole of the current line into a new line underneath"))
so, as you can see (actually, I'm not allowed to post images until I have 10 reputation points, so you won't be able to see), the code adds an extra button to the end of the existing tool-bar buttons. I believe this to be a reasonable way to achieve this, but I'm not an experienced elisp programmer, so if you think it's poorly written, please comment - I'd like to understand why... :)
If I only had 1 button, it would be ok like that, however, I have multiple buttons. I would, thus, like to add them to a second instance of a similar tool-bar (or, perhaps a vertical one placed where the scrollbars are).
Thanks again for any input.
Frame parameter tool-bar-lines is supposed to control this. You can, for instance, customize option default-frames-alist if you want to change the number of tool-bar rows to 2 or 3 everywhere. Or you can do this on a mode-by-mode or frame-by-frame basis. You can, for instance, use M-: (set-frame-parameter nil 'tool-bar-lines 3).
Depending on your platform (and toolkit), the behavior might be variable. See the Elisp manual, node Layout Parameters and node Tool Bars.
I believe you are out of luck. It seems to me that (at least on ubuntu and cygwin) only one row of buttons in the tool-bar is supported.
Here is what I have tried without luck on both systems:
(progn
(set-frame-parameter nil 'tool-bar-lines 3)
(loop for i from 1 upto 20 do
(setcdr tool-bar-map (cons (cadr tool-bar-map) (cdr tool-bar-map)))))
The following picture shows what I get:
The other buttons appear in a pull-down menu if you click on the little triangle at the right end of the toolbar:
You can restore the old tool-bar with the following commands:
(progn
(setq tool-bar-map (make-sparse-keymap))
(tool-bar-setup))
Finally, I have 3 rows of buttons. This is possible with emacs-w32:
So it is the gtk+ / nextstep problem.
in my .emacs configuration, i have the following :
(defun fold-long-comment-lines ()
"This functions allows us to fold long comment lines
automatically in programming modes. Quite handy."
(auto-fill-mode 1)
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(not (eq (get-text-property (point) 'face)
'font-lock-comment-face)))))
the above gets invoked as part of "c-mode-common-hook" and correctly provides folding long comment lines automatically.
however, the above thing works indiscriminately, whether i am using a single line comment e.g. describing struct fields, or multi-line comments describing some complicated piece of code.
so, the basic question is, how can i get automatic folding of long comment lines only if it is a multi-line comment ?
thanks
anupam
edit-1: multi-line-comment explanation
when i say "multi-line-comment", it basically means comments like this:
/*
* this following piece of code does something totally funky with client
* state, but it is ok.
*/
code follows
a correspondingly, a single line comment would be something like this
struct foo {
char buf_state : 3; // client protocol state
char buf_value : 5; // some value
}
the above elisp code, dutifully folds both these comment lines. i would like to fold only the former, not the latter.
If you only want it to affect auto-fill-mode and not general filling (e.g. not when you hit M-q), then your code can be replaced by setting comment-auto-fill-only-comments. As for having it apply only to "multi-line comments", I think you're first going to have to explain what is the difference between. Are you saying that you only want to auto-fill when the comment already spans more than one line, or is there some other characteristic of a comment that can let Emacs figure out that a comment that currently only spans a single line can be spread over multiple lines.
You could try something like:
(set (make-local-variable 'fill-no-break-predicate)
(lambda ()
(let ((ppss (syntax-ppss)))
(or (null (nth 4 ppss)) ;; Not inside a comment.
(save-excursion
(goto-char (nth 8 ppss))
(skip-chars-backward " \t")
(not (bolp))))))) ;; Comment doesn't start at indentation.
Yasnippet snippets that has a percent sign, %, ending a line with the last point of the snippet, $0, before the percent sign acts strange in that the cursor gets placed after the percent sign and not before it. I wonder how I can avoid this strange behavior.
Consider the following snippet:
# -*- mode: snippet -*-
# name: test snippet
# key: ts
# --
{
$0%
}
I take it that as it's activated it should insert three lines where the first contains {, the last line } and the second line % and place the cursor before % on the second line as in the following example:
{
[cursor]%
}
But what happens is the following:
{
% [cursor]
}
How can I make it so that the snippet behaves as I think it should?
My guess is that this is due to something in AUCTeX because it happens with AUCTeX activated but not in the major mode Lisp Interaction.
It works right with my configuration, but I suspect it has to do with auto indenting (mine is heavily customized so that may be the difference). Do you still see the problem if you add
# expand-env: ((yas/indent-line 'fixed))
or
# expand-env: ((yas/indent-line t))
to the snippet's header? You can also try adding $> to the line(s) that you want indented to see if that makes a difference (if it does that would narrow things down a lot). There is a note in the yasnippet code about some problems with markers changing places, but that looks like it was fixed a few years ago.
You should also check that indent-line-function has the proper value namely LaTeX-indent-line.
You could add some sit-for's to the definition of yas/indent-according-to-mode to see where point is at different stages. For example put the following in a scratch buffer, position your cursor after the end of it and type C-x C-e. Then insert your snippet as usual and it will pause for 1 second every where in the code you see a (sit-for 1). So if the cursor starts out in the wrong place, then you know the problem is before indentation, etc. You will have to watch it for every line that is indented, so you may wish to turn off indentation except for the problematic line via $>. Adding or removing sit-for's will allow you to narrow it down.
(defun yas/indent-according-to-mode (snippet-markers)
"Indent current line according to mode, preserving
SNIPPET-MARKERS."
(sit-for 1)
(goto-char (yas/real-line-beginning))
(sit-for 1)
(let ((trouble-markers (remove-if-not #'(lambda (marker)
(= marker (point)))
snippet-markers)))
(save-restriction
(widen)
(sit-for 1)
(condition-case err
(indent-according-to-mode)
(error (message "[yas] warning: yas/indent-according-to-mode habing problems running %s" indent-line-function)
nil)))
(sit-for 1)
(mapc #'(lambda (marker)
(set-marker marker (point)))
trouble-markers)))
Complete emacs newbie here.
I'm using emacs 23.1.1 on Ubuntu with emacs starter kit. I primarily work in the lua-mode (installed with package-install lua-mode).
I need to tune how indentation works, so it would match my coding guidelines.
The guidelines are:
tabs-to-spaces;
two spaces per indent;
80 chars per line maximum, without trailing spaces.
Example:
local foo = function()
print("Hello, world!")
end
What I get with emacs if I don't try to fight with its auto-indent:
local foo = function()
print("Hello, world")
end
Update:
(This belongs to a comment, but since it needs extra formatting, I have to place it here.)
If I try solution by Thomas, I get this:
local foo = function()
print("Hello, world")
end
Note that end is indented with a tab and four spaces.
Does not quite work...
Update 2:
This thing is also gets indented in the wrong way:
local bar = foo(
"one",
"two",
baz(), -- Note three spaces
"quo"
)
It should be:
local bar = foo(
"one",
"two",
baz(),
"quo"
)
Update 3:
Third case of the wrong indentation:
local bar = foo(
"one",
"two"
)
local t = 5 -- This line should not be indented,
-- also note tab between local and t.
Update 4:
Here is what I get with the current version from Thomas:
local foo = function()
print("Hello, world")
end
local bar = 5 -- Emacs put \t before 5
local zzz = foo( -- Emacs put \t before foo
"one", -- Pressed TAB here twice
"two",
three(),
"four"
)
Except where explicitly noted, I did not do anything for indentation, only typed in the code and pressed RETURN at the end of each line. I did not actually type any comments.
It should look as follows:
local foo = function()
print("Hello, world")
end
local bar = 5
local zzz = foo(
"one",
"two",
three(),
"four"
)
Update 5:
One more wrong indentation case:
local foo =
{
bar(); -- Did press a TAB here, but closing brace killed it
baz;
}
Should be:
local foo =
{
bar();
baz;
}
Update 6:
For the sake of completeness, here is what I get with the current Git HEAD of lua-mode, without Thomas's configuration tuning:
local foo = function()
print("Hello, world!")
end
local bar = 5
local foo = bar(
bar,
baz(),
quo(),
aaa
)
local t =
{
"one",
two(),
}
With tuning:
local foo = function()
print("Hello, world!")
end
local bar = 5
local foo = bar(
bar,
baz(),
quo(),
aaa
)
local t =
{
"one",
two(),
}
To match my coding guidelines, it should look as follows:
local foo = function()
print("Hello, world!")
end
local bar = 5
local foo = bar(
bar,
baz(),
quo(),
aaa
)
local t =
{
"one",
two(),
}
Okay, let's give this another try... After browsing through the source code of lua-mode, I've come up with the following approach.
The reason for the admittedly strange default indentation is a function called "lua-calculate-indentation" which computes the column to which to indent the current line. Unfortunately, the values returned by it do not match your desired specification.
For instance, if you enter a single line into a fresh .lua file like this one:
local foo = function()
and hit enter to move the point to the second line, you can invoke the above function by typing M-: (lua-calculate-indentation). The result is 15, which means that lua-mode will indent the second to column 15. This is the reason for the unorthodox indentation you've described and exemplified in your original question.
Now, to fix this I suggest re-defining the function "lua-calculate-indentation" so that it returns the indentation you want. For this, put the following code into an otherwise empty file, and save it under the name "my-lua.el" in the same directory where "lua-mode.el" lives.
;; use an indentation width of two spaces
(setq lua-indent-level 2)
;; Add dangling '(', remove '='
(setq lua-cont-eol-regexp
(eval-when-compile
(concat
"\\((\\|\\_<"
(regexp-opt '("and" "or" "not" "in" "for" "while"
"local" "function") t)
"\\_>\\|"
"\\(^\\|[^" lua-operator-class "]\\)"
(regexp-opt '("+" "-" "*" "/" "^" ".." "==" "<" ">" "<=" ">=" "~=") t)
"\\)"
"\\s *\\=")))
(defun lua-calculate-indentation (&optional parse-start)
"Overwrites the default lua-mode function that calculates the
column to which the current line should be indented to."
(save-excursion
(when parse-start
(goto-char parse-start))
;; We calculate the indentation column depending on the previous
;; non-blank, non-comment code line. Also, when the current line
;; is a continuation of that previous line, we add one additional
;; unit of indentation.
(+ (if (lua-is-continuing-statement-p) lua-indent-level 0)
(if (lua-goto-nonblank-previous-line)
(+ (current-indentation) (lua-calculate-indentation-right-shift-next))
0))))
(defun lua-calculate-indentation-right-shift-next (&optional parse-start)
"Assuming that the next code line is not a block ending line,
this function returns the column offset that line should be
indented to with respect to the current line."
(let ((eol)
(token)
(token-info)
(shift 0))
(save-excursion
(when parse-start
(goto-char parse-start))
; count the balance of block-opening and block-closing tokens
; from the beginning to the end of this line.
(setq eol (line-end-position))
(beginning-of-line)
(while (and (lua-find-regexp 'forward lua-indentation-modifier-regexp)
(<= (point) eol)
(setq token (match-string 0))
(setq token-info (assoc token lua-block-token-alist)))
; we found a token. Now, is it an opening or closing token?
(if (eq (nth 2 token-info) 'open)
(setq shift (+ shift lua-indent-level))
(when (or (> shift 0)
(string= token ")"))
(setq shift (- shift lua-indent-level))))))
shift))
This code sets the indentation level to two spaces (instead of 3), modifies a regular expression that detects if a statement stretches over multiple lines, and finally redefines the indentation function using an auxiliary.
All that's left to do is make sure this code is actually loaded. That must happen after the original lua-mode is loaded, or else that code would re-install the original indentation function.
The way we do that here is a little hacky: we install a call-back function that is invoked each time a buffer changes its major-mode to lua-mode. It then checks if the auxiliary function mentioned before is defined - if not, it loads "my-lua.el". That is a little fragile, but as long as you don't play around with the lua source code, you should be fine.
Add the following lines to your ~/emacs.d/agladysh.el file (assuming that "agladysh" is your username):
(add-hook 'lua-mode-hook
(lambda () (unless (fboundp 'lua-calculate-indentation-right-shift-next)
(load-file (locate-file "my-lua.el" load-path)))))
I assume that lua-mode is on your load-path which it should be if you followed lua-mode's installation instructions.
I hope that it works for you this time, if not, let me know.
I know it's been a while since this was asked, but I just wanted to point out that this is still an issue, with lua-mode installed via the Emacs package system.
However, the latest version on GitHub works very well, didn't notice any indentation weirdness. All you have to do to conform with the Lua style guide is to set indent-tabs-mode to nil and lua-indent-level to 2.
If you enter the following code into .emacs file in your home directory, it will make lua-mode (and only lua-mode) behave the following way:
If you press ENTER, a newline will be inserted and by default the next line will be indented like the previous line.
Whenever you press TAB to indent the line, point either jumps to the first non-whitespace character of the line or, if the line is empty of point is already at that character, two spaces are inserted.
Especially the latter may not be what you want, but perhaps its a first approximation.
(defvar my-lua-indent 2
"The number of spaces to insert for indentation")
(defun my-lua-enter ()
"Inserts a newline and indents the line like the previous
non-empty line."
(interactive)
(newline)
(indent-relative-maybe))
(defun my-lua-indent ()
"Moves point to the first non-whitespace character of the
line if it is left of it. If point is already at that
position, or if it is at the beginning of an empty line,
inserts two spaces at point."
(interactive)
(when (looking-back "^\\s *")
(if (looking-at "[\t ]")
(progn (back-to-indentation)
(when (looking-at "$")
(kill-line 0)
(indent-relative-maybe)
(insert (make-string my-lua-indent ? ))))
(insert (make-string my-lua-indent ? )))))
(defun my-lua-setup ()
"Binds ENTER to my-lua-enter and configures indentation the way
I want it. Makes sure spaces are used for indentation, not tabs."
(setq indent-tabs-mode nil)
(local-set-key "\r" 'my-lua-enter)
(setq indent-line-function 'my-lua-indent))
;; add `my-lua-setup' as a call-back that is invoked whenever lua-mode
;; is activated.
(add-hook 'lua-mode-hook 'my-lua-setup)
Restart Emacs for these changes to take effect.
A cleaner way to do this was added in 2019, in the form of two lua-indent- variables. This gets us almost there, but it still double-indents nested blocks for some reason. Adding a little advice hack finishes the job.
(setq lua-indent-nested-block-content-align nil)
(setq lua-indent-close-paren-align nil)
(defun lua-at-most-one-indent (old-function &rest arguments)
(let ((old-res (apply old-function arguments)))
(if (> old-res lua-indent-level) lua-indent-level old-res)))
(advice-add #'lua-calculate-indentation-block-modifier
:around #'lua-at-most-one-indent)
I can't help much right now - I have a deadline in two days 8-( - but
here is what I use in my .emacs to make lua-mode usable for me...
(setq lua-indent-level 2)
(setq lua-electric-flag nil)
(defun lua-abbrev-mode-off () (abbrev-mode 0))
(add-hook 'lua-mode-hook 'lua-abbrev-mode-off)
(setq save-abbrevs nil) ;; is this still needed?
I indent my code in an unusual way - see the example below - and so
I've disciplined myself to only press TAB when lua-mode can infer the
right indentation correctly from the lines above...
map = function (f, A, n)
local B = {} -- TAB here doesn't work
for i=1,(n or #A) do -- TAB here works
table.insert(B, f(A[i])) -- TAB here works
end -- TAB here works
return B -- TAB here works
end -- TAB here works
I'm the maintainer (but not author) of lua-mode.el. As I'm a lot less fluent in Emacs Lisp than other contributors to this thread, I welcome patches. I'd just like to point out that there's nothing weird or incorrect about the default rules: the idea, as far as I can see, is simply that when you're in an anonymous function, the indentation should take the function keyword as its left margin. This makes sense when you consider using function expressions in other places, e.g. as function parameters.
So, one simple workaround is not to write
local f = function...
but
local function f...
Unless perhaps you're working with a version of Lua that predates the "local function" syntax.
Having said that, I can see why you might want to indent differently. In this case it seems to me reasonable to have a configuration variable lua-indent-function-from-function-keyword (better name, anyone?), and I'd be happy to accept a patch that implemented it.
I think a lot of what you're looking for can be found in the emacs manual on custom C indentation definitions which falls under general indentation engine descriptions.
You can make it do anything you can imagine, which would be strongly preferable to just doing anything you imagine.