Run AStyle on current buffer, save and restore cursor position - emacs

I'm looking for a solution to apply code formatting and static code analysis on contents of current buffer in c++ mode. I'm planning to use AStyle and CppCheck. Both tools need to be executed on current code. For example if I'm editing foo.cpp the function should run
astyle --arg1 --argn foo.cpp
And
cppcheck --arg1 --arg2 foo.cpp
What I already tried is a simple function from here which is not working:
(defun astyle-this-buffer (pmin pmax)
(interactive "r")
(shell-command-on-region pmin pmax
"astyle" ;; add options here...
(current-buffer) t
(get-buffer-create "*Astyle Errors*") t))
Update:
I found that the above code is compatible with Emacs23 while I'm using 24. So I used this instead:
(defun reformat-code ()
(interactive)
(shell-command-on-region (point-min) (point-max)
"astyle --options=~/.astylerc" t t))
(global-set-key (kbd "C-x C-a") 'reformat-code)
Now it works and formats the code, though I can't find out how to save cursor's position and tell emacs to move that line.

It seems to me that reformatting tools like astyle will modify whitespace, but presumably nothing else. (It's possible this is mildly wrong, like if they reformat a C macro then they must modify backslashes as well -- but that can also be taken into account.)
So, the way I would approach this would be to count how many non-whitespace characters appear before (point), invoke astyle, revert the buffer (or whatever), and finally, starting from the start of the buffer, move forward that many non-whitespace characters.
This won't always be "the same", for example if point was in some whitespace that was modified -- but I think it ought to be reasonably close.
If you really want to just record the current line number and go back to that, you can use line-number-at-pos to get the current line number, and then (goto-char (point-min)) and use forward-line to get back to the line.

Related

How to set a keybinding to create and jump to the next line in emacs?

I have the following code that attempts to create a new line and then jump to it. The idea is that move-end-of-line will jump to the end of the current line, and ["C-m"] would act as return/enter. Yet executing this command gives the error: "wrong number of arguments". How do I fix this?
(global-set-key (kbd "C-.") 'new-line)
(defun new-line ()
(interactive)
(move-end-of-line)
["C-m"]
)
I think you need to read the Emacs & elisp manuals: these questions are pretty easy to answer. Here's one way to do it.
(defun insert-line-after-line (&optional n)
(interactive "p")
(end-of-line 1) ;end of current line
(open-line n) ;open n new lines
(forward-line 1)) ;go to start of first of them
But seriously: Emacs has very extensive self-documentation, it is easy to find out how to do these things.
An option is to record a macro and use that.
M-x kmacro-start-macro
C-e
C-m
M-x kmacro-end-macro
If you don't care about the macro persisting, just run it:
C-x e
But if you want it to persist you would save it:
M-x name-last-kbd-macro new-line
M-x insert-kbd-macro new-line
and paste the output into your initialisation file (with your shortcut definition):
(global-set-key (kbd "C-.") 'new-line)
(fset 'new-line
[end return])
["C-m"] is like the way you specify a key for doing a key binding, but this is not the same as how you programmatically tell Emacs to insert a character into a document. You could use (insert-char ?\^M) (see ref here), but that would result in a literal ^M character (try it; another way to do the same thing interactively is Ctrl-Q followed by Ctrl-M). (insert "\n") seems to be what you're looking for.
Also, the reason you're getting the message "wrong number of arguments" is because (move-end-of-line) requires an argument when called out of interactive context. (move-end-of-line 1) works.
That said, possibly an easier way to achieve the result you're looking for is with the following setting:
(setq next-line-add-newlines t)
This will allow you to just do C-n at the end of the file and not worry about the distinction between moving and inserting.

Emacs/AUCTeX prefix arguments

In LaTeX mode C-c C-c is bound to:
(TeX-command-master &optional OVERRIDE-CONFIRM)
Normally this interactive function runs a command, perhaps a LaTeX compilation, asking for confirmation.
In tex-buf.el it reads:
If a prefix argument OVERRIDE-CONFIRM is given, confirmation will
depend on it being positive instead of the entry in `TeX-command-list'.
This is a bit cryptic for me and reading C-h v TeX-command-list didn't help.
How can I pass the prefix argument to "TeX-command-master" so that I avoid all the confirmation requests?
Take a look at Emacs' documentation to find out about prefix arguments. In general, you can pass a command a prefix argument with C-u followed by a number. For one-digit numbers, you can also just type Meta followed by the digit. Thus to pass a positive prefix argument to TeX-command-master you could type:
M-1 C-c C-c
However, this will actually add another minibuffer confirmation, namely about the shell command to be used to compile the LaTeX source. Without the prefix argument, a command-dependent default is used for that.
If you want to avoid the question about the command to use, you can bind the undocumented variable TeX-command-force to "LaTeX" via:
(setq TeX-command-force "LaTeX")
However, this will have the downside that you're basically binding C-c C-c to the "latex" command, you cannot use any of the other commands such as "bibtex" or "view".
Other than that, LaTeX-mode does not allow for any customization of C-c C-c. Your best options are to either advise the function TeX-command-query or to bind C-c C-c to a wrapper function to set TeX-command-force dynamically. The latter would probably be the preferred option if you also want to auto-save the buffer.
It seems that the mystery of the OVERRIDE-CONFIRM continues. In the meantime a fellow suggests that, if we are unable to manage TeX-command-master, we can simply rewrite it.
In my version, based on his, if the buffer is not modified, the external viewer is launched; if the buffer is modified the compiler is run.
Everything with no confirmation for saving or running the given command.
(defun my-run-latex ()
(interactive)
(if (buffer-modified-p)
(progn
(setq TeX-save-query nil)
(TeX-save-document (TeX-master-file))
(TeX-command "LaTeX" 'TeX-master-file -1))
(TeX-view)))
Of course one can bind my-run-latex to whatever keybinding.
On the user's point of view this is a solution to my own question.
Do I click the close tag? Well, on the curious guy point of view I am still interested in understanding the mysterious TeX-command-master technicalities.
If someone should happen to know...
P.S.
Yes, TeX-save-query overrides the save-file request, also with TeX-command-master, that is C-c C-c. But you will still be asked to confirm the command action.
Build & view
Again, this solution, instead of modifying the behaviour of the TeX-command-master, rewrites it. The rewritten version of the command, named build-view, follows a rather straightforward logic.
If the LaTeX file buffer is not-modified, it runs the default viewer;
If the buffer is dirty, it runs the default LaTeX compiler and, after the build, opens the output in the default viewer.
Here's the code:
(defun build-view ()
(interactive)
(if (buffer-modified-p)
(progn
(let ((TeX-save-query nil))
(TeX-save-document (TeX-master-file)))
(setq build-proc (TeX-command "LaTeX" 'TeX-master-file -1))
(set-process-sentinel build-proc 'build-sentinel))
(TeX-view)))
(defun build-sentinel (process event)
(if (string= event "finished\n")
(TeX-view)
(message "Errors! Check with C-`")))
You can now type M-x build-view and start the told build-view process or associate it with a new keybinding such as “F2”:
(add-hook 'LaTeX-mode-hook '(lambda () (local-set-key (kbd "<f2>") 'build-view)))
Note: As suggested by Tyler, TeX-save-query variable is changed locally, therefore the old C-c C-c/ TeX-command-master is unaffected and will keep asking confirmations.
Do edit this code to make it better or easier to read!
I puzzled over the OVERRIDE-CONFIRM bit for a while, and couldn't figure out how it was supposed to work. If you want to automatically run Latex on your file, without being bothered about saving it first, or confirming that you want latex (rather than view, bibtex etc), you could use a function like this:
(defun my-run-latex ()
(interactive)
(TeX-save-document (TeX-master-file))
(TeX-command "LaTeX" 'TeX-master-file -1))
Bind this to something handy, and you'll still have C-c C-c for when you want to use the default processing commands. You may want to modify the TeX-command line if "Latex" isn't the processor you want to call.
If you are just looking to compile the latex source without a confirmation dialog, just add the following to your .emacs:
(setq TeX-command-force "")
You can then compile the source with C-c C-c and it won't ask to confirm. The only problem with this solution is that you can no longer change the command, but with most documents you won't want to. I might suggest that at the same time you can add this to your .emacs for even more flexibility, giving you a C-c C-c equivalent to the former behavior:
(define-key LaTeX-mode-map "\C-c\C-a"
;;; 'a' for ask, change to anything you want
(lambda (arg) (interactive "P")
(let ((TeX-command-force nil))
(TeX-command-master arg))))
You can then just work away at your document, do a C-x C-s, C-c C-c and then C-c C-v to see it. Like others have suggested you can also do the same for the save command and have it compile automatically on save, but some of my documents are in CVS and so I avoid putting hooks on that.
Credit to Ivan for some help on this one - don't know if he is on StackOverflow
I think the gist of this question is "how do I quickly compile my TeX document from AUCTeX without all the key presses and confirmations?"
My answer to that is to use the latexmk command rather than trying to coerce AUCTeX to do it.
latexmk -pdf -pvc myfile.tex
latexmk will monitor the file in question and rebuilt it as soon as you save it. If you use a good pdf viewer, it will notice the change in PDF and re-display it immediately. On OS X, skim works well for this.

How to make emacs behave closer to the regular editors?

I'm using Emacs 23.1.1 on Ubuntu with Emacs starter kit. I primarily work in the lua-mode.
Is there a way to stop Emacs being so smart about indentation? I'm used to the dumb editors, and press all the required keys manually.
I want to use two spaces per indent, tabs-to-spaces.
When I press RETURN, the new line indentation must match the previous line.
When I press TAB on the leading whitespace, the line contents must be indented by one indentation unit.
When I press TAB on the beginning of empty line, the cursor must move one indentation unit to the right.
Oh, and I'd like to get soft word wrap on 80th column and trim-trailing-spaces on save as well.
Update:
(Would put this in a comment, but it needs formatting)
If I use Thomas's solution, auto-indent on RETURN is "fixed", but TAB still indents weirdly:
local run = function(...)
x
"x" marks the spot where cursor appears after I type the first line and hit RETURN, TAB.
Emacs has a concept of modes, which means that depending on what type of file you're editing it provides special functionality that is useful for that file. Every buffer has one major mode associated and optionally a number of minor modes.
Indentation is one of the things that is typically mode-dependent. That is, you may have to configure indentation separately for every major-mode, because otherwise when you load a new file, its associated major mode may override your indentation settings. It's possible though to write a function that configures indentation and set up Emacs in a way that the function is invoked whenever a new major-mode is started.
In order to realize the settings you want, you'll need to run a few lines of elisp code. (Unfortunately your description of what should happen when you hit TAB leaves out some details, I've implemented the simplest version I could think of below -- if it's not what you want, that can be changed, of course.)
Put the following code in the file named .emacs in your home directory (~):
(setq-default indent-tabs-mode nil) ; use spaces for indentation
(defvar my-indentation-width 2
"The number of spaces I prefer for line indentation.")
(defun my-enter ()
"Inserts a newline character then indents the new line just
like the previous line"
(interactive)
(newline)
(indent-relative-maybe))
(defun my-indent ()
"When point is on leading white-space of a non-empty line, the
line is indented `my-indentation-width' spaces. If point is at
the beginning of an empty line, inserts `my-indentation-width'
spaces."
(interactive)
(insert (make-string my-indentation-width ? )))
(defun my-indentation-setup ()
"Binds RETURN to the function `my-enter' and TAB to call
`my-indent'"
(local-set-key "\r" 'my-enter)
(setq indent-line-function 'my-indent))
(defun delete-trailing-whitespace-and-blank-lines ()
"Deletes all whitespace at the end of a buffer (or, rather, a
buffer's accessible portion, see `Narrowing'), including blank
lines."
(interactive)
(let ((point (point)))
(delete-trailing-whitespace)
(goto-char (point-max))
(delete-blank-lines)
(goto-char (min point (point-max)))))
;; make sure trailing whitespace is removed every time a buffer is saved.
(add-hook 'before-save-hook 'delete-trailing-whitespace-and-blank-lines)
;; globally install my indentation setup
(global-set-key "\r" 'my-enter)
(setq indent-line-function 'my-indent)
;; also override key setting of major-modes, if any
(add-hook 'after-change-major-mode-hook 'my-indentation-setup)
This works for me in Emacs 23, although I may have missed some edge cases. However, these changes are so fundamental that I predict you will run into incompatibilities sooner or later with some major-modes that expect indentation to work they set it up. If you really want to get into Emacs it's worthwhile adapting the habits you inherited from other editors to the way Emacs does things.
For soft word-wrap there is a minor-mode called "longlines" which you can download from here: http://www.emacswiki.org/cgi-bin/emacs/download/longlines.el I haven't used it so I can't tell you how well it works.
Fixing TAB and RETURN:
(global-set-key "\t" 'self-insert-command)
(global-set-key "\r" 'newline-and-indent)
Fill column (haven't tried): say ESC x customize-var, enter fill-column, set to 80.

get and set line content in emacs buffer programmatically

I would like to translate the following function from vim script to emacs elisp (I use it to set the email recipients when writing emails).
My question is mainly how to get and set line contents in emacs, because with quick googling I could not find this out (probably I just did not know the right terms to google for, "getline" and "setline" in any case did show any results).
function! G_set_to()
let address = system('my-address-script') "shell command to choose addresses
let line = getline (2)
if strlen(line) == 4
call setline(2, line . address)
else
call setline(2, line . "; " . address)
endif
endfunction
Sorry if the answer is obvious, I am am completely new to emacs and don't even know how to use its in-built help system.
Cheers
Arian
Give this a shot, obviously customizing the variable G-address-script to suit your needs.
(require 'sendmail)
(defvar G-address-script "echo hi#google.com")
(defun G-set-to ()
"execute script in G-address-script and populate the To: line with the results"
(interactive)
(save-excursion
(mail-to)
(unless (= (current-column) 4)
(insert "; "))
(insert (shell-command-to-string G-address-script))
(when (looking-at "^$") ; when shell command has extra newline, delete it
(delete-backward-char 1))))
As far as using the help, there's a reasonable introduction to Emacs lisp here. But the quick intro is:
C-h i (that's control-h then i to see the info pages, there is one for Emacs and one for Emacs Lisp.
M-x apropos searches for terms
C-h f gives you help on a function
C-h v gives you help on a variable
In the *scratch* buffer, C-j will evaluate the expression right before the point (cursor)
M-x edebug-defun when the point is in a emacs lisp function will turn the debugger on, and the next time a function is run you'll step through it (M-x eval-defun in the function will turn the debugger off)
M-x eldoc-mode will turn on automatic documentation for emacs lisp functions and variables as you type them, read more here.
I took Trey's code and changed a few things and now it seems to work:
(defvar G-address-script "goobook_dmenu_with_cache")
(defun G-set-to ()
"execute script in G-address-script and populate the To: line with the results"
(interactive)
(save-excursion
(goto-line 2)
(re-search-forward "$")
(unless (= (current-column) 4)
(insert "; "))
(insert (shell-command-to-string G-address-script))))
Some remaining questions:
The bit where Trey's code checks if the string returned from G-address-script is empty doesn't work at the moment, what do I have to change?
Is there really no function to get the content of a specified line as a string?
Is there a better/more elegant way to do this? The vim script solution looks so much simpler, surely I am missing something.
Anyway, I'll mark this as solved in a day or so if there are no more answers as Trey solution basically does what I wanted. Thank you Trey!

How can I set the encoding of shell-command-on-region output?

I have a small elisp script which applies Perl::Tidy on region or whole file. For reference, here's the script (borrowed from EmacsWiki):
(defun perltidy-command(start end)
"The perltidy command we pass markers to."
(shell-command-on-region start
end
"perltidy"
t
t
(get-buffer-create "*Perltidy Output*")))
(defun perltidy-dwim (arg)
"Perltidy a region of the entire buffer"
(interactive "P")
(let ((point (point)) (start) (end))
(if (and mark-active transient-mark-mode)
(setq start (region-beginning)
end (region-end))
(setq start (point-min)
end (point-max)))
(perltidy-command start end)
(goto-char point)))
(global-set-key "\C-ct" 'perltidy-dwim)
I'm using current Emacs 23.1 for Windows (EmacsW32). The problem I'm having is that if I apply that script on a UTF-8 coded file ("U(Unix)" in the status bar) the output comes back Latin-1 coded, i.e. two or more characters for each non-ASCII source character.
Is there any way I can fix that?
EDIT: Problem seems to be solved by using (set-terminal-coding-system 'utf-8-unix) in my init.el. In anyone has other solutions, go ahead and write them!
Below are from shell-command-on-region document
To specify a coding system for converting non-ASCII characters
in the input and output to the shell command, use C-x RET c
before this command. By default, the input (from the current buffer)
is encoded using coding-system specified by `process-coding-system-alist',
falling back to `default-process-coding-system' if no match for COMMAND
is found in `process-coding-system-alist'.
During executing, it looks for coding system from process-coding-system-alist at first, if it's nil, then looks from default-process-coding-system.
If your want to change the encoding, you can add your converting option to process-coding-system-alist, below are the content of it.
Value: (("\\.dz\\'" no-conversion . no-conversion)
...
("\\.elc\\'" . utf-8-emacs)
("\\.utf\\(-8\\)?\\'" . utf-8)
("\\.xml\\'" . xml-find-file-coding-system)
...
("" undecided))
Or, if you didn't set process-coding-system-alist, it's nil, you could assign your encoding option to default-process-coding-system,
for example:
(setq default-process-coding-system '(utf-8 . utf-8))
(If input is encoded as utf-8, then output encoded as utf-8)
Or
(setq default-process-coding-system '(undecided-unix . iso-latin-1-unix))
I also wrote a post about this if you want details.
Quoting the documentation for shell-command-on-region (C-h f shell-command-on-region RET):
To specify a coding system for converting non-ASCII characters
in the input and output to the shell command, use C-x RET c
before this command. By default, the input (from the current buffer)
is encoded in the same coding system that will be used to save the file,
`buffer-file-coding-system'. If the output is going to replace the region,
then it is decoded from that same coding system.
The noninteractive arguments are START, END, COMMAND,
OUTPUT-BUFFER, REPLACE, ERROR-BUFFER, and DISPLAY-ERROR-BUFFER.
Noninteractive callers can specify coding systems by binding
`coding-system-for-read' and `coding-system-for-write'.
In other words, you'd do something like
(let ((coding-system-for-read 'utf-8-unix))
(shell-command-on-region ...) )
This is untested, not sure what the value of coding-system-for-read (or perhaps -write instead? or as well?) should be in your case. I guess you could also utilize the OUTPUT-BUFFER argument and direct the output to a buffer whose coding system is set to what you need it to be.
Another option might be to wiggle the locale in the perltidy invocation, but again, without more information about what you are using now, and no means to experiment on a system similar to yours, I can only hint.