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