Using One Key for Both flymake And flyspell - emacs

I am using flymake with pyflakes to check my python code and flyspell to check my strings and comments. I want to have one function which will go to the next error, or will display information about the error if currently at an error. How would I write this function?

This code provides functionality which jumps you to the next error, and if it's a flymake error, displays information for it, if it's a flyspell error, it corrects it for you. If you don't want the auto-correction, un-comment the line that calls 'my-flyspell-message and remove the line before that which calls 'flyspell-auto-correct-word - and you'll just get a message about the word being misspelled.
The first line binds this to the keybinding C-c n. For more information on binding keys, see the info page Key Bindings.
(global-set-key (kbd "C-c n") 'my-display-error-or-next-error)
(defun my-display-error-or-next-error ()
"display information for current error, or go to next one"
(interactive)
(when (or (not (my-at-flymake-error))
(not (my-at-flyspell-error)))
;; jump to error if not at one
(my-goto-next-error))
(cond ((my-at-flymake-error)
;; if at flymake error, display menu
(flymake-display-err-menu-for-current-line))
((my-at-flyspell-error)
;; if at flyspell error, fix it
(call-interactively 'flyspell-auto-correct-word)
;; or, uncomment the next line to just get a message
;; (my-flyspell-message)
)))
(defun my-at-flyspell-error ()
"return non-nill if at flyspell error"
(some 'flyspell-overlay-p (overlays-at (point))))
(defun my-at-flymake-error ()
"return non-nil if at flymake error"
(let* ((line-no (flymake-current-line-no))
(line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no))))
line-err-info-list))
(defun my-goto-next-error ()
"jump to next flyspell or flymake error"
(interactive)
(let* ((p (point))
(spell-next-error-function '(lambda ()
(forward-word) (forward-char)
(flyspell-goto-next-error)))
(spell-pos (save-excursion
(funcall spell-next-error-function)
(point)))
(make-pos (save-excursion
(flymake-goto-next-error)
(point))))
(cond ((or (and (< p make-pos) (< p spell-pos))
(and (> p make-pos) (> p spell-pos)))
(funcall (if (< make-pos spell-pos)
'flymake-goto-next-error
spell-next-error-function)))
((< p make-pos)
(flymake-goto-next-error))
((< p spell-pos)
(funcall spell-next-error-function)))))
(defun my-flyspell-message ()
(interactive)
(let ((word (thing-at-point 'word)))
(set-text-properties 0 (length word) nil word)
(message "Missspelled word: %s" word)))

Related

Emacs jump to next annotated words or phrases

When using Emacs, I notice that words or phrases in a buffer can be annotated or highlighted by many minor modes like hi-lock-mode, flyspell-mode, flycheck-mode...
Is there any uniform way to jump to the highlighted words or phrases created by all these minor modes? Specifically, is there any package or function support jumping to the next and previous highlighted phrases?
When using Eclipse, I can do it by pressing Ctrl-. and Ctrl-,. However, when switching to Emacs, so far, I haven't found an equivalent feature.
Developing a mode which aims to tackle that kind of tasks
https://github.com/andreas-roehler/werkstatt/tree/master/general-key
Facilitates the setting of a general command.
Than this command gets different bindings according to modes - which needs to be edited by hand once. Afterwards it allows to set/change a key at one place for all related/bound commands.
See for example inside
https://github.com/andreas-roehler/werkstatt/blob/master/general-key/general-key-python-mode.el
It's alpha still notably for the install process. Bug reports resp. feature requests welcome.
Not surprisingly, #Drew has answered something related to this.
You can programmatically use isearch with something like:
(defun foo (regexp)
(interactive (list (read-regexp "Regexp: ")))
(isearch-mode t t)
(let ((isearch-regexp nil))
(isearch-yank-string regexp)))
This will pull your previous regexp history, including those from hi-lock. I imagine it would be a fun exercise to modify this to use hi-lock-regexp-history.
If you use swiper, you can restrict the search candidates to lines with highlighted patterns by hi-lock-mode.
Here is a simple wrapper of swiper:
(require 'cl-lib)
(defun swiper-over-highlights-simple ()
(interactive)
(let ((original-swiper--candidates (symbol-function 'swiper--candidates)))
(cl-letf (((symbol-function 'swiper--candidates)
(lambda ()
(let ((pattern (mapconcat #'car hi-lock-interactive-patterns "\\|")))
(cl-remove-if-not (lambda (x) (string-match-p pattern x))
(funcall original-swiper--candidates))))))
(swiper))))
In addition, you can change ivy-read's preselect argument, which initializes the first matched line inside swiper.
The following fuction, modified from swiper, finds the closest next line with a highlighted pattern:
(defun swiper-over-highlights (&optional initial-input)
(interactive)
(let ((original-swiper--candidates (symbol-function 'swiper--candidates))
(pattern (mapconcat #'car hi-lock-interactive-patterns "\\|")))
(cl-letf (((symbol-function 'swiper--candidates)
(lambda ()
(cl-remove-if-not (lambda (x) (string-match-p pattern x))
(funcall original-swiper--candidates)))))
(let ((candidates (swiper--candidates)))
(swiper--init)
(setq swiper-invocation-face
(plist-get (text-properties-at (point)) 'face))
(let ((preselect
(save-excursion
(search-forward-regexp pattern nil t)
(let* ((current-line-value (current-line))
(candidate-line-numbers (mapcar (lambda (x) (cadr (text-properties-at 0 x)))
candidates))
(preselect-line-num (cl-find-if (lambda (x) (<= current-line-value x))
candidate-line-numbers)))
(- (length candidate-line-numbers)
(length (member preselect-line-num candidate-line-numbers))))))
(minibuffer-allow-text-properties t)
res)
(unwind-protect
(and
(setq res
(ivy-read
"Swiper: "
candidates
:initial-input initial-input
:keymap swiper-map
:preselect preselect
:require-match t
:action #'swiper--action
:re-builder #'swiper--re-builder
:history 'swiper-history
:extra-props (list :fname (buffer-file-name))
:caller 'swiper))
(point))
(unless (or res swiper-stay-on-quit)
(goto-char swiper--opoint))
(isearch-clean-overlays)
(unless (or res (string= ivy-text ""))
(cl-pushnew ivy-text swiper-history))
(setq swiper--current-window-start nil)
(when swiper--reveal-mode
(reveal-mode 1))))))))

Is is possible to bind a key plus a variable in Emacs?

I have buffers named *terminal<1>*, *terminal<2>*, *terminal<3>*, etc. Is there a way to bind a key combination that will take an argument for the number? That is, I want to bind C-c 1 to switch to *terminal<1>* and C-c 2 to switch to *terminal<2>*, and so on. If I can't do this directly, is it possible to do metaprogramming in Elisp that will define all the functions for me?
In this suggestion, the interactive switch-to-terminal will take either a prefix argument C-u 2 for example, or prompt the user.
The macro then makes setting up the key bindings a little easier.
Finally I bind C-c 1 to C-c 4 to switch to *terminal<1>* to *terminal<4>*.
(defun switch-to-terminal (buf-num)
(interactive "NNumber of buffer to visist: ")
(let* ((buf-name (format "*terminal<%d>*" buf-num))
(buf (get-buffer buf-name)))
(unless buf
(error "No buffer %s" buf-name))
(switch-to-buffer buf)))
(defmacro bind-switch-to-terminal (num)
`(global-set-key
,(kbd (format "C-c %d" num))
(lambda ()
(interactive)
(switch-to-terminal ,num))))
(bind-switch-to-terminal 1)
(bind-switch-to-terminal 2)
(bind-switch-to-terminal 3)
(bind-switch-to-terminal 4)
This change uses the same switch-to-terminal function, but replaces bind-switch-to-terminal with a function. The lexical-let* allows for the creation of a closure to create unique terminal switching functions, the dotimes loop then binds for C-c 1 to C-c 9.
(defun bind-switch-to-terminal (num)
(lexical-let* ((buf-num num)
(switch-func
(lambda ()
(interactive)
(switch-to-terminal buf-num))))
(global-set-key
(kbd (format "C-c %d" buf-num))
switch-func)))
(dotimes (num 9)
(bind-switch-to-terminal (1+ num)))
You can bind keys as usual:
(global-set-key (kbd "C-c 1") (lambda ()
(interactive)
(switch-to-buffer "*terminal<1>*")))
To create all the shortcuts from 1 to 9 we would use macros.
edit: This buggy version may put you on tracks. I give up :(
(defmacro gototerminal (count)
`(global-set-key (kbd ,(concat "C-c " (number-to-string count)))
;; with the comma I want to evaluate what is inside concat
(lambda () (interactive)
(switch-to-buffer (concat "*terminal<" ,count ">*"))))
)
(progn (setq count 1)
(while (< count 10)
(gototerminal count)
(setq count (1+ count))
))
ps: an elisp debugger is edebug. Set it with C-u C-M-x
I would write a function that calls interactive with an n argument which indicates that the function reads a number from the mini buffer:
(defun test (x)
(interactive "nNumber of buffer to visit: ")
(message (concat "received number: " (number-to-string x))))
Binding this to a key will let you enter a number in the mini buffer.
Another way is to use a numerical argument:
(defun test (x)
(interactive "P")
(message (concat "received number: " (number-to-string x))))
Say you bind this function to C-c c, you can then pass it the number 2 as an argument by pressing C-u 2 C-c c.
If you avoid the usage of an existing prefix key like C-c you can trigger a command with one keypress e.g. F9.
This command can have a single key as input.
Example:
(defun test (k)
(interactive "K")
(message "Pressed key: %d" (- (aref k 0) ?0)))
(local-set-key [f9] 'test)

Make frames in Emacs GUI behaves like frames in Terminal

In terminal, Emacs manage multiple frames with names like F1, F2.... because it can't create multiple OS windows. I want the GUI version to behave this way, that is, instead of creating multiple OS windows, I want it to create many virtual frames inside a single Emacs window. Is there a way?
There is a way to mimic the frame switching behavior of terminal emacs in GUI. Here is what I did. Basicly it uses make-frame-invisible to hide inactive frames. It works well on archlinux with i3.
(defsubst +amos--is-frame-daemons-frame (f)
(and (daemonp) (eq f terminal-frame)))
(defun +amos--frame-list-without-daemon ()
"Return a list of frames without the daemon's frame."
(if (daemonp)
(filtered-frame-list
#'(lambda (f) (not (+amos--is-frame-daemons-frame f))))
(frame-list)))
(defun +amos/workspace-new ()
(interactive)
(let ((name (frame-parameter nil 'name))
(oframe (selected-frame)))
(select-frame (if (s-starts-with? "F" name)
(make-frame)
(make-frame `((name . ,name)))))
(make-frame-invisible oframe t))
(setq +amos--frame-list (reverse (+amos--frame-list-without-daemon))))
(setq +amos-tmux-need-switch nil)
;; TODO ring lru
(defun +amos/workspace-delete ()
(interactive)
(let ((f (selected-frame)))
(select-frame (previous-frame))
(make-frame-visible)
(delete-frame f))
(setq +amos--frame-list (reverse (+amos--frame-list-without-daemon)))
(+doom-modeline|set-selected-window)
(realign-windows)
(when +amos-tmux-need-switch
(shell-command! "tmux switch-client -t amos\; run-shell -t amos '/home/amos/scripts/setcursor.sh $(tmux display -p \"#{pane_tty}\")'")
(setq +amos-tmux-need-switch nil)))
(defun +amos/workspace-switch-to (index)
(interactive)
(when (< index (length +amos--frame-list))
(let ((frame (nth index +amos--frame-list))
(oframe (selected-frame)))
(select-frame frame)
(raise-frame frame)
(make-frame-invisible oframe t)
(setq +amos-tmux-need-switch nil)
(realign-windows)
(recenter))))
(defun +amos/workspace-switch-to-1 () (interactive) (+amos/workspace-switch-to 0))
(defun +amos/workspace-switch-to-2 () (interactive) (+amos/workspace-switch-to 1))
(defun +amos/workspace-switch-to-3 () (interactive) (+amos/workspace-switch-to 2))
(defun +amos/workspace-switch-to-4 () (interactive) (+amos/workspace-switch-to 3))
(defun +amos/workspace-switch-to-5 () (interactive) (+amos/workspace-switch-to 4))
(defun +amos/workspace-switch-to-6 () (interactive) (+amos/workspace-switch-to 5))
(defun +amos/workspace-switch-to-7 () (interactive) (+amos/workspace-switch-to 6))
(defun +amos/workspace-switch-to-8 () (interactive) (+amos/workspace-switch-to 7))
(defun +amos/workspace-switch-to-9 () (interactive) (+amos/workspace-switch-to 8))
(defun +amos-workspace-cycle (off)
(let* ((n (length +amos--frame-list))
(index (-elem-index (selected-frame) +amos--frame-list))
(i (% (+ off index n) n)))
(+amos/workspace-switch-to i)))
(defun +amos/workspace-switch-left () (interactive) (+amos-workspace-cycle -1))
(defun +amos/workspace-switch-right () (interactive) (+amos-workspace-cycle +1))
(defun +amos|maybe-delete-frame-buffer (frame)
(let ((windows (window-list frame)))
(dolist (window windows)
(let ((buffer (window-buffer (car windows))))
(when (eq 1 (length (get-buffer-window-list buffer nil t)))
(kill-buffer buffer))))))
(add-to-list 'delete-frame-functions #'+amos|maybe-delete-frame-buffer)
If what you mean is that you want to be able to access frames by name, then yes, you can do this with Icicles.
By default, C-x 5 o is bound to multi-command icicle-select-frame. This lets you select one or more frames by name.
A frame's name comes from its name frame parameter. It is suffixed as needed by [NUMBER], to
make it unique. For example, in a context where frames are named for
their buffers and you have two frames showing buffer *Help*, one of
the frames will be called *Help*[2] for use with this command.
Frame selection with C-x 5 o uses completion and cycling. The completion can be vanilla Emacs completion or regexp (including, of course, substring) completion. (It can also be any of several fuzzy completions.)
(If, for some reason, you want the frame names to be just F1, F2, etc., as with terminal Emacs, then you just need to do that at the level of frame parameter name. You can do that using hooks etc.)

Emacs: swapping replace queries

Using query-replace, the minibuffer says this (having saved the previous arguments):
Query replace (default FROM -> TO)
is there a command to swap the args? To get this:
Query replace (default TO -> FROM)
AFAIK, nothing out of the box does that for you. But IMHO you don't need that.
All you need to do is use M-p. Use it once to get the last TO you used. Then repeat M-p a couple times to get the last FROM you used. Very quick.
After that, you can use C-x ESC ESC (or C-x M-: or C-x M-ESC), possibly followed by M-p, to repeat either combination (TO -> FROM or FROM -> TO).
(defun swap-query-replace-defaults ()
"Swap the initial expressions offered by `query-replace'. "
(interactive)
(let* ((erg query-replace-defaults)
(first (car erg))
(second (cdr erg)))
(setq query-replace-defaults (cons second first))
(when (interactive-p) (message "%s" query-replace-defaults))
query-replace-defaults))
Made a feature-request:
http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-10/msg00102.html
There's a shortcut to swap the args: M-p RET M-p M-p RET
I use this:
;; Redefine `query-replace-read-from' to add a custom keymap when
;; replacing strings. Now, C-u ENTER does the reverse suggested
;; replacement.
(defvar query-replace-keymap
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map [remap exit-minibuffer]
(lambda ()
(interactive)
(if (and current-prefix-arg query-replace-defaults)
(setq query-replace-defaults
(cons
(cdr query-replace-defaults)
(car query-replace-defaults))))
(exit-minibuffer)))
map))
(defun query-replace-read-from (prompt regexp-flag)
"Query and return the `from' argument of a query-replace operation.
The return value can also be a pair (FROM . TO) indicating that the user
wants to replace FROM with TO."
(if query-replace-interactive
(car (if regexp-flag regexp-search-ring search-ring))
(let* ((history-add-new-input nil)
(query-replace-defaults query-replace-defaults)
(prompt
(if query-replace-defaults
(format "%s (default %s -> %s): " prompt
(query-replace-descr (car query-replace-defaults))
(query-replace-descr (cdr query-replace-defaults)))
(format "%s: " prompt)))
(from
;; The save-excursion here is in case the user marks and copies
;; a region in order to specify the minibuffer input.
;; That should not clobber the region for the query-replace itself.
(save-excursion
(if regexp-flag
(read-regexp prompt nil query-replace-from-history-variable)
(read-from-minibuffer
prompt nil query-replace-keymap nil query-replace-from-history-variable
(car (if regexp-flag regexp-search-ring search-ring)) t)))))
(if (and (zerop (length from)) query-replace-defaults)
(cons (car query-replace-defaults)
(query-replace-compile-replacement
(cdr query-replace-defaults) regexp-flag))
(add-to-history query-replace-from-history-variable from nil t)
;; Warn if user types \n or \t, but don't reject the input.
(and regexp-flag
(string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\[nt]\\)" from)
(let ((match (match-string 3 from)))
(cond
((string= match "\\n")
(message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
((string= match "\\t")
(message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
(sit-for 2)))
from))))

Shortcut for inserting environments in `org-mode`

I'm using org-mode for organizing myself (very useful so far!). However, it is kind of annoying writting
#+begin_comment
...
#+end_comment
each time I'd like to insert an environment.
Question
Is there a shortcut to insert the #+begin_ and #+end_ for a given environment?
In the same way C-c C-o comment RET would insert
\begin{comment}
\end{comment}
in latex-mode.
Org has a facility called "Easy templates": http://orgmode.org/manual/Easy-Templates.html
A template for comment is missing but you can add it with:
(add-to-list 'org-structure-template-alist '("C" "#+begin_comment\n?\n#+end_comment"))
And use it by typing <C followed by TAB.
Alternatively, you could use yasnippet.
Now the corresponding template section is called Structure Template and the insertion sequence is invoked by C-c C-,. I didn't (require 'org-tempo) which is described to support insertion keys like <s TAB.
The comment environment is already defined in org-structure-template-alist. So the comment would be inserted by
C-c C-, C
It's still possible to add a user defined sequence by, for example,
C-c C-, [TAB|RET|SPC] src python :results output :session
delivering
#+begin_src python :results output :session
#+end_src
(emacs 25.2.2, org-mode 9.2)
You could have a look at "org-auctex-keys.el", a minor mode which I created to offer AUCTeX key bindings within Org documents.
In this case, you'd use C-c C-e to insert an environment (prompt to enter the environment name), as what AUCTeX does.
If you're interested, check it out at https://github.com/fniessen/org-auctex-key-bindings.
Not as elegant as the answer of Michael Markert but maybe more expandable.
1) You can select a region and put the block around it or you can just put the block at point.
2) Keyword expansion and history.
3) Keystrokes: C-c b
The command could be further expanded. E.g., for the src block the various switches like -n -r and export to files could be supported.
(defun list-major-modes ()
"Returns list of potential major mode names (without the final -mode).
Note, that this is guess work."
(interactive)
(let (l)
(mapatoms #'(lambda (f) (and
(commandp f)
(string-match "-mode$" (symbol-name f))
;; auto-loaded
(or (and (autoloadp (symbol-function f))
(let ((doc (documentation f)))
(when doc
(and
(let ((docSplit (help-split-fundoc doc f)))
(and docSplit ;; car is argument list
(null (cdr (read (car docSplit)))))) ;; major mode starters have no arguments
(if (string-match "[mM]inor" doc) ;; If the doc contains "minor"...
(string-match "[mM]ajor" doc) ;; it should also contain "major".
t) ;; else we cannot decide therefrom
))))
(null (help-function-arglist f)))
(setq l (cons (substring (symbol-name f) 0 -5) l)))))
(when (called-interactively-p 'any)
(with-current-buffer (get-buffer-create "*Major Modes*")
(clear-buffer-delete)
(let ((standard-output (current-buffer)))
(display-completion-list l)
(display-buffer (current-buffer)))))
l))
(defvar org-insert-block-hist nil
"History for command `org-insert-block'")
(defvar org-insert-block-hist/src:major nil
"History for major mode in org src blocks.")
(defvar org-insert-block-list (append org-protecting-blocks
'("comment" ""))
"List of block types offered as completion for command `org-insert-block'")
;; block_src switches: -n () -r (references) -l "((%s))" (label format) -k (keep labels)
(defvar org-insert-block-list-specials
"Assoc list of Commands for reading additional specification of org-blocks.")
(setq org-insert-block-list-specials
'(("src" . (concat " " (completing-read "Major mode:"
(list-major-modes)
nil nil
(car org-insert-block-hist/src:major)
'(org-insert-block-hist/src:major . 1)
)))))
(defun org-insert-block (bl &optional b e attributes)
"Put region between b and e into org-block of kind bl.
If b or e is nil then put org-block limiters around point.
The string attributes is inserted behind the string #+begin_... "
(interactive
(let ((usereg (use-region-p))
(blKind (completing-read "Input block kind (tab: completion, uparrow: history):"
org-insert-block-list nil nil (car org-insert-block-hist) '(org-insert-block-hist . 1))))
(list
blKind
(when usereg (region-beginning))
(when usereg (region-end))
(let ((spec (assoc blKind org-insert-block-list-specials)))
(when spec (eval (cdr spec)))
))))
(let ((begBlock (concat "\n#+begin_" bl attributes "\n"))
(endBlock (concat "\n#+end_" bl "\n")))
(if (and b e)
(save-restriction
(narrow-to-region b e)
(goto-char (point-min))
(insert begBlock)
(goto-char (point-max))
(insert endBlock)
(indent-region (point-min) (point-max)))
(let ((p (point)))
(insert endBlock)
(goto-char p)
(insert begBlock))
)))
(add-hook 'org-mode-hook '(lambda ()
(local-set-key (kbd "C-c b") 'org-insert-block)))