I'd like to create a function that offers me numbered or lettered choices (1, 2, 3, or a, b, c) of available frames to switch to, instead of manually typing the name. Aspell would be the closest example I can think of.
Could someone please share an example of how this might be done? Lines 6 to 14 of the following function creates a list of all available frame names on the fly. Additional functions related to frame switching can be found here
(defun switch-frame (frame-to)
(interactive (list (read-string (format "From: (%s) => To: %s. Select: "
;; From:
(frame-parameter nil 'name)
;; To:
(mapcar
(lambda (frame) "print frame"
(reduce 'concat
(mapcar (lambda (s) (format "%s" s))
(list "|" (frame-parameter frame 'name) "|" )
)
)
)
(frame-list) )
)))) ;; end of interactive statement
(setq frame-from (frame-parameter nil 'name))
(let ((frames (frame-list)))
(catch 'break
(while frames
(let ((frame (car frames)))
(if (equal (frame-parameter frame 'name) frame-to)
(throw 'break (select-frame-set-input-focus frame))
(setq frames (cdr frames)))))) )
(message "Switched -- From: \"%s\" To: \"%s\"." frame-from frame-to) )
EDIT (November 13, 2014): Here is a revised function using ido-completing-read:
(defun ido-switch-frame ()
(interactive)
(when (not (minibufferp))
(let* (
(frames (frame-list))
(frame-to (ido-completing-read "Select Frame: "
(mapcar (lambda (frame) (frame-parameter frame 'name)) frames))))
(catch 'break
(while frames
(let ((frame (car frames)))
(if (equal (frame-parameter frame 'name) frame-to)
(throw 'break (select-frame-set-input-focus frame))
(setq frames (cdr frames)))))))))
I see what you're trying to do. Here's how I've solved this problem:
Part 1
The files that you use every day should be bookmarked.
The reason is that you loose focus when you're reading any sort of menu,
even as short as you describe. After some time with bookmarks,
it becomes like touch-typing: you select the buffer without thinking about it.
You can check out this question
to see my system.
I've got about 20 important files and buffers bookmarked and reachable
in two keystrokes, e.g. μ k for keys.el and μ h for hooks.el.
A nice bonus is that bookmark-bmenu-list shows all this stuff, so I can
add/remove bookmarks easily
rename bookmarks (renaming changes binding)
it's clickable with mouse (sometimes useful)
bookmark+ allows function bookmarks, so I've got org-agenda on μ a
and magit on μ m.
And of course the dired bookmarks: source is on μ s and
org-files are on μ g.
Part 2
For the files that can't be bookmarked, I'm using:
(ido-mode)
(setq ido-enable-flex-matching t)
(global-set-key "η" 'ido-switch-buffer)
This is fast as well: you need one keystroke to call ido-switch-buffer
and around 2-3 letters to find the buffer you need, and RET to select.
I've also recently added this hack:
(add-hook 'ido-setup-hook
(lambda()
(define-key ido-buffer-completion-map "η" 'ido-next-match)))
With this you can use the same key to call ido-switch-buffer and cycle the selection.
Part 3
The actual function with lettered choices has been on my todo list for a while
now. I'll post back here when I get around to implementing it,
or maybe just copy the solution from a different answer:)
This answer describes Icicles command icicle-select-frame, which lets you choose frames by name using completion.
There is also Icicles command icicle-other-window-or-frame (C-x o), which combines commands icicle-select-frame, other-frame, and other-window. It lets you select a window or a frame, by its name or by order.
With no prefix arg or a non-zero numeric prefix arg:
If the selected frame has multiple windows then this is
other-window. Otherwise, it is other-frame.
With a zero prefix arg (e.g. C-0):
If the selected frame has multiple windows then this is
icicle-select-window with windows in the frame as candidates.
Otherwise (single-window frame), this is icicle-select-frame.
With plain C-u:
If the selected frame has multiple windows then this is
icicle-select-window with windows from all visible frames as
candidates. Otherwise, this is icicle-select-frame.
Depending upon the operating system, it may be necessary to use (select-frame-set-input-focus chosen-frame) instead of select-frame / raise-frame towards the end of the function.
(defface frame-number-face
'((t (:background "black" :foreground "red" )))
"Face for `frame-number-face`."
:group 'frame-fn)
(defface frame-name-face
'((t ( :background "black" :foreground "ForestGreen")))
"Face for `frame-name-face`."
:group 'frame-fn)
(defun select-frame-number ()
"Select a frame by number -- a maximum of 9 frames are supported."
(interactive)
(let* (
choice
chosen-frame
(n 0)
(frame-list (frame-list))
(total-frames (safe-length frame-list))
(frame-name-list
(mapcar
(lambda (frame) (cons frame (frame-parameter frame 'name)))
frame-list))
(frame-name-list-sorted
(sort
frame-name-list
#'(lambda (x y) (string< (cdr x) (cdr y)))))
(frame-number-list
(mapcar
(lambda (frame)
(setq n (1+ n))
(cons n (cdr frame)))
frame-name-list-sorted))
(pretty-list
(mapconcat 'identity
(mapcar
(lambda (x) (concat
"["
(propertize (format "%s" (car x)) 'face 'frame-number-face)
"] "
(propertize (format "%s" (cdr x)) 'face 'frame-name-face)))
frame-number-list)
" | ")) )
(message "%s" pretty-list)
(setq choice (read-char-exclusive))
(cond
((eq choice ?1)
(setq choice 1))
((eq choice ?2)
(setq choice 2))
((eq choice ?3)
(setq choice 3))
((eq choice ?4)
(setq choice 4))
((eq choice ?5)
(setq choice 5))
((eq choice ?6)
(setq choice 6))
((eq choice ?7)
(setq choice 7))
((eq choice ?8)
(setq choice 8))
((eq choice ?9)
(setq choice 9))
(t
(setq choice 10)))
(setq chosen-frame (car (nth (1- choice) frame-name-list-sorted)))
(when (> choice total-frames)
(let* (
(debug-on-quit nil)
(quit-message
(format "You must select a number between 1 and %s." total-frames)))
(signal 'quit `(,quit-message ))))
(select-frame chosen-frame)
(raise-frame chosen-frame)
chosen-frame))
Related
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))))))))
How can I cycle through only those buffers which are in a given major mode (such as Python-mode ) ?
Currently I am using C-X-Left/Right arrows, but these also show all sorts of irrelevant (i.e. non source code) buffers, any idea how can I restrict the buffer switching only to a specific type of buffer (with a given major mode) ?
I could not find something ready-made. However, it is not very hard to make the suitable commands.
(defun buffer-mode-alist ()
"Returns a list of (<buffer-name> . <major-mode>) pairs."
(let ((all-buffers (buffer-list))
(rv nil))
(while all-buffers
(let* ((this (car all-buffers))
(name (buffer-name this)))
(setq all-buffers (cdr all-buffers))
(when name
(setq rv (cons (cons name (with-current-buffer this major-mode)) rv)))))
rv))
(defun buffers-with-major-mode (the-major-mode)
(let ((buffer-alist (buffer-mode-alist))
(rv nil))
(while buffer-alist
(let ((this (car buffer-alist)))
(setq buffer-alist (cdr buffer-alist))
(if (eql (cdr this) the-major-mode)
(setq rv (cons (car this) rv)))))
(sort rv #'string<)))
(defun spin-buffers (buffer-list current)
(cond ((not (member current buffer-list)) buffer-list)
((string= current (car buffer-list)) buffer-list)
(t (spin-buffers (append (cdr buffer-list)
(list (car buffer-list)))
current))))
(defvar next-buffer-mode nil)
(defun choose-next-buffer-mode (mode)
"Ask for what major mode should be used as a selector for next-buffer-with-mode."
(interactive "aMajor Mode: ")
(setq next-buffer-mode mode))
(defun next-buffer-with-mode (set)
"Switches to the 'next' buffer with a given mode. If the mode is not set,
require it to be set, by calling choose-next-buffer-mode. If any prefix
argument is passed, also call choose-next-buffer-mode."
(interactive "P")
(when (or (not next-buffer-mode)
set)
(call-interactively 'choose-next-buffer-mode))
(let ((buffers (spin-buffers (buffers-with-major-mode next-buffer-mode)
(buffer-name))))
(when (cdr buffers)
(switch-to-buffer (cadr buffers)))))
(defun prev-buffer-with-mode (set)
"Switches to the 'previous' buffer with a given mode. If the mode is not set,
require it to be set, by calling choose-next-buffer-mode. If any prefix
argument is passed, also call choose-next-buffer-mode."
(interactive "P")
(when (or (not next-buffer-mode)
set)
(call-interactively 'choose-next-buffer-mode))
(let ((buffers (spin-buffers (buffers-with-major-mode next-buffer-mode)
(buffer-name))))
(when buffers
(switch-to-buffer (car (last buffers))))))
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)))
Does anyone have any ideas, please, regarding how to specify (within a function) switching to a specific tab group using Tabbar 2.0 and a current version of Emacs? For example, If the sky is blue, then switch to tab group "BLUE" (and/or the most recently viewed tab / buffer within that particular tab group).
I have written a few functions that permit me to organize tab groups by frames such that the tabs appear to be associated with a given frame. However, my function cycles through the various tab groups using tabbar-forward-group until the function finally stops at the correct group -- this method is very slow.
The function tabbar-current-tabset is used to determine the name of a current tab group that has focus. The result can be seen when placing it inside a message -- e.g., (message "%s" tabbar-current-tabset). It can also be used inside a function such as . . . (if (not (equal (format "%s" tabbar-current-tabset) "common")) . . . (tabbar-forward-group).
There is only one working function I have found that permits selecting a specific tab group, which is called ido-jump-to-tab-group (set forth below): https://github.com/bamanzi/dotemacs-full/blob/master/init.d/25-tabbar.el I am looking for a way to select a specific tab group (hard-coded into the function), without pausing to manually choose it using ido . . .. I mention this because it may help someone to resolve: If the sky is blue, then switch to tab group "BLUE" (and/or the most recently viewed tab / buffer within that particular tab group).
(defun ido-jump-to-tab-group ()
"Jump to a tabbar group."
(interactive)
(if (< emacs-major-version 24)
(ido-common-initialization))
(unless (and (featurep 'tabbar)
tabbar-mode)
(error "Error: tabbar-mode not turned on."))
(set tabbar-tabsets-tabset (tabbar-map-tabsets 'tabbar-selected-tab)) ;; refresh groups
(let* ( (groups (mapcar #'(lambda (group)
(format "%s" (cdr group)))
(tabbar-tabs tabbar-tabsets-tabset)))
(group-name (ido-completing-read "Groups: " groups)) )
(mapc #'(lambda (group)
(when (string= group-name (format "%s" (cdr group)))
(message "Switch to group '%s', current buffer: %s" (cdr group) (car group))
(switch-to-buffer (car group)) ))
(tabbar-tabs tabbar-tabsets-tabset))) )
During my Google searches, I came across an apparently broken function that does not work with Tabbar 2.0 and a current version of Emacs Trunk -- it is called tabbar+switch-group: https://gist.github.com/Johniel/4324127 I mention this function because it is the only one (other than ido-jump-to-tab-group) that is related to this issue.
(defun goto-tab-group (group-name)
"Jump to a specific tabbar group."
(unless (and (featurep 'tabbar)
tabbar-mode)
(error "Error: tabbar-mode not turned on."))
(set tabbar-tabsets-tabset (tabbar-map-tabsets 'tabbar-selected-tab)) ;; refresh groups
(let* ( (groups (mapcar #'(lambda (group)
(format "%s" (cdr group)))
(tabbar-tabs tabbar-tabsets-tabset))))
(mapc #'(lambda (group)
(when (string= group-name (format "%s" (cdr group)))
(message "Switch to group '%s', current buffer: %s" (cdr group) (car group))
(switch-to-buffer (car group)) ))
(tabbar-tabs tabbar-tabsets-tabset))) )
(defun example-using-goto-tab-group ()
(interactive)
(goto-tab-group "BLUE")) ;; predefined existing tab group
EDIT (September 27, 2014): The function ido-jump-to-tab-group (in the question above) and the function goto-tab-group (in the answer immediately above) are not compatible with a custom tabbar-buffer-groups-function that groups tabs based upon buffers associated with a particular frame, with that special list imbedded in the frame-parameter (independent of the general buffer-list and general buried-buffer-list). The following functions fix that imcompatibility.
(defun ido-switch-tab-group ()
"Switch tab groups using ido."
(interactive)
(let* (
(tab-buffer-list (mapcar
#'(lambda (b)
(with-current-buffer b
(list (current-buffer)
(buffer-name)
(funcall tabbar-buffer-groups-function) )))
(funcall tabbar-buffer-list-function)))
(groups (delete-dups
(mapcar #'(lambda (group)
(car (car (cdr (cdr group))))) tab-buffer-list)))
(group-name (ido-completing-read "Groups: " groups)) )
(catch 'done
(mapc
#'(lambda (group)
(when (equal group-name (car (car (cdr (cdr group)))))
(throw 'done (switch-to-buffer (car (cdr group))))))
tab-buffer-list) )))
(defun switch-tab-group (group-name)
"Switch to a specific tab group."
(let ((tab-buffer-list (mapcar
#'(lambda (b)
(with-current-buffer b
(list (current-buffer)
(buffer-name)
(funcall tabbar-buffer-groups-function) )))
(funcall tabbar-buffer-list-function))))
(catch 'done
(mapc
#'(lambda (group)
(when (equal group-name (format "%s" (car (car (cdr (cdr group))))))
(throw 'done (switch-to-buffer (car (cdr group))))))
tab-buffer-list) )))
(defun switch-to-tab-group-n ()
"Switch to a predefined existing tab group named `N`."
(interactive)
(switch-tab-group "N"))
(defun switch-to-tab-group-a ()
"Switch to a predefined existing tab group named `A`."
(interactive)
(switch-tab-group "A"))
When we use o in dired, it opens a file in "other window". But if there is more than one other window visible, then it appears to choose randomly. Is there a way to choose which window it should open that file in?
I was annoyed by that behaviour of dired too. I like the way ace-window lets you easily select windows with only one key stroke, so a wrote a function that would let me use that to open a file from dired in a window of my choice:
(require 'ace-window)
(defun find-file-ace-window ()
"Use ace window to select a window for opening a file from dired."
(interactive)
(let ((file (dired-get-file-for-visit)))
(if (> (length (aw-window-list)) 1)
(aw-select "" (lambda (window)
(aw-switch-to-window window)
(find-file file)))
(find-file-other-window file))))
To replace dired standard find-file-other-window command add
(define-key dired-mode-map "o" 'find-file-ace-window)
I doubt the behaviour is random, but you can change it by hooking into display-buffer and binding your own command.
Note that most of the code is to sort window list by area.
(defvar le::dired-chosen-window nil
"current chosen window to show buffers for `le::dired-choose-window-action'")
(defun le::window-list-for-completion ()
"Return alist of (BUFFER-NAME . WINDOW) sorted by size,
suitable for completion."
;; Schwartzian transform
(mapcar
(lambda (cell)
(let ((window (car cell)))
(cons (concat
(when (and (boundp 'window-numbering-mode)
window-numbering-mode)
(format "%s: "
(window-numbering-get-number-string window)))
(buffer-name (window-buffer window)))
window)))
(sort (loop with boost-alist = (if (eq major-mode 'dired-mode)
(list (cons (selected-window) -1000000))
nil)
for window in (window-list nil 0 (window-at 0 0))
for index from 0
collect (cons window (+
(* (window-total-width window)
(window-total-height window)
100)
index
(let ((boost (assq window boost-alist)))
(if boost
(cdr boost)
0)))))
(lambda (a b)
(> (cdr a) (cdr b))))))
(defun le::dired-choose-window (window)
"Choose window to display buffer in.
Reset selection with universal prefix (C-u)."
(interactive (let ((completions (le::window-list-for-completion)))
(list (unless current-prefix-arg
(cdr (assoc (completing-read "window holding buffer: " completions) completions))))))
(setq le::dired-chosen-window window))
(defun le::dired-choose-window-action (buffer alist)
"action to display buffer in `le::dired-chosen-window'"
(window--display-buffer buffer le::dired-chosen-window 'reuse))
(defun le::dired-find-file-specified-window ()
"Dired command to display buffer in chosen window"
(interactive)
(let ((display-buffer-overriding-action '((le::dired-choose-window-action))))
(dired-find-file-other-window)))
(define-key dired-mode-map [remap dired-find-file-other-window] 'le::dired-find-file-specified-window)
Evaluate buffer.
choose the window with le::dired-choose-window-action
press o from dired to open file in chosen window.