Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

helm-split-window-preferred-function and helm-display-function #1902

Closed
Ambrevar opened this issue Oct 19, 2017 · 1 comment
Closed

helm-split-window-preferred-function and helm-display-function #1902

Ambrevar opened this issue Oct 19, 2017 · 1 comment

Comments

@Ambrevar
Copy link
Member

I have been tinkering around helm-split-window-preferred-function. Which is a fantastic customization possibility! But things went wrong...

After some debugging, it turns out that helm-split-window-preferred-function gets called twice in helm-default-display-buffer if

  • helm-full-frame is nil
  • helm-split-window-default-side is not 'same or one-window-p is nil.

Which happens with common configurations including the default one.

This is because helm-default-display-buffer calls both helm-split-window-preferred-function and display-buffer, the latter calling split-window-preferred-function which was locally bound to helm-split-window-preferred-function in the caller.

Calling the function twice is a major issue because the result of the second call will depend on the result of the first call, which makes it extremely convoluted to design any splitting rules. That the default function works is mostly a lucky shot I believe.

To make my helm-split-window-preferred-function work I had to replace helm-display-function:

(defun helm-custom-display-buffer (buffer)
  "Custom function to display `helm-buffer' BUFFER."
  (display-buffer
   buffer `(nil . ((window-height . ,helm-display-buffer-default-height)
                   (window-width  . ,helm-display-buffer-default-width))))
  (helm-log-run-hook 'helm-window-configuration-hook))

(setq helm-display-function 'helm-custom-display-buffer)

This does not seem very productive and I think this calls for some improvements:

  1. Let's fix the documentation. helm-split-window-preferred-function should link to the documentation of helm-default-display. helm-display-buffer and helm-default-display-buffer too, and it should say it uses it.
    All functions should explain how they relate to each other. Some configuration variables remain buried deep within the code. It took me a while to realize helm-full-frame existed!

  2. helm-display-buffer and helm-default-display-buffer should be revised to not call helm-split-window-preferred-function twice.

  3. More generally, what about having only one callback, that is, either helm-display-function or helm-split-window-preferred-function? And leave all configuration variables to this callback instead of being scattered around 3 functions (more?). Namely those variables:

helm-full-frame
helm-split-window-default-side
helm-always-two-windows
helm-reuse-last-window-split-state
helm-split-window-in-side-p ; Also fix this typo: it's "inside", not "in-side"

;; Merge those callbacks into one:
helm-split-window-preferred-function
helm-display-function
thierryvolpiatto added a commit that referenced this issue Oct 20, 2017
This revert 2ea4457 which seems no more needed as the persistent
action buffer is always displayed in other-window.

Reverting this avoid calling helm-split-window-preferred-function
twice as specified in issue #1902.

* helm.el (helm-default-display-buffer): Do it.
If needed the test can be reenabled by not calling
helm-split-window-preferred-function but only a subset of it:

    (and (not helm-split-window-in-side-p)
         (memq helm-split-window-default-side
               '(right left above below))
         (eq (or (helm-window-in-direction
                  helm-split-window-default-side)
                 (selected-window))
             (get-buffer-window helm-current-buffer)))
thierryvolpiatto added a commit that referenced this issue Oct 20, 2017
* helm.el (helm-display-function): Do it.
(helm-split-window-default-fn):    Do it.
(helm-display-buffer):             Do it.
thierryvolpiatto added a commit that referenced this issue Oct 20, 2017
to helm-split-window-inside-p.

* helm-elisp.el (with-helm-show-completion):           Use new name.
* helm-utils.el (with-helm-display-marked-candidates): Use new name.
* helm.el (helm-split-window-default-side):            Use new name.
(helm-split-window-inside-p): Renamed from helm-split-window-in-side-p.
(helm-split-window-in-side-p): Now a var alias and make it obsolete.
@Ambrevar
Copy link
Member Author

Thanks for the update, that seems to do it.

I wrote the following split function:

(defun helm-split-window-combined-fn (window)
  "Helm window splitting that combined most standard features.

- With C-u, split inside. With C-u C-u, use same window.
- Else use biggest other window when available.
- Else split horizontally if width>height, vertically otherwise."
  (cond
   ((or (minibufferp helm-current-buffer)
        (and
         (not (one-window-p t))
         (not (equal current-prefix-arg '(4)))
         (not (equal current-prefix-arg '(16)))))
    ;; Find biggest window.
    (let (biggest (maxarea 0))
      (dolist (w (window-list))
        (unless (eq w (selected-window))
          (let ((area (* (window-pixel-width w) (window-pixel-height w))))
            (when (> area maxarea)
              (setq maxarea area
                    biggest w)))))
      biggest))
   ((equal current-prefix-arg '(16))
    ;; Same window.
    (selected-window))
   (t
    ;; If split inside or if unique window.
    (split-window (selected-window) nil
                  (if (> (window-pixel-width) (window-pixel-height))
                      'right
                    'below)))))

What I found frustrating with the default function is that you could not change the behaviour "live", i.e. choose between "other window", "inside", or "same".

So what do think about my last point, merging the display and the split functions? I'm not sure of the semantic difference between the two when it comes to Emacs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants