Original
Say, I have a function like this:
(defun my-function ()
"This is my function."
:his-keyword xxx
:her-keyword yyy
(his-function)
(her-function))
After applying Emacs built-in indentation for Emacs Lisp, I get:
(defun my-function ()
"This is my function."
:his-keyword xxx
:her-keyword yyy
(his-function)
(her-function))
Of course I expected it to stay as it was, so looks like a bug to me. Does anyone know how to intercept this behavior? Or should I file a bug report? I'm on Emacs 24.3.
Update
I figured it out.
I've been extending the emacs-lisp-mode with my elisp-mode in order to add more syntax highlighting:
...
(define-derived-mode elisp-mode
fundamental-mode
"EL"
"A major mode for Emacs Lisp."
(emacs-lisp-mode)
...)
(provide 'elisp)
And then somewhere:
(require 'elisp)
(add-to-list
'auto-mode-alist
'("\\.el" . elisp-mode))
While elisp-mode was loading successfully, it turned out that emacs-lisp-mode did not load even though I've put (emacs-lisp-mode) into elisp-mode initialization (see above).
After changing to:
(define-derived-mode elisp-mode
emacs-lisp-mode
"EL"
"A major mode for Emacs Lisp."
...)
emacs-lisp-mode turns on properly and the indentation finally behaves as expected. That was pretty subtle.
Although, the 2nd variant seems more natural and right, can anyone give me a clue why the 1st variant didn't work?
original question
I cannot reproduce this with emacs -q and emacs-lisp-mode, so something is wrong with your setup.
You will have to figure out what in your .emacs triggers this behavior, and then report the bug (if it contradicts the documented behavior).
reply to your edit
I think the difference is, more or less, similar to a class inheriting from another class:
(defclass c1 (c2))
and having a field of that class:
(defclass c1 () ((a :type c2)))
See also
Defining Derived Modes
Create new mode in emacs
You might also want to ask a separate question.
Related
I'm updating some fortran 77 code to use fortran 90 constructs and emacs is my editor of choice. Currently, the source is in fixed format and that isn't going to change any time soon (due to external constraints). The two emacs major modes that I can choose from are fortran-mode which only highlights the syntax for fortran 77 constructs (It doesn't understand module or contains, etc. as keywords which I find pretty annoying, but it does understand fixed format -- correctly indenting the code where necessary). The other major mode I could use is f90-mode, however, that gets the indentation all wrong which is also slightly annoying. Is there any way to get the syntax highlighting from f90-mode, but the indentation structure used in fortran-mode?
It looks like this is indeed possible. Try adding the following to your config file:
(require 'f90)
(add-hook 'fortran-mode-hook 'f90-font-lock-2)
This is just following the solution provided on emacs.stackexchange.com, so thanks should flow to user deprecated!
You can achieve some fortran90 like highlighting in fortran-mode by adding
(add-hook 'after-change-major-mode-hook
(lambda () (font-lock-add-keywords 'fortran-mode
'(
("\\(CONTAINS\\)" 1 font-lock-keyword-face t )
("\\(USE\\)" 1 font-lock-keyword-face t )
))))
to your ~/.emacs (or ~/.emacs.d/init.el) file.
For a comprehensive solution some additional work with regular expressions would be needed. But with a few lines, you should be able to feel comfortable with your code. Different colors can be gained by using different faces:
font-lock-comment-face
font-lock-constant-face
font-lock-function-name-face
font-lock-keyword-face
font-lock-type-face
font-lock-warning-face
Emacs 23.2 in emacs-starter-kit v1 has C-x C-i (or ido-imenu) (similar to Sublime Text's Cmd+R). Emacs24 in emacs-starter-kit v2 lacks this function. I found this github issue and a fix, which try to recreate the functionality. While this ido-imenu works in elisp-mode, it stopped working in ruby-mode. I get:
imenu--make-index-alist: No items suitable for an index found in this buffer
Has anyone figured out how to get this to work?
Why was this taken out of Emacs24?
Is there a new replacement for this function?
Since the function is part of ESK (as opposed to something budled with Emacs) you'd probably do best to report the bug upstream. On a related note ESK main competitor Emacs Prelude offers the same functionality (bound to C-c i by default) and it seems to be working fine with ruby-mode in Emacs 24. Here you can find more on ido-imenu.
So I finally figured it out, after reading the Defining an Imenu Menu for a Mode section on emacs-wiki again.
Short answer: you need to add this bit to your customization. Feel free to add more types to the list (I am happy with just methods).
(add-hook 'ruby-mode-hook
(lambda ()
(set (make-local-variable imenu-generic-expression)
'(("Methods" "^\\( *\\(def\\) +.+\\)" 1)
))))
Longer answer: I first tried to define a ruby-imenu-generic-expression function and set that to imenu-generic-expression by using the ruby-mode-hook:
(defvar ruby-imenu-generic-expression
'(("Methods" "^\\( *\\(def\\) +.+\\)" 1))
"The imenu regex to parse an outline of the ruby file")
(defun ruby-set-imenu-generic-expression ()
(make-local-variable 'imenu-generic-expression)
(make-local-variable 'imenu-create-index-function)
(setq imenu-create-index-function 'imenu-default-create-index-function)
(setq imenu-generic-expression ruby-imenu-generic-expression))
(add-hook 'ruby-mode-hook 'ruby-set-imenu-generic-expression)
This however did not work (I would get the same error as before). More reading of the Defining an Imenu Menu for a Mode section showed me the way. Now, I'm not an elisp expert, so here's my hypothesis: basically, the above method works for modes where the
major mode supports a buffer local copy of the “real” variable, ‘imenu-generic-expression’. If your mode doesn’t do it, you will have to rely on a hook.
The example for foo-mode made it clear how to do it for ruby-mode. So it appears that ruby-mode does not have a buffer-local copy of the real imenu-generic-expression variable. I still can't explain why it worked in Emacs 23.2 (with ESK v1) but does not on Emacs24, but hey at least I found a working solution.
I'm currently using tuareg-mode but I would like to be able to use the functionality of caml-mode as well. In particular I want to be able to use type annotations interactively, and apparently this occurs with caml-types. I tried putting http://cristal.inria.fr/~remy/poly/emacs/index.html in my .emacs.d, but I'm confused about how or if these two modes can work together. In fact, I can't get caml-mode to work at all.
I have this line in my init.el:
(add-to-list 'load-path "~/.emacs.d/modes/caml")
But the files are not loaded - at least, none of the function definitions or keybindings are. I really thought I was starting to grasp how these emacs plugins work, but I'm starting to wonder. Maybe someone can explain what else needs to happen?
Edit: I didn't realize I had to require 'caml for this to work. Still, annotations don't seem to be working although I have caml-types from http://caml.inria.fr/svn/ocaml/branches/gadts/emacs/. I compile with -annot but I'm still told there's no annotations file.
You can have type annotation with the tuareg mode.
If I have this exact ~/.emacs file:
(add-hook 'tuareg-mode-hook '(lambda ()
(define-key tuareg-mode-map [f10] 'caml-types-show-type); requires caml-types
))
(add-to-list 'auto-mode-alist '("\\.ml\\w?" . tuareg-mode))
(autoload 'caml-types-show-type "caml-types" "Show the type of expression or pattern at point." t)
then pressing F10 shows the type of the expression under the point.
As you know, you need to compile your file foo.ml with
ocamlc -annot foo.ml
so that there is a file foo.annot in the same directory as foo.ml.
I'm an Emacs user with no skills with regards to configuring the editor. After I upgraded from haskell-mode 2.4 to 2.7, I've noticed two changes:
Indentation is different somehow, in a way I don't quite like. I can't quite put my finger on what it is.
More importantly: If I have cua-mode enabled and highlight a block of text, backspace/delete does not delete the entire block, just the previous/next character from my marker.
I see that haskell-mode 2.7 uses the minor mode haskell-indentation-mode by default, while 2.4's behaviour has been preserved in the form of haskell-indent-mode. If I first turn off the former, and then on the latter, the behaviour I want is restored (i.e. indentation feels like before, and backspace/delete deletes highlighted blocks).
I can't, however, get this to happen automatically whenever I open a file with a .hs suffix. I've tried various things resembling
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indentation-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent-mode)
and the likes of it, but I either end up with the standard mode or with plain haskell-mode without indent and doc.
Any ideas?
Solution (thanks to nominolo):
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indent)
(remove-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
(defun my-haskell-mode-hook ()
(haskell-indentation-mode -1) ;; turn off, just to be sure
(haskell-indent-mode 1) ;; turn on indent-mode
)
The best way to configure such things is by writing a custom hook:
(add-hook 'haskell-mode-hook 'my-haskell-mode-hook)
(defun my-haskell-mode-hook ()
(haskell-indentation-mode -1) ;; turn off, just to be sure
(haskell-indent-mode 1) ;; turn on indent-mode
;; further customisations go here. For example:
(setq locale-coding-system 'utf-8 )
(flyspell-prog-mode) ;; spell-checking in comments and strings
;; etc.
)
You could also stick an anonymous function in there, but having a named function is easier if you want to experiment with some settings. Just redefining the function (and re-opening a Haskell file) will give you the new behaviour.
Vim's Ctrl+N generally works like this: I type few letters, hit Ctrl+N, and Vim provides me with completions based on words in my all opened buffers.
Solution for Emacs doesn't have to be identical. I mainly use it like this: declare variable, then use it in later code. But I like the lightweight approach of not parsing the source code.
You want dabbrev-expand, bound to M-/ by default. I haven't used Vim, but from your description, it does the exact same thing.
try hippie-expand, bound to your favorite key
(global-set-key (kbd "M-/") 'hippie-expand)
Instead of presenting a completion-list, repeatedly hitting the bound-key cycles through the completions in-place.
Why "hippie"-expand? I have no idea, and I actually avoided looking at the function because the name was uninformative and off-putting, until I read the write-up at 'Life Is Too Short For Bad Code'. (The EmacsWiki entry on hippie-expand also asks "why 'hippie?'" but can't answer it, either.)
I personally use AutoComplete It gives you a nice dropdown box. You can select how many letters you want to type before it activates and customise what you want to show up, including stuff in dabbrev-expand.
;; Allow tab to autocomplete
(defun indent-or-expand (arg)
"Either indent according to mode, or expand the word preceding point."
(interactive "*P")
(if (and
(or (bobp) (= ?w (char-syntax (char-before))))
(or (eobp) (not (= ?w (char-syntax (char-after))))))
(dabbrev-expand arg)
(tab-to-tab-stop)))
(defun my-tab-fix ()
(local-set-key [tab] 'indent-or-expand))
(add-hook 'as-mode-hook 'my-tab-fix)
(add-hook 'java-mode-hook 'my-tab-fix)
(add-hook 'c-mode-hook 'my-tab-fix)
(add-hook 'sh-mode-hook 'my-tab-fix)
(add-hook 'emacs-lisp-mode-hook 'my-tab-fix)
The matter, in my opinion is that emacs completion I tryed doesn't complete regarding the context.
For instance, if you write some OOP with a method foobar() and an argument foo, M-/ will suggest you both foo and foobar.
But it would be great if you are calling an object method, not to provide just "foo" completion.
Has anyone a solution?
Aif> This requires much more than what "hippie expand" has to offer. If you code C/C++ you COULD use ECB http://ecb.sourceforge.net/ but frankly, the project is quite dead and this addon is not very reliable. If you need really good intelligent completion you should try Eclipse (CDT). But if you code python then Emacs (rope + flymake) is just as fine as Eclipse (PyDev).