Tabbar 2.0 -- custom function switching to a specific tab group - emacs

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"))

Related

How emacs js2-mode jump to definition open in other window?

In js2-mode, M-. runs the command js2-jump-to-definition, this works great. But I want it go to the definition in other window. I find the code js2-jump-to-definition in Github.
What is the easiest way to make it open in other window?
(defun js2-jump-to-definition (&optional arg)
"Jump to the definition of an object's property, variable or function."
(interactive "P")
(if (eval-when-compile (fboundp 'xref-push-marker-stack))
(xref-push-marker-stack)
(ring-insert find-tag-marker-ring (point-marker)))
(js2-reparse)
(let* ((node (js2-node-at-point))
(parent (js2-node-parent node))
(names (if (js2-prop-get-node-p parent)
(reverse (let ((temp (js2-compute-nested-prop-get parent)))
(cl-loop for n in temp
with result = '()
do (push n result)
until (equal node n)
finally return result)))))
node-init)
(unless (and (js2-name-node-p node)
(not (js2-var-init-node-p parent))
(not (js2-function-node-p parent)))
(error "Node is not a supported jump node"))
(push (or (and names (pop names))
(unless (and (js2-object-prop-node-p parent)
(eq node (js2-object-prop-node-left parent)))
node)) names)
(setq node-init (js2-search-scope node names))
;; todo: display list of results in buffer
;; todo: group found references by buffer
(unless node-init
(switch-to-buffer
(catch 'found
(unless arg
(mapc (lambda (b)
(with-current-buffer b
(when (derived-mode-p 'js2-mode)
(setq node-init (js2-search-scope js2-mode-ast names))
(if node-init
(throw 'found b)))))
(buffer-list)))
nil)))
(setq node-init (if (listp node-init) (car node-init) node-init))
(unless node-init
(pop-tag-mark)
(error "No jump location found"))
(goto-char (js2-node-abs-pos node-init))))

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))))))))

How can I cycle through only those buffers which are in a given major mode (such as Python-mode ) ?

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))))))

How to limit the number of "suggestions" that flyspell gives?

In emacs flyspell mode, sometimes the list of suggestions is really long, so that the pop-up menu is taller than the screen and requires vertical scrolling of the menu because the "Save word" option is at the bottom of the menu.
Is there a way to to do one of the following:
Move "Save word" to the top of the menu?
Put a hard limit on the number of suggestions displayed?
Modify the threshold of a matching word?
This code will limit all ispell solutions to a maximum of limit-ispell-choices-to, which gets the desired limit in flyspell.
(defvar limit-ispell-choices-to 5
"Number indicating the maximum number of choices to present")
(defadvice ispell-parse-output (after limit-ispell-choices activate)
(when (and (listp ad-return-value)
ad-return-value)
(let* ((miss-list-end (nthcdr (- limit-ispell-choices-to 1)
(nth 2 ad-return-value)))
(guess-list-end (nthcdr (- limit-ispell-choices-to 1)
(nth 3 ad-return-value))))
(when miss-list-end (setcdr miss-list-end nil))
(when guess-list-end (setcdr guess-list-end nil)))))
This will put "Save word" at the top. I just swapped two words in the source.
It's a bit of a hack, but I can't see a better way.
(defun flyspell-emacs-popup (event poss word)
"The Emacs popup menu."
(unless window-system
(error "This command requires pop-up dialogs"))
(if (not event)
(let* ((mouse-pos (mouse-position))
(mouse-pos (if (nth 1 mouse-pos)
mouse-pos
(set-mouse-position (car mouse-pos)
(/ (frame-width) 2) 2)
(mouse-position))))
(setq event (list (list (car (cdr mouse-pos))
(1+ (cdr (cdr mouse-pos))))
(car mouse-pos)))))
(let* ((corrects (if flyspell-sort-corrections
(sort (car (cdr (cdr poss))) 'string<)
(car (cdr (cdr poss)))))
(cor-menu (if (consp corrects)
(mapcar (lambda (correct)
(list correct correct))
corrects)
'()))
(affix (car (cdr (cdr (cdr poss)))))
show-affix-info
(base-menu (let ((save (if (and (consp affix) show-affix-info)
(list
(list (concat "Save affix: " (car affix))
'save)
'("Accept (session)" session)
'("Accept (buffer)" buffer))
'(("Save word" save)
("Accept (session)" session)
("Accept (buffer)" buffer)))))
(if (consp cor-menu)
(append save (cons "" cor-menu))
save)))
(menu (cons "flyspell correction menu" base-menu)))
(car (x-popup-menu event
(list (format "%s [%s]" word (or ispell-local-dictionary
ispell-dictionary))
menu)))))

Switch between frames by number or letter

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))