In an org-mode file, with code like the following:
#+begin_src emacs-lisp
(add-to-list 'org-tab-before-tab-emulation-hook
(lambda ()
(when (within-the-body-of-a-begin-src-block)
(indent-for-tab-command--as-if-in-lisp-mode))))
#+end_src
I would like the TAB key to indent the code as it would if it were in a buffer in lisp mode.
What I need is:
A way to figure out whether the cursor is within a src block. It needs to not trigger when on the header line itself, as in that case the default org folding should take place.
A way to indent the code according to the mode (emacs-lisp in this case) specified in the header.
Org can already syntax highlight src blocks according to mode, and the TAB hooks are there. This looks do-able.
Since Emacs 24.1 you can now set the following option:
(setq org-src-tab-acts-natively t)
...and that should handle all src blocks.
Just move point into the code block and press C-c '
This will pop up a buffer in elisp-mode, syntax higlighting ad all...
Here's a rough solution:
(defun indent-org-src-block-line ()
"Indent the current line of emacs lisp code."
(interactive)
(let ((info (org-babel-get-src-block-info 'light)))
(when info
(let ((lang (nth 0 info)))
(when (string= lang "emacs-lisp")
(let ((indent-line-function 'lisp-indent-line))
(indent-for-tab-command)))))))
(add-to-list 'org-tab-before-tab-emulation-hook
'indent-org-src-block-line)
It only handles emacs-lisp blocks. I've only tested with the src block un-indented (not the org default).
It is tough in general to make one mode work inside another - many keyboard commands will conflict. But some of the more basic strokes, like tab for indent, newline, commenting (org will comment the lisp code with #, which is wrong) seem like they could be made to work and would have the largest impact.
(defun my/org-cleanup ()
(interactive)
(org-edit-special)
(indent-buffer)
(org-edit-src-exit))
should do it, where `indent-buffer' is defined as:
(defun indent-buffer ()
(interactive)
(indent-region (point-min) (point-max)))
Related
I am trying to write an Emacs major mode but it is not working; specifically, my keywords are not being displayed in keyword font face. I have tried to follow the tutorials but I must be doing something wrong. I know a little Lisp but I do not know Emacs scripting.
My Emacs mode script:
;; emacs mode for OldRope
;; does no work for some reason
(setq oldrope-directive-keywords-regexp (regexp-opt '("page" "link" "goto" "act" "end" "div" "span" "include")))
(defvar oldrope-font-lock-defaults '((
(oldrope-directive-keywords-regexp . font-lock-keyword-face))))
(define-derived-mode oldrope-mode fundamental-mode
"oldrope mode"
"Major mode for editing OldRope games"
(setq comment-start "/*")
(setq comment-end "*/")
(setq font-lock-defaults oldrope-font-lock-defaults))
(provide 'oldrope-mode)
Test file:
$[page start]$ Hello $[link]$ Click me $[act]$ That is right. $[end]$
(For context, this is part of https://github.com/martinellison/oldrope but that is not really relevant to the question).
You need this - the rest is OK:
(defvar oldrope-font-lock-defaults
`(((,oldrope-directive-keywords-regexp . font-lock-keyword-face))))
By simply quoting the list you were not evaluating oldrope-directive-keywords-regexp - your quoted list just had that symbol as its car.
Using either backquote (`) plus comma (,) or (list (list (cons oldrope-directive-keywords-regexp 'font-lock-keyword-face))) you evaluate that variable and use its value in the resulting list.
I am writing R Markdown (.Rmd) file with a lot of LaTeX contents. The major mode is Markdown-mode. But what I want is that: when I try to type some LaTeX commands between $$, I want to automatically turn on the LaTeX major mode, and after I end the LaTeX chunk with $$ or $, it can turn off LaTeX major mode and turn on Markdown-mode again.
The inline format for LaTeX is
$\alpha$
The equation(displaymath) format for LaTeX is
$$
\alpha + \beta
$$
A similar example is when I was writing a .Rnw file, the major mode is LaTeX, but when I edit the R
code chunk:
<<>>=
y <- 1000
#
between <<>>= and #, it turns on the ESS mode.
So can anyone help me to do the similar stuff in Markdown-LaTeX case? Thanks!
Updates after Inaimathi's answer:
Following http://www.emacswiki.org/emacs/MultipleModes#toc6, I need to modify the two-mode-mode.el
- (if (string= to-mode mode-name)
+ (if (string= to-mode major-mode)
and for emacs 24
- (make-local-hook 'post-command-hook)
Then, by Inaimathi, I put the following in my .emacs:
(require 'two-mode-mode)
(setq default-mode (list "Markdown" 'markdown-mode)
second-modes (list (list "LaTeX" "\\\[" "\\\]" 'latex-mode)))
Then the major mode switches between \[ and \].
If you're ok with your major mode changing as you navigate, two-mode-mode should be able to do what you need. You need to include that .el, then add a block that looks something like
(require 'two-mode-mode)
(setq default-mode (list "Haskell" 'haskell-mode)
second-modes (list (list "Markdown" "\[markdown|" "|\]" 'markdown-mode)))
to your ~/.emacs. The above is what I do to highlight markdown blocks while editing Elm code. For your particular use case, you'd probably need
(require 'two-mode-mode)
(setq default-mode (list "Markdown" 'markdown-mode)
second-modes (list (list "Latex" "\$\$" "\$\$" 'latex-mode)
(list "Latex" "<<>>=" "#" 'latex-mode)))
Instead. This is completely untested, includes no warranty, etc etc.
Ideally, what I'd like in that situation is for the rest of the buffer to keep markdown-mode highlighting, and have just the particular region get highlighted in latex-mode or whatever. Near as I can tell, there isn't a ready, general solution for that, but if you're up for some Elisp hacking, you could give this a read and see what you can come up with.
I'd like the corresponding, closing HTML tag to be automatically inserted whenever I open one.
So if I type
<div>
I should get
<div></div>
Without having to call to sgml-close-tag myself.
How to achieve this?
Rather than calling a hook function after every single key-stroke, it makes sense to only call it after a > was typed. This can be achieved by rebinding the > character in the keymap that sgml-mode uses.
In addition, sgml-close-tag shouldn't get called if the tag is already closed. Therefore, the following code adds a simple regexp check for that:
(defun my-sgml-insert-gt ()
"Inserts a `>' character and calls
`my-sgml-close-tag-if-necessary', leaving point where it is."
(interactive)
(insert ">")
(save-excursion (my-sgml-close-tag-if-necessary)))
(defun my-sgml-close-tag-if-necessary ()
"Calls sgml-close-tag if the tag immediately before point is
an opening tag that is not followed by a matching closing tag."
(when (looking-back "<\\s-*\\([^</> \t\r\n]+\\)[^</>]*>")
(let ((tag (match-string 1)))
(unless (and (not (sgml-unclosed-tag-p tag))
(looking-at (concat "\\s-*<\\s-*/\\s-*" tag "\\s-*>")))
(sgml-close-tag)))))
(eval-after-load "sgml-mode"
'(define-key sgml-mode-map ">" 'my-sgml-insert-gt))
If you like paredit (and if you're an emacs user, chances are you do), you may be interested in tagedit, an emacs package written by Magnar Sveen that provides paredit-like features for editing html.
The library is here: https://github.com/magnars/tagedit, and can be installed through Melpa/Marmalade (package-install tagedit).
If you enable the experimental features (tagedit-add-experimental-features), then it will automatically close tags for you and keep the corresponding closing tag text matching the opening tag text. That's on top of being able to splice, slurp, barf and all the other crazy things that paredit lets you do when working with balanced expressions...I think it's great!
I'm using yasnippet for this purpose.
To type shortcuts this answer, like <kbd>C-o</kbd>, I have the following snippet:
# -*- mode: snippet -*-
# name: kbd
# key: kbd
# --
<kbd>$0</kbd>
So I type kbdC-o and it get's expanded to <kbd></kbd> with cursor
right in the middle. You can have the same behavior for div.
You may eval this on your sgml-buffer or add ii to your sgml-hook:
(add-hook 'post-self-insert-hook
(lambda () (and (eq (char-before) ?>) (sgml-close-tag))) nil t)
Whenever you insert a ">", the function sgml-close-tag will be run for you
I'm a new user to emacs, and I don't particularly like the way emacs modes handle indentation, especially when mixing modes (say ASP and perl). I have written the following functions to indent things the way a "classic" editor would:
(defun classic-indent (width)
"Tab the current line or block the 'classic' way"
(save-excursion
(if (not (use-region-p)) (select-current-line))
(indent-rigidly (mark) (point) width)))
(defun indent-forward ()
"tab two space forward"
(interactive)
(classic-indent 2))
(defun indent-back ()
"tab two spaces back"
(interactive)
(classic-indent -2))
(defun select-current-line ()
"Select the current line"
(interactive)
(end-of-line) ; move to end of line
(set-mark (line-beginning-position)))
The idea here being to bind indent-back to <backtab> and indent-forward to <tab>. The functions work great when calling them with M-x, and the <backtab> binding works fine, but if I try to bind <tab> directly, it interfere's with all sorts of cool things like auto-completion. I tried setting indent-line-function with:
(setq indent-line-function 'indent-forward)
and setting my major modes indentation function with:
(setq cperl-indent-command 'indent-forward)
but neither has any effect. I'm not sure if I'm setting them wrong or if this is even the right approach.
to sum up, How can I override indentation with the tab key without clobbering other 'tab' behavior like auto-completion?
Emacs wiki has a whole category page about indentation and TAB: http://www.emacswiki.org/emacs/CategoryIndentation. See that for other wiki pages about libraries or snippets that give you various kinds of TAB DWIM ("smart" TAB) behavior. Here are a couple:
http://www.emacswiki.org/emacs/TabCompletion
http://www.emacswiki.org/emacs/IndentOrInsertTab
It's likely the major-mode default is overriding your setting when you load a buffer. Do something like this ensure your indent-line-function is used buffer-local and it will work.
(add-hook 'elixir-mode-hook
(lambda ()
(electric-indent-mode -1)
(setq indent-line-function 'indent-forward)))
ref: https://www.emacswiki.org/emacs/BufferLocalVariable
I've looked through a number of other questions and el files looking for something i could modify to suit my needs but I'm having trouble so I came to the experts.
Is there anyway to have a key behave differently depending on where in the line the cursor is?
To be more specific I'd like to map the tab key to go to the end of the line if I'm in the middle of the line but work as a tab normally would if my cursor is positioned at the beginning of the line.
So far I have braces and quotes auto-pairing and re-positioning the cursor within them for C++/Java etc. I'd like to use the tab key to end-of-line if for example a function doesn't have any arguments.
Behaving differently depending on where point is in the line is the easy bit (see (if (looking-back "^") ...) in the code). "[Working] as a tab normally would" is the harder bit, as that's contextual.
Here's one approach, but I was thinking afterwards that a more robust method would be to define a minor mode with its own binding for TAB and let that function look up the fallback binding dynamically. I wasn't sure how to do that last bit, but there's a solution right here:
Emacs key binding fallback
(defvar my-major-mode-tab-function-alist nil)
(defmacro make-my-tab-function ()
"Return a major mode-specific function suitable for binding to TAB.
Performs the original TAB behaviour when point is at the beginning of
a line, and moves point to the end of the line otherwise."
;; If we have already defined a custom function for this mode,
;; return that (otherwise that would be our fall-back function).
(or (cdr (assq major-mode my-major-mode-tab-function-alist))
;; Otherwise find the current binding for this mode, and
;; specify it as the fall-back for our custom function.
(let ((original-tab-function (key-binding (kbd "TAB") t)))
`(let ((new-tab-function
(lambda ()
(interactive)
(if (looking-back "^") ;; point is at bol
(,original-tab-function)
(move-end-of-line nil)))))
(add-to-list 'my-major-mode-tab-function-alist
(cons ',major-mode new-tab-function))
new-tab-function))))
(add-hook
'java-mode-hook
(lambda () (local-set-key (kbd "TAB") (make-my-tab-function)))
t) ;; Append, so that we run after the other hooks.
This page of Emacs Wiki lists several packages (smarttab, etc.) which make TAB do different things depending on the context. You can probably modify one of them to do what you want.