Emacs auto compelete paren, indent and new line - how to? - emacs

In C - I want that when I type a { and then } emacs will insert a new line between them and then set the cursor in between them. For example:
int main() {
now I type } and the following happens:
int main()
{
//cursor is here
}
Edit: forgot to mention - I want emacs to know that when defining a function that it should do what was described above but when doing a for loop, or if statement for example I want it to do the following:
if (bla bla) {
type } and... :
if (bla bla) {
//cursor here
}

If you don't mind that the behaviour will be only almost, but not exactly the way you described it, there is a built-in way to do that. It's the auto-newline feature, that can be activated with the key combination C-c C-a or this line your .emacs:
(c-toggle-auto-newline 1)
The difference is that it will do the reformatting right after entering the opening brace {. When you finally enter the closing brace, it will indent it the right way, too.
You also need to set the right CC Mode style. The style "cc-mode" seems to define things the way you described it. You can activate it with the key combination C-c . and then choosing cc-mode, or the .emacs line
(c-set-style "cc-mode")
The c-mode functions are autoloaded and will therefore usually not be available while loading the .emacs file. Therefore you should wrap them in a hook for c-mode, like this
(add-hook 'c-mode-hook
(lambda ()
(c-toggle-auto-newline 1)
(c-set-style "cc-mode")))

As for the { stuff:
(define-minor-mode c-helpers-minor-mode
"This mode contains little helpers for C developement"
nil
""
'(((kbd "{") . insert-c-block-parentheses))
)
(defun insert-c-block-parentheses ()
(interactive)
(insert "{")
(newline)
(newline)
(insert "}")
(indent-for-tab-command)
(previous-line)
(indent-for-tab-command)
)
Paste the above into your .emacs. You can activate it with c-helpers-minor-mode.
Edit: The above inserts everything by just pressing {. The script below should do it if you type {}:
(defun insert-latex-brackets (opening closing) ; prototype function for all enclosing things
(interactive)
(insert opening)
(insert " ")
(insert closing)
(backward-char (+ 1 (length closing )))
)
(defun check-char-and-insert (char opening closing)
(interactive)
(if (equal char (char-to-string (char-before (point))))
(progn (delete-backward-char 1)
(insert-latex-brackets opening closing))
(insert char)
)
)
(local-set-key (kbd "}") 'check-char-and-insert)
One last note: You could try using yasnippet, which can be a real time saver used properly.

Related

Emacs24 and python-mode: indention in docstrings

I have the following code/text:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
In Emacs23 (23.4.1) I was able to press TAB in the last line ("second note line"; nomatter how this line was indented) and it was aligned correctly like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e., it uses the previous line and indents the following line in the same way.
Now in Emacs24 (24.3.1) this does not work anymore and it is aligned like this:
def f():
"""
Return nothing.
.. NOTE::
First note line
second note line
I.e. it aligns the multi-line string block, but does not depend on the previous line.
It affects only docstrings; code is indented as I want. I am using python-mode. How can I change this, so that pressing TAB aligns the block correctly?
Python mode has changed quite a bit between Emacs 23 and 24. There is no configuration that would allow you to do what you want.
But, Emacs is quite flexible and you can advise the (python-indent-context) function to make it return a different result that will lead to the behavior you want. The function (python-indent-context) returns a character at which the indentation is measured and used for indenting the current line. By default, when inside a string, it returns the point where the beginning of the string resides. Thus, your line will be indented to the indentation of the start of the string. We can easily modify it to return a point in the previous non-empty line instead, for instance like this:
(defun python-fake-indent-context (orig-fun &rest args)
(let ((res (apply orig-fun args))) ; Get the original result
(pcase res
(`(:inside-string . ,start) ; When inside a string
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point))))
(_ res)))) ; Otherwise, return the result as is
;; Add the advice
(advice-add 'python-indent-context :around #'python-fake-indent-context)
The same effect can be achieved using the old defadvice for older Emacs:
(defadvice python-indent-context (after python-fake-indent-context)
(pcase ad-return-value
(`(:inside-string . ,start) ; When inside a string
(setq ad-return-value ; Set return value
`(:inside-string . ,(save-excursion ; Find a point in previous non-empty line
(beginning-of-line)
(backward-sexp)
(point)))))))
(ad-activate 'python-indent-context)
What about editing the section de-stringified in a separate buffer? That would allow python-mode with all its facilities.
Here a first draft - original string will be stored in kill-ring:
(defun temp-edit-docstring ()
"Edit docstring in python-mode. "
(interactive "*")
(let ((orig (point))
(pps (parse-partial-sexp (point-min) (point))))
(when (nth 3 pps)
(let* (;; relative position in string
(relpos (- orig (+ 2 (nth 8 pps))))
(beg (progn (goto-char (nth 8 pps))
(skip-chars-forward (char-to-string (char-after)))(push-mark)(point)))
(end (progn (goto-char (nth 8 pps))
(forward-sexp)
(skip-chars-backward (char-to-string (char-before)))
(point)))
(docstring (buffer-substring beg end)))
(kill-region beg end)
(set-buffer (get-buffer-create "Edit docstring"))
(erase-buffer)
(switch-to-buffer (current-buffer))
(insert docstring)
(python-mode)
(goto-char relpos)))))
When ready, copy the contents back into original buffer.
Which remains to be implemented still.

Moving the cursor inside brackets and intent when pressing RETURN

Let's see if I achieve to explain it. When I type this in emacs 24:
int foo() {|}
Note: | = Cursor
And press the Return key, I get the next output:
int foo() {
|}
So, my question is: how can I achieve the next behaviour?
int foo() {
|
}
Instead of global-set-key you should probably use something like (define-key 'c++-mode-map ..., but here's the basics.
(defun newline-and-push-brace ()
"`newline-and-indent', but bracket aware."
(interactive)
(insert "\n")
(when (looking-at "}")
(insert "\n")
(indent-according-to-mode)
(forward-line -1))
(indent-according-to-mode))
(global-set-key (kbd "RET") 'newline-and-push-brace)
You could define a function that checks if you're in that situation and does what you want if you are, and otherwise just calls whatever the newline command for your major mode is, e.g.:
(defun brackets-newline (point)
(interactive "d")
(setq next-char (char-before point))
(if (and next-char
(char-equal next-char 123))
;; if we are sitting in front of a close bracket, do what you want
(progn
(newline)
(newline)
(previous-line)
;;call whatever "TAB" is in this mode
(funcall (key-binding (kbd "TAB"))))
;; otherwise just insert a newline
(newline)))
Then bind this to (kbd "RET")
There may be a better way to do this using defadvice or some such, this seemed to work pretty well for me though.

Context-sensitive font-locking in emacs

Basically, I'm trying to syntax highlight the following piece of coffeescript code the way I want it. Explanation of the syntax of coffeescript functions can be found here.
nameHere = (tstamp, moo, boo) ->
...
The names tstamp, moo and boo should be colored pink (and nothing else, not the commas and not the brackets) because they are parameters to a lambda function.
highOrderFun ((x) -> x * x) someList
Here it is the first x that is the parameter. Parameters can have default arguments:
class Foo
meth: (msg = "Hello", bar = "foo") ->
....
Default arguments can be variables themselves:
defColor = "red"
print = (msg, color = defColor) ->
...
So msg and color above should be highlighted, but not defColor. An even trickier case is functions with default arguments that themselves are functions. I think that is to hard for emacs' font-lock to highlight correctly, but I'm including it anyway:
funTakingFuns = (f1 = ((a, b) -> a*b), f2 = ((c, d) -> c/d)) ->
...
This appears to be pretty complicated to achieve in emacs because you want the highlighting to be context sensitive. I've read up on the documentation on font-lock but haven't been able to figure it out.
I'd be grateful if someone could show me what to set font-lock-defaults to make it syntax highlight the way I want it.
Update Showing more coffeescript syntax examples.
font-lock-keywords allows function values in the MATCHER field:
where MATCHER can be either the regexp to search for, or the function name to
call to make the search (called with one argument, the limit of the search;
it should return non-nil, move point, and set match-data appropriately if
it succeeds; like re-search-forward would).
So we need to write a function that would search for the next function argument in the buffer.
Something like this:
(defun coffee-match-next-argument (limit)
(let ((start (point)))
;; Look for the arrow.
(when (re-search-forward ") *->" limit t)
;; Save the position of the closing paren.
(let ((stop (point)))
(goto-char (match-beginning 0))
;; Go to the opening paren.
(goto-char (nth 1 (syntax-ppss)))
;; If we're before our initial position, go forward.
;; We don't want to find the same symbols again.
(when (> start (point))
(goto-char start))
;; Look for the next symbol until the arrow.
(or (re-search-forward "\\((\\|,\\) *\\(\\(\\sw\\|_\\)+\\)" stop 'mv)
(coffee-match-next-argument limit))))))
And the setup, to use with existing coffee-mode:
(font-lock-add-keywords
'coffee-mode
'((coffee-match-next-argument 2 font-lock-variable-name-face)))
You can also use this in font-lock-defaults, of course.
This will likely use some other color than pink, but that's easy to change.
This is more kind of a hack, it's far from optimal (as I am not familiar at all with coffeescript), but perhaps with a little tweaking yourself, you can get this done.
All the ingredients are there.
The triggering of the commands/functions are based on the assumption that you use coffee-mode.
If you do not, this is not a big trouble, you'll just have to hook these things differently.
Put the following line in your .emacs:
(eval-after-load 'coffee '(load "/PATH/custom-coffee-font-lock.el"))
You can just save the below text as a file, and it will:
(1) Font lock when you trigger coffee-mode
(2) Font lock current line when you type the ">" as part of "->"
(3) Allow to font-lock the buffer by running M-x coffee-init-font-lock
;;;; custom-coffee-font-lock
;; Firstly, create a new font for this.
(make-face 'font-lock-coffeescript-face)
(set-face-foreground 'font-lock-coffeescript-face "pink")
;; Next, one function that should be ran after a file is identified as
;; a coffeescript file. It will do the font-locking you want on
;; the whole buffer. It is also possible to run it manually.
(defun coffee-init-font-lock ()
(interactive)
(save-excursion
(goto-char 1)
(while (search-forward-regexp "=.+->" nil t)
(search-backward-regexp "(")
(forward-char 1)
(add-text-properties
(point) (- (search-forward-regexp "," nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))
(add-text-properties
(point) (- (search-forward-regexp "," nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))
(add-text-properties
(point) (- (search-forward-regexp ")" nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))
(move-end-of-line 1)))
)
;; This actually runs that function.
(coffee-init-font-lock)
;; This advice will be ran everytime you write something. It will check
;; whether "->" is before it, so when you type the final ">", it will
;; do the font locking for the current line (it also checks for your mode).
(defadvice self-insert-command (after coffee-font-lock activate)
(when (and (looking-back "->") (eq major-mode 'coffee-mode))
(save-excursion
(search-backward-regexp "(")
(forward-char 1)
(add-text-properties
(point) (- (search-forward-regexp "," nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))
(add-text-properties
(point) (- (search-forward-regexp "," nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))
(add-text-properties
(point) (- (search-forward-regexp ")" nil nil) 1)
'(font-lock-face font-lock-coffeescript-face))))
)
(provide 'custom-coffee-font-lock)
;;; custom-coffee-font-lock.el
If you have any requests, let me know. Like I said, I do not use CoffeeScript, so this might throw huge errors your way. At the very least it should help with some basic ideas.
Result:

How to switch the point to previous line after a } was input?

I am working with emacs24 with cc-mode, I want to know how to make my emacs more "clever". After I type a }, it will auto insert a new line and indent as excepted. I want to know how to switch the point to previous line.
For example, when i define a function, Now my emacs behavior is:
void f()
{
}
//point
"//point" is the position of cursor after } was input.
But i want is this:
void f()
{
//point
}
I hope the position of cursor can switch to previous line and indent automatically.
I know emacs can do this, but I don't know how to do it, who can help me?
I think you are after these.. C-M-u, C-M-d, C-M-f and C-M-b
Practice a bit... They are kind of global and they do behave contextually in almost all modes..
UPDATE:
ohh.. It seems you want to place the cursor automatically.. actually in more general Emacs will help you not to type } at all. I mean emacs can insert closing paran automatically.
There is inbuilt one
electric pair mode
third party
autopair.el
I don't trust anything electric, so I wrote this function.
(defconst insert-logical-brackets-logical-bracket-begin "{")
(defconst insert-logical-brackets-logical-bracket-end "}")
(defconst insert-logical-brackets-default-style 0)
(make-variable-buffer-local 'logical-bracket-begin)
(make-variable-buffer-local 'logical-bracket-end)
(make-variable-buffer-local 'insert-logical-brackets-default-style)
(defun insert-logical-brackets(&optional style)
"If STYLE = 0(default, according to `insert-logical-brackets-default-style' value), make a newline before opening bracket, if line is not empty. Make a newline after closing bracket, if there is something after this bracket. Make two newlines in the middle.
If STYLE = 1, don't make newlines before opening a bracket(one of c styles).
If STYLE = 2, don't make newlines before opening and after closing bracket.
If STYLE = 3, allways make all newlines.
If STYLE is not nil, don't make newlines between brackets(still makes before/after lines)."
(interactive "P")
(when (eq style nil)
(setq style insert-logical-brackets-default-style))
(funcall indent-line-function)
(unless (or (eq 1 style) (eq 2 style))
(when (or (/= (point) (save-excursion (back-to-indentation) (point))) (eq 3 style))
(newline)
(funcall indent-line-function)))
(unless (and (integerp style) (= 2 style))
(when (or (not (looking-at "\n")) (eq 3 style))
(newline)
(funcall indent-line-function)
(forward-line -1)
(goto-char (point-at-eol))))
(insert logical-bracket-begin)
(funcall indent-line-function)
(let ((return-point (point)))
(when (or (not style) (or (eq 0 style) (eq 1 style) (eq 2 style) (eq 3 style)))
(newline)
(funcall indent-line-function)
(setq return-point (point))
(newline))
(insert logical-bracket-end)
(funcall indent-line-function)
(goto-char return-point)))
Take a look at template systems like yasnippet: http://www.emacswiki.org/emacs/CategoryTemplates
auto-indent-mode maybe what you want!

Highlighting correctly in an emacs major mode

I am developing an emacs major mode for a language (aka mydsl). However, using the techniques on xahlee's site doesn't seem to be working for some reason (possibly older emacs dialect..)
The key issues I am fighting with are (1) highlighting comments is not working and (2), the use of regexp-opt lines is not working.
I've reviewed the GNU manual and looked over cc-mode and elisp mode... those are significantly more complicated than I need.
;;;Standard # to newline comment
;;;Eventually should also have %% to %% multiline block comments
(defun mydsl-comment-dwim (arg)
"comment or uncomment"
(interactive "*P")
(require 'newcomment)
(let
((deactivate-mark nil)
(comment-start "#")
(comment-end "")
comment-dwim arg)))
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;;Highlight various elements
(setq mydsl-hilite
'(
; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
))
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
(define-derived-mode mydsl-mode fundamental-mode
"MYDSL mode is a major mode for editing MYDSL files"
;Recommended by manual
(kill-all-local-variables)
(setq mode-name "MYDSL script")
(setq font-lock-defaults '((mydsl-hilite)))
(if (null mydsl-tab-width)
(setq tab-width mydsl-tab-width)
(setq tab-width default-tab-width)
)
;Comment definitions
(define-key mydsl-mode-map [remap comment-dwim] 'mydsl-comment-dwim)
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)
You have a couple of syntactic problems in your code, but you got it nearly correct. Here's my edited version which appears to do the right thing for a buffer in mydsl-mode:
; No changes to the simple vars
(defvar mydsl-events
'("reservedword1"
"reservedword2"))
(defvar mydsl-keywords
'("other-keyword" "another-keyword"))
;; I'd probably put in a default that you want, as opposed to nil
(defvar mydsl-tab-width nil "Width of a tab for MYDSL mode")
;; Two small edits.
;; First is to put an extra set of parens () around the list
;; which is the format that font-lock-defaults wants
;; Second, you used ' (quote) at the outermost level where you wanted ` (backquote)
;; you were very close
(defvar mydsl-font-lock-defaults
`((
;; stuff between "
("\"\\.\\*\\?" . font-lock-string-face)
;; ; : , ; { } => # $ = are all special elements
(":\\|,\\|;\\|{\\|}\\|=>\\|#\\|$\\|=" . font-lock-keyword-face)
( ,(regexp-opt mydsl-keywords 'words) . font-lock-builtin-face)
( ,(regexp-opt mydsl-events 'words) . font-lock-constant-face)
)))
(define-derived-mode mydsl-mode fundamental-mode "MYDSL script"
"MYDSL mode is a major mode for editing MYDSL files"
;; fundamental-mode kills all local variables, no need to do it again
(setq mode-name "MYDSL script")
;; you again used quote when you had '((mydsl-hilite))
;; I just updated the variable to have the proper nesting (as noted above)
;; and use the value directly here
(setq font-lock-defaults mydsl-font-lock-defaults)
;; when there's an override, use it
;; otherwise it gets the default value
(when mydsl-tab-width
(setq tab-width mydsl-tab-width))
;; for comments
;; overriding these vars gets you what (I think) you want
;; they're made buffer local when you set them
(setq comment-start "#")
(setq comment-end "")
(modify-syntax-entry ?# "< b" mydsl-mode-syntax-table)
(modify-syntax-entry ?\n "> b" mydsl-mode-syntax-table)
;;A gnu-correct program will have some sort of hook call here.
)
(provide 'mydsl-mode)