Skip to content

Commit

Permalink
Merge pull request #1871 from Ambrevar/master
Browse files Browse the repository at this point in the history
Add helm-switch-to-buffers-function and perform alternate splits
  • Loading branch information
Thierry Volpiatto committed Oct 2, 2017
2 parents 2385b81 + eaf6a52 commit a66849b
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 90 deletions.
15 changes: 14 additions & 1 deletion helm-buffers.el
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ If REGEXP-FLAG is given use `query-replace-regexp'."
"Run switch to other window action from `helm-source-buffers-list'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-display-buffers-other-windows)))
(helm-exit-and-execute-action 'helm-buffer-switch-buffers-other-window)))
(put 'helm-buffer-switch-other-window 'helm-only t)

(defun helm-buffer-switch-other-frame ()
Expand All @@ -750,6 +750,19 @@ If REGEXP-FLAG is given use `query-replace-regexp'."
(helm-exit-and-execute-action 'switch-to-buffer-other-frame)))
(put 'helm-buffer-switch-other-frame 'helm-only t)

(defun helm-buffer-switch-buffers (_candidate)
"Switch to buffer candidates and replace current buffer.
If more than one buffer marked switch to these buffers in separate windows.
If a prefix arg is given split windows vertically."
(let ((buffers (helm-marked-candidates)))
(helm-window-show-buffers buffers)))

(defun helm-buffer-switch-buffers-other-window (_candidate)
"Switch to buffer candidates in other windows."
(let ((buffers (helm-marked-candidates)))
(helm-window-show-buffers buffers t)))

(defun helm-buffer-run-ediff ()
"Run ediff action from `helm-source-buffers-list'."
(interactive)
Expand Down
19 changes: 8 additions & 11 deletions helm-files.el
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

(defcustom helm-boring-file-regexp-list
(mapcar (lambda (f)
(let ((rgx (regexp-quote f)))
(let ((rgx (regexp-quote f)))
(if (string-match-p "[^/]$" f)
;; files: e.g .o => \\.o$
(concat rgx "$")
Expand Down Expand Up @@ -694,7 +694,7 @@ ACTION must be an action supported by `helm-dired-action'."
(if (and (and (fboundp 'dired-async-mode)
dired-async-mode)
(null prefarg))
(concat "Async " (symbol-name action))
(concat "Async " (symbol-name action))
(capitalize (symbol-name action)))
(length ifiles)))
helm-ff--move-to-first-real-candidate
Expand Down Expand Up @@ -750,12 +750,9 @@ This reproduce the behavior of \"cp --backup=numbered from to\"."
"Keep current-buffer and open files in separate windows.
When a prefix arg is detected files are opened in a vertical windows
layout."
(let* ((files (helm-marked-candidates))
(initial-ow-fn (if (cdr (window-list))
#'switch-to-buffer-other-window
#'helm-switch-to-buffer-other-window)))
(funcall initial-ow-fn (find-file-noselect (car files)))
(helm-simultaneous-find-file files t)))
(let* ((files (helm-marked-candidates))
(buffers (mapcar 'find-file-noselect files)))
(helm-window-show-buffers buffers t)))

(defun helm-find-files-byte-compile (_candidate)
"Byte compile elisp files from `helm-find-files'."
Expand All @@ -772,7 +769,7 @@ layout."

(defun helm-find-files-ediff-files-1 (candidate &optional merge)
"Generic function to ediff/merge files in `helm-find-files'."
(let* ((helm-dwim-target 'next-window)
(let* ((helm-dwim-target 'next-window)
(bname (helm-basename candidate))
(marked (helm-marked-candidates :with-wildcard t))
(prompt (if merge "Ediff Merge `%s' With File: "
Expand Down Expand Up @@ -2012,7 +2009,7 @@ Return nil on valid file name remote or not."
(let* ((str (helm-basename fname))
(split (split-string str ":" t))
(meth (car (member (car split)
(helm-ff--get-tramp-methods)))))
(helm-ff--get-tramp-methods)))))
(when meth (car (last split)))))

(cl-defun helm-ff--tramp-hostnames (&optional (pattern helm-pattern))
Expand Down Expand Up @@ -3347,7 +3344,7 @@ Called with a prefix arg open files in background without selecting them."
(if (cdr marked)
;; If helm-current-prefix-arg is detected split is done
;; vertically.
(helm-simultaneous-find-file marked)
(helm-window-show-buffers (mapcar 'find-file-noselect marked))
(let ((dir (and (not url-p) (helm-basedir candidate))))
(cond ((and dir (file-directory-p dir))
(find-file (substitute-in-file-name candidate)))
Expand Down
2 changes: 1 addition & 1 deletion helm-grep.el
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ WHERE can be one of other-window, other-frame."
(fname (if tramp-host
(concat tramp-prefix loc-fname) loc-fname)))
(cl-case where
(other-window (helm-switch-to-buffer-other-window
(other-window (helm-window-other-window
(find-file-noselect fname)))
(other-frame (find-file-other-frame fname))
(grep (helm-grep-save-results-1))
Expand Down
2 changes: 1 addition & 1 deletion helm-regexp.el
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame."
(split-pat (helm-mm-split-pattern helm-input)))
(cl-case method
(buffer (switch-to-buffer buf))
(buffer-other-window (helm-display-buffers-other-windows buf))
(buffer-other-window (helm-buffer-switch-buffers-other-window buf))
(buffer-other-frame (switch-to-buffer-other-frame buf)))
(with-current-buffer buf
(helm-goto-line lineno)
Expand Down
4 changes: 2 additions & 2 deletions helm-types.el
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@

(defcustom helm-type-buffer-actions
(helm-make-actions
"Switch to buffer(s)" 'helm-switch-to-buffers
"Switch to buffer(s)" 'helm-buffer-switch-buffers
(lambda () (and (locate-library "popwin")
"Switch to buffer in popup window"))
'popwin:popup-buffer
"Switch to buffer(s) other window `C-c o'"
'helm-display-buffers-other-windows
'helm-buffer-switch-buffers-other-window
"Switch to buffer other frame `C-c C-o'"
'switch-to-buffer-other-frame
"Browse project from buffer"
Expand Down
191 changes: 117 additions & 74 deletions helm-utils.el
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ In this case last position is added to the register
("&yen" . 165) ;; ¥
("¦" . 166) ;; ¦
("§" . 167) ;; §
("¨" . 32) ;; SPC
("¨" . 32) ;; SPC
("©" . 169) ;; ©
("ª" . 97) ;; a
("«" . 171) ;; «
Expand All @@ -121,7 +121,7 @@ In this case last position is added to the register
("µ" . 956) ;; μ
("¶" . 182) ;; ¶
("·" . 183) ;; ·
("¸" . 32) ;; SPC
("¸" . 32) ;; SPC
("¹" . 49) ;; 1
("º" . 111) ;; o
("»" . 187) ;; »
Expand Down Expand Up @@ -217,12 +217,12 @@ In this case last position is added to the register
;;; Utils functions
;;
;;
(defcustom helm-switch-to-buffer-ow-vertically nil
(defcustom helm-window-prefer-horizontal-split nil
"Maybe switch to other window vertically when non nil.
Possible values are `t', `nil' and `decide'.
Possible values are t, nil and `decide'.
When `t' switch vertically.
When t switch vertically.
When nil switch horizontally.
When `decide' try to guess if it is possible to switch vertically
according to the setting of `split-width-threshold' and the size of
Expand All @@ -236,89 +236,132 @@ behavior is the same that with a nil value."
(const :tag "Split window horizontally" nil)
(symbol :tag "Guess how to split window" 'decide)))

(defun helm-switch-to-buffers (buffer-or-name &optional other-window)
"Switch to buffer BUFFER-OR-NAME.
(defcustom helm-window-show-buffers-function #'helm-window-default-split-fn
"The default function to use when opening several buffers at once.
It is typically used to rearrange windows."
:group 'helm-utils
:type '(choice
(function
(const :tag "Split windows vertically or horizontally"
#'helm-window-default-split-fn)
(const :tag "Split in alternate windows"
#'helm-window-alternate-split-fn)
(const :tag "Split windows in mosaic"
#'helm-window-mosaic-fn))))

(defun helm-window-show-buffers (buffers &optional other-window)
"Show BUFFERS.
If more than one buffer marked switch to these buffers in separate windows.
If OTHER-WINDOW is specified keep current-buffer and switch to others buffers
If OTHER-WINDOW is non-nil, keep current buffer and switch to others buffers
in separate windows.
If a prefix arg is given split windows vertically."
(let ((mkds (helm-marked-candidates))
(initial-ow-fn (if (cdr (window-list))
(let ((initial-ow-fn (if (cdr (window-list))
#'switch-to-buffer-other-window
#'helm-switch-to-buffer-other-window)))
(helm-aif (cdr mkds)
(progn
(if other-window
(funcall initial-ow-fn (car mkds))
(switch-to-buffer (car mkds)))
(save-selected-window
(cl-loop with nosplit
for b in it
when nosplit return
(message "Too many buffers to visit simultaneously")
do (condition-case _err
(helm-switch-to-buffer-other-window b 'balance)
(error (setq nosplit t) nil)))))
#'helm-window-other-window)))
(if (cdr buffers)
(funcall helm-window-show-buffers-function buffers
(and other-window initial-ow-fn))
(if other-window
(funcall initial-ow-fn buffer-or-name)
(switch-to-buffer buffer-or-name)))))

(defun helm-simultaneous-find-file (files &optional other-window)
"Find files in FILES list in separate windows.
If frame is too small to display all windows, continue finding files
in background.
When called with a prefix arg split is done vertically."
(helm-aif (cdr files)
(progn
(unless other-window
(switch-to-buffer (find-file-noselect (car files))))
(save-selected-window
(cl-loop with nosplit
with len = (length it)
with remaining = 0
with displayed = 0
for f in it
for count from 1
for buf = (find-file-noselect f)
unless nosplit do
(condition-case-unless-debug _err
(helm-switch-to-buffer-other-window buf 'balance)
(error
(setq nosplit t)
(message
"%d files displayed, %d files opening in background..."
(setq displayed count)
(setq remaining (- len count)))
nil))
finally
(when nosplit
(message
"%d files displayed, %d files opened in background"
displayed remaining)))))))

(defun helm-switch-to-buffer-other-window (buffer-or-name &optional balance)
"Switch to buffer-or-name in other window.
(funcall initial-ow-fn (car buffers))
(switch-to-buffer (car buffers))))))

(defun helm-window-default-split-fn (candidates &optional other-window-fn)
"Split windows in one direction and balance them.
Direction can be controlled via `helm-window-prefer-horizontal-split'.
If a prefix arg is given split windows vertically.
This function is suitable for `helm-window-show-buffers-function'."
(if other-window-fn
(funcall other-window-fn (car candidates))
(switch-to-buffer (car candidates)))
(save-selected-window
(cl-loop with nosplit
for b in (cdr candidates)
when nosplit return
(message "Too many buffers to visit simultaneously")
do (condition-case _err
(helm-window-other-window b 'balance)
(error (setq nosplit t) nil)))))

(defun helm-window-alternate-split-fn (candidates &optional other-window-fn)
"Alternatively split last window left and right.
This function is suitable for `helm-window-show-buffers-function'."
(if other-window-fn
(funcall other-window-fn (car candidates))
(switch-to-buffer (car candidates)))
(let (right-split)
(save-selected-window
(cl-loop with nosplit
for b in (cdr candidates)
when nosplit return
(message "Too many buffers to visit simultaneously")
do (condition-case _err
(progn
(select-window (split-window (get-buffer-window) nil right-split))
(setq right-split (not right-split))
(switch-to-buffer b))
(error (setq nosplit t) nil))))))

(defun helm-window-mosaic-fn (candidates &optional other-window-fn)
"Make an as-square-as-possible window mosaic of the CANDIDATES buffers.
The outer splits are done in the direction given by
`helm-window-prefer-horizontal-split'.
If OTHER-WINDOW-FN is non-nil, current windows are included in the mosaic.
This function is suitable for `helm-window-show-buffers-function'."
(when other-window-fn
(setq candidates (append (mapcar 'window-buffer (window-list)) candidates)))
(delete-other-windows)
(let* ((mosaic-side-tile-count (ceiling (sqrt (length candidates))))
;; We lower-bound the tile size, otherwise the function would fail during the first inner split.
;; There is consequently no need to check for errors when splitting.
(mosaic-tile-width (max (/ (frame-width) mosaic-side-tile-count) window-min-width))
(mosaic-tile-height (max (/ (frame-height) mosaic-side-tile-count) window-min-height))
(helm-window-prefer-horizontal-split
(if (eq helm-window-prefer-horizontal-split 'decide)
(and (numberp split-width-threshold)
(>= (window-width (selected-window))
split-width-threshold))
helm-window-prefer-horizontal-split))
(mosaic-outer-split-size (if helm-window-prefer-horizontal-split mosaic-tile-width mosaic-tile-height))
(mosaic-inner-split-size (if helm-window-prefer-horizontal-split mosaic-tile-height mosaic-tile-width))
next-window)
(let ((max-tiles (* (/ (frame-width) mosaic-tile-width) (/ (frame-height) mosaic-tile-height))))
(when (> (length candidates) max-tiles)
(message "Too many buffers to visit simultaneously")
;; Shorten `candidates' to `max-tiles' elements.
(setcdr (nthcdr (- max-tiles 1) candidates) nil)))
(while candidates
(when (> (length candidates) mosaic-side-tile-count)
(setq next-window (split-window (get-buffer-window) mosaic-outer-split-size helm-window-prefer-horizontal-split)))
(switch-to-buffer (car candidates))
(setq candidates (cdr candidates))
(dotimes (_ (min (- mosaic-side-tile-count 1) (length candidates)))
(select-window (split-window (get-buffer-window) mosaic-inner-split-size (not helm-window-prefer-horizontal-split)))
(switch-to-buffer (car candidates))
(setq candidates (cdr candidates)))
(when next-window
(select-window next-window)))))

(defun helm-window-other-window (buffer-or-name &optional balance)
"Switch to BUFFER-OR-NAME in other window.
If a prefix arg is detected split vertically.
When argument balance is provided `balance-windows'."
(let* ((helm-switch-to-buffer-ow-vertically
(if (eq helm-switch-to-buffer-ow-vertically 'decide)
When argument BALANCE is provided `balance-windows'."
(let* ((helm-window-prefer-horizontal-split
(if (eq helm-window-prefer-horizontal-split 'decide)
(and (numberp split-width-threshold)
(>= (window-width (selected-window))
split-width-threshold))
helm-switch-to-buffer-ow-vertically))
(right-side (if helm-switch-to-buffer-ow-vertically
(not helm-current-prefix-arg)
helm-current-prefix-arg)))
helm-window-prefer-horizontal-split))
(right-side (if helm-window-prefer-horizontal-split
(not helm-current-prefix-arg)
helm-current-prefix-arg)))
(select-window (split-window nil nil right-side))
(and balance (balance-windows))
(switch-to-buffer buffer-or-name)))

(defun helm-display-buffers-other-windows (buffer-or-name)
"switch to buffer BUFFER-OR-NAME in other window.
See `helm-switch-to-buffers' for switching to marked buffers."
(helm-switch-to-buffers buffer-or-name t))

(cl-defun helm-current-buffer-narrowed-p (&optional
(buffer helm-current-buffer))
"Check if BUFFER is narrowed.
Expand Down

0 comments on commit a66849b

Please sign in to comment.