mmm-mode: Implementing C++ mode as a submode - emacs

We use an internal scripting language (let's call it pkc), which allows for embedding C++ code. The C++ code segments are delimited by {{{ and }}} markers.
I create an emacs mode for this language, using Generic Mode and mmm-mode.
Here is what I got (stripped down non-essential parts for posting here):
(require 'generic-x)
(setq pkc-imenu-generic-expression
'(("macros" "^[ \t]*macro[ \n\t]+\\([a-zA-Z0-9_]+\\)" 1)
("functions" "function[ \n\t]+\\([a-zA-Z0-9_]+\\)" 1)
))
(require 'cc-mode) ;; for c++-mode
(require 'mmm-auto)
(setq mmm-global-mode 'maybe)
(define-generic-mode
'pkc-mode ;; name of the mode to create
'("//" ("/*" . "*/")) ;; comments are same C++ comments
'( ... ) ;; some keywords
'("\\.pkc$") ;; files for which to activate this mode
;; other functions to call
'((lambda ()
(mmm-mode 1)
(setq mmm-submode-decoration-level 2)
(setq imenu-generic-expression pkc-imenu-generic-expression)
(which-function-mode 1)
(c-initialize-cc-mode t)
(c-init-language-vars-for 'c++-mode)
(c-common-init 'c++-mode)
(c-update-modeline)
(message "pkc-mode[mmm] is on")))
"A mode for pkc source files" ;; doc string for this mode
)
(mmm-add-classes
'((embedded-c++
:submode c++-mode
:face mmm-default-submode-face
:front "{{{"
:front-offset -1
:back "}}}"
:back-offset 1)))
(mmm-add-mode-ext-class 'pkc-mode nil 'embedded-c++)
When I load the source file with embedded C++ code segments, they are highlighted somewhat less than what would have been if C++ mode was the major mode (that's not my problem, however). When the cursor in C++ code, the modeline changes to pkc/l[C++/l] (as expected).
The problem is, whenever I press TAB to indent a line, I get the error Wrong type argument: stringp, nil. When I turned on debugger, this is the stack trace I see:
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
c-syntactic-skip-backward(nil nil t)
c-looking-at-decl-block(nil t)
c-guess-basic-syntax()
c-indent-line()
#[nil \302>\203)\212\303 \210\304\305x\210\303 \210\306 )i\306 X\203\"\307 !\202'\212\307 !))\20 \207" [indent-line-function column (indent-relative indent-relative-maybe) beginning-of-line "\n " nil current-indentation indent-line-to] 2 1908700 nil]()
c-indent-command(nil)
c-indent-line-or-region(nil nil)
call-interactively(c-indent-line-or-region nil nil)
Looking at the definition of c-looking-at-decl-block and particularly the call to `c-syntactic-skip-backward, I find:
(c-syntactic-skip-backward c-block-prefix-charset limit t)
Examining the first argument c-block-prefix-charset reveals that its value is nil. Doing the same from a plain C++ buffer shows a non-nil value. So, I suspect that C++-mode requires some initialization that's not being properly done.
So, my questions are:
What am I missing in the C++-mode initialization section in my implementation?
Am I using the right approach (combining generic-x and mmm-mode)? Is there a better approach?
I also see another error (File mode specification error) when I load the file, but I suspect the problem is the same or something similar.
Thanks for your time.

(Rewritten after the discussion in the comments, for any later visitors).
The setup in the question is basically fine, but to work with current c++-mode you need to use an updated version of mmm-mode. It's available at the GitHub project page and also at Melpa.
The relevant patches (one, two, three) added new entries to the value of mmm-save-local-variables, which mmm-mode uses to decide which local variables to save or restore when leaving or entering a submode region.
From what I understand, a future update to cc-mode can add more such vars, so the list may need to be updated from time to time.
Extra tip: to have better indentation in the subregions, you may want to wrap the submode's indent-line-function with some code that will narrow the buffer before calling it (example here). Depending on the indentation function (and whether it calls widen), it may or may not help.

Related

Emacs. Spell check "on fly" for 2 languages

Windows 7, Emacs 25.1
I need to spell check "on fly" for my custom text (e.g. to emphasize the incorrect words). But I write text in two languages: English and Russian. And I want easy to switch between spell checking for 2 languages.
What is the best emacs package for this? Thanks.
You want this: guess_language.el
(use-package guess-language ; Automatically detect language for Flyspell
:ensure t
:defer t
:init (add-hook 'text-mode-hook #'guess-language-mode)
:config
(setq guess-language-langcodes '((en . ("en_GB" "English"))
(it . ("it_IT" "Italian")))
guess-language-languages '(en it)
guess-language-min-paragraph-length 45)
:diminish guess-language-mode)
Alternatively if you just want to cycle through them:
(defvar mu-languages-ring nil "Languages ring for Ispell")
(let ((languages '("en_GB" "it_IT")))
(validate-setq mu-languages-ring (make-ring (length languages)))
(dolist (elem languages) (ring-insert mu-languages-ring elem)))
(defun mu-cycle-ispell-languages ()
(interactive)
(let ((language (ring-ref mu-languages-ring -1)))
(ring-insert mu-languages-ring language)
(ispell-change-dictionary language)))
These should work with FlySpell
I had a similar problem, the solution I found manages two or more languages at the same time without using guess_language package. This solution is based on Hunspell spelling checker.
SYSTEM:
Windows 7 SP1, GNU Emacs 26.1
First, perform a Ispell/Hunspell configuration after Hunspell installation. Insert the next code in the .emacs file, usually located within C:/Users/Account.
;; START BLOCK1 <-- Ispell/Hunspell setting
;; e.g., "C:/Hunspell/bin/hunspell.exe"
(setq-default ispell-program-name "hunspell.exe FULL PATH")
(setq-default ispell-extra-args '("--sug-mode=ultra"))
;; Set "DICTDIR" variable, e.g., "C:/Hunspell/share/hunspell"
(setenv "DICTDIR" "hunspell DICTIONARY PATH")
;; Uncomment next line to set English or another dictionary
;; (setq ispell-dictionary "en_US")
;; Automatically enable flyspell-mode in text-mode
(setq text-mode-hook '(lambda() (flyspell-mode t) ))
(require 'ispell)
;; END BLOCK1 <-- Ispell/Hunspell setting
This code is based on the spelling configuration section of another discussion, see M Parashar - Load Theme. The block code 1 works for the default dictionary, which can be changed uncommenting the line with the ispell-dictionary variable. This code works perfectly for me.
The second code block enable us to use multiple dictionaries, is based on AM Lafon - Multi Spell Checking. For me, this code block works only next of code block 1.
;;START BLOCK2<-- Multiple dictionaries. Only works with BLOCK1
(with-eval-after-load "ispell"
;; Configure `LANG`, otherwise ispell.el cannot find a 'default
;; dictionary' even though multiple dictionaries will be configured
;; in next line.
(setenv "LANG" "es_ES")
;; English/spanish configuration.
(setq ispell-dictionary "en_US,es_ES")
;; ispell-set-spellchecker-params has to be called
;; before ispell-hunspell-add-multi-dic will work
(ispell-set-spellchecker-params)
(ispell-hunspell-add-multi-dic "en_US,es_ES")
;; For saving words to the personal dictionary, don't infer it from
;; the locale, otherwise it would save to ~/.hunspell_de_DE.
(setq ispell-personal-dictionary "~/.hunspell_personal"))
;; The personal dictionary file has to exist, otherwise hunspell will
;; silently not use it.
(unless (file-exists-p ispell-personal-dictionary)
(write-region "" nil ispell-personal-dictionary nil 0))
;;END BLOCK2<-- Multiple dictionaries. Only works with BLOCK1
These two code blocks enable the spell checking for the english/spanish languages at the same time. More languages can be added to the checking system expanding the "en_US,es_ES" strings with the appropriate dictionary names. I used that ones located in the Share/Hunspell directory. There is no keybinding to change between languages and no per file dictionary assignation at the beginning of files, like this:
# -\*- ispell-dictionary: "castellano8" -\*-.
A context menu is displayed when clicking the middle mouse button over the misspelled word, an option is the Save Word entry. These words will be saved using the variable ispell-personal-dictionary in the new file called .hunspell_personal, located on the usual path.
The inclusion of the two code blocks gave the expected results. Just including the second block of code threw the error 'wrong-type-argument stringp nil'.

How to make emacs switch to *scheme* by default when eval / load from the file?

The problem:
I'm in scheme-mode (simple quack)
scheme is already running
eval expression
it sends the expression to scheme buffer
but! doesn't bring that buffer up in 2nd window = no immediate feedback
and I have to manually switch second buffer to scheme which is annoying
Some (more recent) modes like fsharp-mode or tuareg do that automatically. Tried to read quack.el, but didn't find convenient separate function like "pop scheme". It's tangled within run-scheme which also changes focus. Settings also don't help.
I want to stay in my rkt/scm file and see repl buffer pop up if not already popped. Like this simple build logic in sublime-text but with persistent repl.
Maybe I should try geiser, but quack is ok for now. Just missing few obvious conveniences.
Just rungeiser. It's in MELPA now, so it's a quick install.
You can also try lispy (which uses geiser) for in-place scheme eval.
e will eval current expression and display the result in the minibuffer.
E will eval current expression and insert the result in current buffer.
u is bound to undo, so you can either e or Eu if you prefer.
I ended up writing this:
(setq scheme-program-name "guile")
(defun run-scheme-2.0 ()
"Loads your chosen Scheme implementation for interactive development,
and displays that buffer below your main editing buffer, and makes sure that
your cursor will be on your code."
(interactive)
(if (not (get-buffer "*scheme*"))
(progn
(setq starting-buffer (buffer-name))
(run-scheme scheme-program-name)
(split-window-below)
(other-window 1)
(shrink-window-if-larger-than-buffer)
(other-window 1)
(switch-to-buffer starting-buffer))))
(add-hook 'scheme-mode-hook 'run-scheme-2.0)

Don't display *compilation* buffer in Emacs until the process exits with error or warning

I am looking for a way to have the Emacs compilation buffer triggered by M-x compile, M-x recompile or some compile on save script only appear when the compilation exits either with an error or a warning.
Note that I am not looking for a way to close the compile buffer if there are no errors or warnings as described in [1]. No I want the buffer to never appear until the compilation is fully finished and only appear if there is an error or warning to display.
The reasons are simple: The flickering compile buffer is disturbing and rearranges the position of the code on the screen. This becomes more annoying if you have compile on save turned on.
The compile buffer contains many different types of compile processes from make to pdflatex so it would be great if the function which determines whether the buffer should be displayed works across the board.
[1] emacs compile buffer auto close?
Looks like you can achieve what you want through temporarily disabling display-buffer across compilation-start.
This is a combination of what sds said and something posted on the comments # here
The comment there had a nasty problem with point jumping in the original source buffer that I appear to have worked out by also blocking set-window-point and goto-char. It feels like a dirty hack, but is working so far. YMMV!
(defun brian-compile-finish (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
t)
(setq compilation-finish-functions 'brian-compile-finish)
(require 'cl)
(defadvice compilation-start
(around inhibit-display
(command &optional mode name-function highlight-regexp))
(if (not (string-match "^\\(find\\|grep\\)" command))
(flet ((display-buffer)
(set-window-point)
(goto-char))
(fset 'display-buffer 'ignore)
(fset 'goto-char 'ignore)
(fset 'set-window-point 'ignore)
(save-window-excursion
ad-do-it))
ad-do-it))
(ad-activate 'compilation-start)
Now you should see that all compile buffers will only be shown if outstr doesn't return a successful finish status OR the invoked command started with "find" or "grep."
I edited #assem's answer to use cl-letf instead of flet.
(defun brian-compile-finish (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
t)
(setq compilation-finish-functions 'brian-compile-finish)
(defadvice compilation-start
(around inhibit-display
(command &optional mode name-function highlight-regexp))
(if (not (string-match "^\\(find\\|grep\\)" command))
(cl-letf ((display-buffer #'ignore)
(set-window-point #'ignoreco)
(goto-char #'ignore))
(save-window-excursion
ad-do-it))
ad-do-it))
(ad-activate 'compilation-start)
(provide 'only-display-compile-on-error)
The function compilation-start calls display-buffer on the compilation buffer. This should give you all the control you need.
I.e., you need to customize one of the action variables (display-buffer-overriding-action et al) so that it will handle compilation buffers specially buy displaying it in a separate frame and not displaying the frame itself.
Then you need to customize your compilation-filter-hook so that, whenever a warning or an error is inserted into the compilation buffer, the compilation buffer is displayed visibly (e.g., by popping up the aforementioned separate frame). Don't forget to bind your action variable to nil there!
assems answer has been overtaken by events, somewhat.
Emacs core, in their wisdom have decided to deprecate flet.
The suggested alternative is cl-flet. However, as discussed in this post, this seems to be lexically scoped rather than dynamically scoped. We explicitly want dynamic scoping.
Should `flet` be replaced with `cl-flet` or `cl-letf` ?
This page suggests replace flet to noflet, a third-party library.
This appears to only support the definition of functions and their bodies.
So the flet in assem's answer becomes
(noflet ((display-buffer ()) ....

Configuring emacs for latex - void-variable LaTeX-mode-hook

Following this pdf document I added the following to my ~/.emacs file:
(load "auctex.el" nil t t)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-PDF-mode t) ;; .pdf statt .dvi per default:
;;Zeilenumbruch
;;(add-hook ’LaTeX-mode-hook ’turn-on-auto-fill)
;;Syntax Higlight
(add-hook ’LaTeX-mode-hook ’turn-on-font-lock)
;; Mathe Modus
(add-hook ’LaTeX-mode-hook ’LaTeX-math-mode)
;; Reftex einflechten und laden
(setq reftex-plug-into-AUCTeX t)
(add-hook ’LaTeX-mode-hook ’turn-on-reftex)
;; Satzende ". " statt ". ". " fuer M-k: loeschen bis Satzende usw.
;;(setq sentence-end "[.?!][]\"’)}]*\\($\\| \\| \\)[
;;]*") ;; Da ist ein "Newline in der Zeile!"
;;(setq sentence-end-double-space nil)
;;direkte Rechtschreib Korrektur:
;;(add-hook ’LaTeX-mode-hook ’flyspell-mode)
;; Nur benutzen falls Auctex > 11.81 mit preview-latex:
(load "preview-latex.el" nil t t)
;; aspell ist besser als ispell.
;; Zeile kommentieren, falls nicht installiert:
(setq-default ispell-program-name "aspell")
;; Deutsche Rechtschreibung falls \usepackage{ngerman}
;; oder german benutzt wird
(add-hook ’TeX-language-de-hook
(function (lambda () (ispell-change-dictionary "german8"))))
Unfortunately emacs doesn't start now, instead it gives the error
Warning (initialization): An error occurred while loading `/home/../.emacs':
Symbol's value as variable is void: ’LaTeX-mode-hook
To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file. Start Emacs with
the `--debug-init' option to view a complete error backtrace.
When starting with --debug-init it gives the following information
Debugger entered--Lisp error: (void-variable ’LaTeX-mode-hook)
(add-hook ’LaTeX-mode-hook ’turn-on-font-lock)
eval-buffer(#<buffer *load*> nil "/home/../.emacs" nil t) ; Reading at buffer position 812
load-with-code-conversion("/home/../.emacs" "/home/../.emacs" t t)
load("~/.emacs" t t)
...
I tried using latex-mode-hook instead. I searched for a solution, but I seem to be the only one having exactly this problem.
I'm using Ubuntu 12.04 with the latest Emacs and Auctex. If required I'll post version information, but I rather think that something has to be added into the configuration or any package has to be installed instead.
How can I get emacs work with that configuration?
Are you using the wrong single quote character? it seems to be some kind of a backward quote instead of a plain single quote. Try
'LaTeX-mode-hook
instead of
’LaTeX-mode-hook
(and likewise for all other occurrences of that character).
As Thomas also said, the back quote is not the character you want to use there, it should be the single straight quote. But, in general, if you get "symbol's value as variable is void" error, it means the same as NPE (null pointer exception) in other languages. The way to check what went wrong is like so:
Move point to the variable that gives the problem and C-h v (or M-x describe-variable [name of the variable without quote]). You can use TAB to complete the variable name as you type to see if you by chance didn't mistype it.
Once you see the buffer that describes the variable - you know you've fixed the error.
Now, if you have LaTeX mode set through auctex.el, then latex-mode-hook must exist. However, you need to make sure that auctex.el actually loads and requires latex-mode. The way it does so isn't an idiomatic way for Emacs to do it, most of the time you add the source files for the mode to the load-path variable and then (require 'mode-name) or load the mode conditionally once Emacs opens the type of the file associated with it (makes startup time for Emacs shorter) through autoload as described here: Emacs: Best-practice for lazy loading modes in .emacs? .
However, whenever you see a variable called [something]-mode-hook it means that this is a list of functions you want to call when [something] mode loads up. If the [something] mode at all exists, there's a 99.99% chance that variable exists too (can't be void). So, if it is void - you need to make sure that the mode it belongs to at all loads.

Emacs: highlighting TODO *only* in comments

This question is related to another one, Emacs :TODO indicator at left side. I recently came across a minor mode I like a lot called FixmeMode. It supports auto highlighting of TODO marks, and navigating between them. However, I think it makes more sense to recognize the "TODO" strings only in comments, rather than polluting the whole file. Is it possible?
Check out the library fic-mode.el, it has been verified in C++ and Emacs-Lisp.
It was written specifically to answer this question.
The installation is like any standard package:
(require 'fic-mode)
(add-hook 'c++-mode-hook 'turn-on-fic-mode)
Though Wei Hu did ask for an easy way to add it to multiple modes, so here goes:
(defun add-something-to-mode-hooks (mode-list something)
"helper function to add a callback to multiple hooks"
(dolist (mode mode-list)
(add-hook (intern (concat (symbol-name mode) "-mode-hook")) something)))
(add-something-to-mode-hooks '(c++ tcl emacs-lisp) 'turn-on-fic-mode)
It's possible but quite a bit trickier. Fixme mode uses font-lock to do its highlighting, so it works on an as-you-type basis to highlight the keywords. Font-lock hooks in at a very low level, basically running after every change is made to the buffer's contents. It is highly optimized, though, which allows it to appear instantaneous on modern computers.
The TODO indicator in the left fringe is static. Execute the function and all current TODO's are highlighted; change the buffer (adding or removing TODO's) does not change the fringe indicator; that's only changed when the function runs again.
Your approach would have to get into syntax tables, determining first when you're in a comment and then looking for the keywords. The tricky part comes in doing this interactively (i.e. as you type). You should be able to hook into the font-lock constructs to do this, but the function you provide to search for the comment syntax table and then for the keywords better be very efficient, as it will be run each and every time a buffer changes (though it will only run on the changed region, I think). You would want to stuff all of this in font-lock-syntactic-keywords rather than font-lock-keywords because the syntactic-keyword pass happens before the syntactic pass (which happens before the keyword pass), and you need to set TODO inside comments before comments themselves are set.
Sorry it's not a full working-code answer.....
Maybe this will help: there's a fn c-in-literal in
cc-mode, and a similar csharp-in-literal in csharp mode. The
return value is c if in a C-style comment, c++ if in a C++
style comment. You could add that to the code at
Emacs :TODO indicator at left side
to get what you want.
(defun annotate-todo ()
"put fringe marker on TODO: lines in the curent buffer"
(interactive)
(let (lit)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "TODO:" nil t)
(progn
(setq lit (c-in-literal)) ;; or csharp-in-literal
(if (or (eq lit 'c) (eq lit 'c++))
(let ((overlay (make-overlay (- (point) 5) (point))))
(overlay-put overlay 'before-string
(propertize "A"
'display
'(left-fringe ;; right
horizontal-bar
better-fringes-important-bitmap))))))))))
https://github.com/tarsius/hl-todo seems to do exactly what you want. I just tried it and love it.