Kungsgeten/ryo-modal

[Feature request] Better way to map operators and textobjects

sriramkswamy opened this issue · 4 comments

Given that the idea of using ryo-modal in a way similar to vim is suggested in the README, I had defined tons of keymaps that way. However, I had some free time recently and have hacked together a simple macro that provides a similar functionality by creating a function.

  1. The (long, messy, and uncommented) macro is shown here. I made the macro to create functions as they are versatile to be just called or added to hooks for specific modes.
  2. The usage is shown here.

Let me know if this is something you would be interested to include, and suggest changes if you can. I will clean the code and submit a pull request if that's the case. Of course, this requires many third-party packages as of now but it can be avoided and a much simpler macro can be included.

It could definitely be a good idea to include a text macro like this, or at least to suggest how to do it in the README. Here is how I'm currently doing it in my setup:

  (let ((text-objects
         '(("." er/mark-symbol :name "Symbol")
           (":" er/mark-symbol-with-prefix :name "Symbol+Prefix")
           ("B" mark-whole-buffer :name "All buffer")
           ("E" org-mark-element :name "Org Element")
           ("b" er/mark-python-block :name "Block")
           ("d" er/mark-defun :name "Defun")
           ("f" avy-goto-word-1 :then (er/mark-symbol) :name "◎ Symbol")
           ("i" mark-inner :name "Inner")
           ("l" mark-line :name "Line")
           ("m" er/mark-method-call :name "Method call")
           ("n" er/mark-next-accessor :name "Next accessor")
           ("o" mark-outer :name "Outer")
           ("p" er/mark-paragraph :name "Paragraph")
           ("r" avy-mark-region :name "◎ Region")
           ("s" er/mark-sentence :name "Sentence")
           ("t" org-mark-subtree :name "Org Subtree")
           ("u" er/mark-url :name "URL")
           ("w" er/mark-word :name "Word")
           ("ö" er/mark-comment :name "Comment"))))
    (eval `(ryo-modal-keys
            ("c" ,text-objects :then '(kill-region) :exit t)
            ("d" ,text-objects :then '(kill-region))
            ("y" ,text-objects :then '(copy-region-as-kill))
            ("v" ,text-objects)
            ("q" ,text-objects :then '(quickrun-region))
            ("Q" ,text-objects :then '(quickrun-replace-region))
            ("i" ,text-objects :then '(vimish-fold))
            ("ö" ,text-objects :then '(comment-dwim)))))

So I have some "text objects", which each are a function that selects a region. The "action list" then loop through the text objects, and does something after the text has been selected. So if I press c l it will first mark the current line (l for line) and then run kill-region and then exit ryo.

This one is much better. I'll rewrite my macros taking some ideas from you and submit one around next week when I have some time.

@sriramkswamy Did you ever write a macro for this? I've added an example to the README, so I'm marking this as closed for the moment.

Yeah, I did. It's slightly different from the example. I define some auxiliary functions for marking and some wrappers around expand region first. Then, I define a variable in the global namespace for text objects. I use it for global operators and major mode specific operators with repetitive operators defined separately. For completely new major modes, I define a function that calls the macro for major mode specific bindings and add it as a hook to the major mode. You can probably just eval it in the config section of use-package too. I think the example in the README is a neat quick example. If you find the need, you can link my config or I can submit a pull request with a few examples illustrating the different use cases.