emacs-eaf / eaf-browser

A modern, customizable and extensible browser in Emacs
GNU General Public License v3.0
129 stars 26 forks source link

Insert_or_Continue_Binding #31

Closed WammKD closed 2 years ago

WammKD commented 2 years ago

Is your feature request related to a problem? Please describe. Way back, I used Uzbl and got used to following links with f l; I was able to make this work with the EAF browser by, naïvely, doing (eaf-bind-key nil "f" eaf-browser-keybinding). Of course, this also ruined being able to use f, on its own.

Describe the solution you'd like I don't know if it already exists but, if there were a eaf-py-proxy-insert_or_continue_binding function, I could assign f to that and, when typing in a textbox, f would get inserted and, when not, it would look to the next key typed to determine if there's something to execute (or if the multi-key binding doesn't, in fact, exist).

Describe alternatives you've considered N/A

Additional context N/A

manateelazycat commented 2 years ago

What is the use of this feature? Can you describe the use scenario?

WammKD commented 2 years ago

Sure; it's primarily aimed at being able to still be able to type in areas that allow typing text on any webpage.

At the moment, there isn't (assuming I understand things correctly) any eaf-py-proxy-insert_or_ function which allows me to not do anything with the key other than run something else with the next typed key; so I can't do a binding such as f l since any of the current eaf-py-proxy-insert_or_ functions result in executing something rather than looking to the next key to decide whether or not to do anything.

Not doing (eaf-bind-key nil "f" eaf-browser-keybinding) and leaving things as is results in EAF throwing an error that f is already bound to something (so f l can't be accepted as a valid binding); but, like I mentioned, doing (eaf-bind-key nil "f" eaf-browser-keybinding) also means that f stops working when trying to type in any text area of a webpage: f l works but I can't use f when filling out a form.

Does that make sense?

manateelazycat commented 2 years ago

Sorry, I still don't understand why now design can't work, do you need a switch to control EAF browser to switch between insert mode and command mode?

WammKD commented 2 years ago

It may be that I don't understand how the browser currently functions; are there both an insert and command mode? I was under the assumption that eaf-py-proxy-insert_or_ functions checked whether it made sense to insert (like if the cursor was in a textbox) and, if not, then did the part after the _or_ in the function name. I assumed there wasn't an insert mode, like in browsers like Uzbl and Qutebrowser, because I hadn't seen any visual indication of modes while using EAF browser and clicking on a text area, doing C-g a few times, and then typing something like k just put a "k" in the text area rather than scrolling down, like I'd expect from eaf-py-proxy-insert_or_scroll_down.

If my understanding of this is correct, I need to reassign f in order for my f l binding to work but can't reassign f to nil, like I initially tried to do, as that removes any kind of action for typing "f", on its own (which means I can't type something like "p u f f" in a textbox on the page because the only f-related binding that exists is f l).

WammKD commented 2 years ago

If what I'm saying still doesn't make sense, just run

(eaf-bind-key nil                 "f" eaf-browser-keybinding)
(eaf-bind-key insert_or_open_link "fl" eaf-browser-keybinding)

in an Emacs instance; go to, say, duckduckgo.com; and try typing "puff" in the search box. While I want to use f l to run eaf-py-proxy-insert_or_open_link, I also want to be able to use "f" and "fl" in textboxes on webpages, when I type in them. Outside of said textboxes, I want to be able to type f l to run eaf-py-proxy-insert_or_open_link.

manateelazycat commented 2 years ago

https://github.com/emacs-eaf/emacs-application-framework/blob/44a207e07381feaab698a4a4dff2975617b44578/core/buffer.py#L156

In core/buffer.py, when is_focus() is true, EAF will insert character in textbox, otherwise EAF will do command as user binding.

manateelazycat commented 2 years ago

If what I'm saying still doesn't make sense, just run

(eaf-bind-key nil                 "f" eaf-browser-keybinding)
(eaf-bind-key insert_or_open_link "fl" eaf-browser-keybinding)

in an Emacs instance; go to, say, duckduckgo.com; and try typing "puff" in the search box. While I want to use f l to run eaf-py-proxy-insert_or_open_link, I also want to be able to use "f" and "fl" in textboxes on webpages, when I type in them. Outside of said textboxes, I want to be able to type f l to run eaf-py-proxy-insert_or_open_link.

I never try binding "fl" key with eaf-bind-key, don't know whether can work.

