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

Build general dispatch function for Casual porcelains #26

Open
minad opened this issue Jul 10, 2024 · 8 comments
Open

Build general dispatch function for Casual porcelains #26

minad opened this issue Jul 10, 2024 · 8 comments
Assignees
Labels
enhancement New feature or request

Comments

@minad
Copy link

minad commented Jul 10, 2024

For the suite I'd like to propose adding a general casual-tmenu command which could be bound to a key like C-c c (C-c a, C-c t, C-c m, ...) to open the Casual transient menu corresponding to the currently active mode. Do you think this would make sense? I've seen you currently use C-o everywhere, binding it in the mode maps separately.

@kickingvegas
Copy link
Owner

kickingvegas commented Jul 10, 2024

@minad Thanks for the suggestion! To help clarify thinking here, I think there are two issues you raise.

  1. Should there be a global binding to Casual?
  2. At current, Casual Suite requires manual installation and configuration of each porcelain. Should this be streamlined?

With your proposal for casual-tmenu, it seems like I would have to answer yes to both of the above. With binding decisions often being contentious in Emacs (especially global ones), I’m reluctant to press for this.

I’m not sure it is desirable for a globally bound function (in this case the proposed casual-tmenu) to interrogate the current mode and select the appropriate Transient as it would have to cover modes that Casual does not support.

That said, I think streamlining installation and configuration would be a good thing. Here’s a quick and dirty example I’ve pulled together.

