Permalink
Browse files

Merge pull request #1871 from Ambrevar/master

Add helm-switch-to-buffers-function and perform alternate splits
  • Loading branch information...
2 parents 2385b81 + eaf6a52 commit a66849bfc008bc0082b0a97caa3ac75652f0a8ad @thierryvolpiatto thierryvolpiatto committed Oct 2, 2017
Showing with 143 additions and 90 deletions.
  1. +14 −1 helm-buffers.el
  2. +8 −11 helm-files.el
  3. +1 −1 helm-grep.el
  4. +1 −1 helm-regexp.el
  5. +2 −2 helm-types.el
  6. +117 −74 helm-utils.el
View
@@ -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 ()
@@ -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)
View
@@ -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 "$")
@@ -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
@@ -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'."
@@ -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: "
@@ -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))
@@ -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)))
View
@@ -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))
View
@@ -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)
View
@@ -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"
View
@@ -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) ;; «
@@ -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) ;; »
@@ -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
@@ -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.

0 comments on commit a66849b

Please sign in to comment.