I just wonder why you need binding two characters as keybinding? With EAF principle, I don't think EAF can handle two characters keybinding.

WammKD commented 2 years ago

Hmm; that's entirely fair. I thought that might end up being the case but wanted to ask, just in case.

For this particular case, mostly because my muscle-memory has me instinctively going to f l, whenever I want to follow a link, rather than just f; I always end up accidentally typing "l", with the default bindings.

But I think binding multiple characters can be really intuitive for, especially, Emacs users (given the way Emacs does key bindings) but I can definitely understand if it isn't feasible.

Thanks a ton, though, for hearing me out!

manateelazycat commented 2 years ago

Hmm; that's entirely fair. I thought that might end up being the case but wanted to ask, just in case.

For this particular case, mostly because my muscle-memory has me instinctively going to f l, whenever I want to follow a link, rather than just f; I always end up accidentally typing "l", with the default bindings.

But I think binding multiple characters can be really intuitive for, especially, Emacs users (given the way Emacs does key bindings) but I can definitely understand if it isn't feasible.

Thanks a ton, though, for hearing me out!

The principle is possible, I also understand how you want to do it.

I just feel that there is no advantage. ;)

manateelazycat commented 2 years ago

Hmm; that's entirely fair. I thought that might end up being the case but wanted to ask, just in case.

For this particular case, mostly because my muscle-memory has me instinctively going to f l, whenever I want to follow a link, rather than just f; I always end up accidentally typing "l", with the default bindings.

But I think binding multiple characters can be really intuitive for, especially, Emacs users (given the way Emacs does key bindings) but I can definitely understand if it isn't feasible.

Thanks a ton, though, for hearing me out!

I think you can do insert_or_continue at Elisp side:

(eaf-call-sync "execute_function" eaf--buffer-id "is_focus")

Above is use for test cursor is in textbox.

(eaf-call-async "send_key" eaf--buffer-id "l"))

Above is use for send key "l" to EAF buffer.

(eaf-call-sync "execute_function" eaf--buffer-id "get_url")

Above is call function "get_url" that define in app/buffer.py class

Then you can binding "fl" to an elisp function, when focus, send key "f", otherwise parse character after "f", then call function.

WammKD commented 2 years ago

Hey; I wanted to say thanks, so much, for this info. It was super helpful, though I didn't get enough freetime to take a look at it until now.

Using what you provided, I was able to come up with

(defun eaf-py-proxy-insert_or_continue_binding ()
  (interactive)

  (let* ((rk              (recent-keys))
         (k  (aref rk (1- (length rk)))))
    (if (eaf-call-sync "execute_function" eaf--buffer-id "is_focus")
        (eaf-call-async "send_key" eaf--buffer-id (key-description (vector k)))
      (call-interactively
        (key-binding (kbd (key-description (vconcat (vector k)
                                                    (read-key-sequence "" k)))))))))

which I think would accomplish what I'd originally wanted; probably not good practice to use the eaf-py-proxy- prefix but such a naming allowed me to bind with eaf-bind-key. The only snag is you can't bind both f and fl.

So, sadly, I had to go with something less elegant; I modified to

(defun eaf-py-proxy-insert_or_continue_binding ()
  (let* ((rk              (recent-keys))
         (k  (aref rk (1- (length rk)))))
    (if (eaf-call-sync "execute_function" eaf--buffer-id "is_focus")
        (eaf-call-async "send_key" eaf--buffer-id (key-description (vector k)))
      (key-description (read-key-sequence "" k)))))

which doesn't allow you to bind more than two-character chains, as anything after the first letter has to be unbound, but it still allows chains of two character bindings.

You then just have to create a helper function to actually create various bindings; in my fl example, I came up with

(defun eaf-py-proxy-insert_or_follow_link ()
  (interactive)

  (pcase (eaf-py-proxy-insert_or_continue_binding)
    ("l" (eaf-call-sync "execute_function" eaf--buffer-id "insert_or_open_link"))))

which then allows me to do my fl binding while still able to use the letter "f" in textboxes. And, if I have any other f- bindings, I just add the letter to the pcase structure and can for various other ones. I then just had to add (eaf-bind-key insert_or_follow_link "f" eaf-browser-keybinding) to make sure the function was triggered when I pressed "f".

This is fantastic (for me) so thanks, once again, so much for all the info. you provided in your last comments.

manateelazycat commented 2 years ago

you're welcome