;; Example installer for Casual Suite.
(defun casual-suite-install (main)
  "Installer for Casual Suite with binding MAIN.
- MAIN binding specified for Casual main menu for specific mode."
  (keymap-set calc-mode-map main #'casual-calc-tmenu)
  (keymap-set dired-mode-map main #'casual-dired-tmenu)
  (keymap-set dired-mode-map "s" #'casual-dired-sort-by-tmenu)
  (keymap-set isearch-mode-map "<f2>" #'cc-isearch-menu-transient)
  (keymap-set ibuffer-mode-map main #'casual-ibuffer-tmenu)
  (keymap-set ibuffer-mode-map "F" #'casual-ibuffer-filter-tmenu)
  (keymap-set ibuffer-mode-map "s" #'casual-ibuffer-sortby-tmenu)
  (keymap-set Info-mode-map main #'casual-info-tmenu)
  (keymap-global-set "M-g" #'casual-avy-tmenu))

With such a function (casual-suite-install) in place, then the install procedure becomes trivial.

(require 'casual-suite)
(casual-suite-install "C-o")

The benefit of the above approach is that it requires no global-binding yet offers the same user experience. It is also optional, so that users who want finer grained control can continue to install each package individually.

I’d be interested in your thoughts on this and come up with a clear set of requirements before moving forward.

Thanks!

@kickingvegas kickingvegas self-assigned this Jul 10, 2024
@minad
Copy link
Author

minad commented Jul 10, 2024

Should there be a global binding to Casual?

Not necessarily. My proposal is to only add some kind of dispatching command which makes the whole suite a little easier to use. I only call casual-tmenu and get the appropriate menu. In any case, no binding should be installed automatically. It is up to the user where and how to install the binding.

At current, Casual Suite requires manual installation and configuration of each porcelain. Should this be streamlined?

No, I don't think the setup should be streamlined. I just thought it would be neat to have an abstract single entry point casual-tmenu. However in the end the overall setup would get easier as an effect, so maybe this is a partial yes to your question.

The benefit of the above approach is that it requires no global-binding yet offers the same user experience. It is also optional, so that users who want finer grained control can continue to install each package individually.

I don't really like the setup function approach for various reasons. Such setup functions don't interact nicely with lazy loading. Setup functions are less transparent and creates clutter across various maps. Also a user may not want to install all the bindings. In this sense a setup function takes control away from the user. My preference would be to have a single casual entry point which one could invoke everywhere. So my proposal is really that specific.

I am just mentioning this (but I also think it wouldn't be great) - a better, cleaner alternative than a setup function would be a global minor mode which can be used to globally activate/deactivate the entry points. However I also dislike global minor modes which do nothing else than adding bindings. In summary, I consider both setup functions and keybinding-only minor modes malpractices.

So I hope you are not going to add a setup function or a minor mode as the result of my proposal... ;)

I’m not sure it is desirable for a globally bound function (in this case the proposed casual-tmenu) to interrogate the current mode and select the appropriate Transient as it would have to cover modes that Casual does not support.

Why do you feel like that? The command would be quite simple. It could look up the appropriate command in a mode/command alist. However if you don't like this idea, let's just close this and do nothing. :)

@kickingvegas
Copy link
Owner

kickingvegas commented Jul 10, 2024

@minad Thanks for your clarifying thoughts, particularly around setup functions and minor modes.

So I suppose you’re looking for something like this behavior?

(defun casual-tmenu ()
  "Dispatcher for the Casual main menu of a supported mode."
  (let ((current-mode major-mode))
    (cond
     ((equal current-mode 'calc-mode) (call-interactively #'casual-calc-tmenu))
     ((equal current-mode 'dired-mode) (call-interactively #'casual-dired-tmenu))
     ((equal current-mode 'Info-mode) (call-interactively #'casual-info-tmenu))
     ((equal current-mode 'ibuffer-mode) (call-interactively #'casual-ibuffer-tmenu))
     (t (message "Casual does not support this mode.")))))

Sidestepping an implementation using an alist and other implementation details like how the Avy and I-Search menus really aren’t mode specific, if this is what you’re looking for then I’d be open to putting this in.

@minad
Copy link
Author

minad commented Jul 10, 2024

Yes, like this - a simple Casual DWIM comand. I'd prefer an alist for config, but this is really just an implementation detail. As a special case, Isearch could also be handled by checking if isearch-mode is active. In this case the Isearch Casual should be preferred over the other modes I guess?

I am unsure about casual-avy. While I have Avy installed, I barely use it. Also I haven't tried casual-avy yet. My problem with Avy is mainly that I have to think too much when using it. At the same time, Avy is supposed to speed up things, so I doubt that a Transient will help with that. But maybe it could help with learning.

@kickingvegas
Copy link
Owner

@minad Give casual-avy a try! In this case I’ve globally bound it to M-g and have made it mirror a number of the default global map bindings for M-g. Before building this menu, I too rarely used Avy. Now it's embedded in my usage of Emacs.

@kickingvegas kickingvegas changed the title General entry key Build general dispatch function for Casual porcelains Jul 10, 2024
@kickingvegas kickingvegas added the enhancement New feature or request label Jul 10, 2024
@kickingvegas
Copy link
Owner

@minad per discussion #28, concerned that any implementation here would violate lazy-loading which would break use-package. Would appreciate your thoughts here.

@minad
Copy link
Author

minad commented Aug 2, 2024

No, the implementation you've given in #26 wouldn't violate lazy loading. I only proposed this, given the possibility of lazy loading. I am generally averse to patterns which do not work lazily and I also avoid such patterns in my packages.

But anyway, it is okay to not implement this, if it doesn't fit into your overall design. Thanks for consideration.

@kickingvegas kickingvegas transferred this issue from kickingvegas/casual-suite Oct 22, 2024
@mavit
Copy link

mavit commented Dec 5, 2024

     ((equal current-mode 'calc-mode) (call-interactively #'casual-calc-tmenu))
     ((equal current-mode 'dired-mode) (call-interactively #'casual-dired-tmenu))
     ((equal current-mode 'Info-mode) (call-interactively #'casual-info-tmenu))
     ((equal current-mode 'ibuffer-mode) (call-interactively #'casual-ibuffer-tmenu))

In general, better to use derived-mode-p, here, perhaps?

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

When branches are created from issues, their pull requests are automatically linked.

3 participants