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

Dispatch command hook #3508

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions source/browser.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,6 @@ Which commands will they invoke next?")
nil
:type (maybe function)
:documentation "The last command invoked by the user.")
(command-dispatcher
#'dispatch-command
:type (or sym:function-symbol function)
:documentation "Function to process the command processed in `dispatch-input-event'.
Takes the function/command as the only argument.")
(prompt-buffer-generic-history
(make-ring)
:documentation "The default history of all prompt buffer entries.
Expand Down
14 changes: 14 additions & 0 deletions source/buffer.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
"Hook to modify keymaps.
Get a list of `nkeymaps:keymap's and `buffer' and return a new list and buffer.")
(export-always '(hook-keymaps-buffer))
(hooks:define-hook-type command (function ((or sym:function-symbol function))
boolean)
"Hook to dispatch command.
Get a command and return a boolean indicating whether the command is handled.")
(export-always '(hook-command))
(hooks:define-hook-type url->url (function (quri:uri) quri:uri)
"Hook getting a `quri:uri' and returning same/another one. ")

Expand Down Expand Up @@ -461,6 +466,15 @@ To access all modes, including disabled ones, use `slot-value'."
:combination #'hooks:combine-composed-hook)
:type hook-keymaps-buffer
:documentation "Hook run as a return value of `current-keymaps'.")
(dispatch-command-hook
(make-instance 'hook-command
:combination #'hooks:combine-hook-until-success)
:type (or sym:function-symbol function)
:documentation "Hook to process the command processed in `dispatch-input-event'.
Takes the function/command as the only argument. Each handler should return a
boolean indicating whether it dispatched the command successfully. Handlers are
tried in successsion until the first handler which returns T. If no handlers in
this hook dispatched the command, `dispatch-command' is used as fallback.")
(conservative-word-move
nil
:documentation "If non-nil, the cursor moves to the end
Expand Down
4 changes: 2 additions & 2 deletions source/changelog.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
(:li "Refactor input to be handled on the buffer level rather than the window
level.")
(:li "Delete " (:code "input-skip-dispatcher") ".")
(:li "Move slot " (:nxref :slot 'command-dispatcher :class-name 'browser)
" from window to the browser class.")
(:li "Change slot " (:code "command-dispatcher")
" in window class to the " (:nxref :slot 'dispatch-command-hook :class-name 'buffer) ".")
(:li "Move slots " (:nxref :slot 'last-key :class-name 'buffer)
" and " (:nxref :slot 'key-stack :class-name 'buffer)
" from window to the buffer class.")
Expand Down
7 changes: 4 additions & 3 deletions source/describe.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -636,15 +636,16 @@ A command is a special kind of function that can be called with
(buffer-load-internal-page-focus 'describe-bindings :buffer-id (id buffer)))

(defun describe-key-dispatch (command)
(hooks:remove-hook (dispatch-command-hook (current-buffer)) 'describe-key-dispatch)
(unwind-protect (describe-command :command (typecase command
(symbol command)
(command (name command))))
(setf (command-dispatcher *browser*) #'dispatch-command)
(echo-dismiss)))
(echo-dismiss)
t))

(define-command describe-key ()
"Display binding of user-inputted keys."
(setf (command-dispatcher *browser*) #'describe-key-dispatch)
(hooks:add-hook (dispatch-command-hook (current-buffer)) 'describe-key-dispatch)
(echo "Press a key sequence to describe:"))

(export-always 'system-information)
Expand Down
3 changes: 2 additions & 1 deletion source/input.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ Return nil to forward to renderer or non-nil otherwise."
(log:debug "Found key binding ~a to ~a." (keyspecs key-stack translated-key) bound-function)
(setf (last-key buffer) (first key-stack))
(run-thread "run-command"
(unwind-protect (funcall (command-dispatcher *browser*) command)
(unwind-protect (or (hooks:run-hook (dispatch-command-hook buffer) command)
(dispatch-command command))
(setf key-stack nil)))
t))
((or (and (input-buffer-p buffer) (forward-input-events-p buffer))
Expand Down
35 changes: 22 additions & 13 deletions source/mode/repeat.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -113,29 +113,38 @@ It takes a `repeat-mode' instance as argument.")
"Create a command dispatcher that counts the M-digit keys and adds them together.
Once a non-number key is pressed, it dispatches this key to a command and starts
repeating it like a regular `repeat-mode' does."
(lambda (command)
(if (eq 'repeat-key command)
(dispatch-command command)
(unwind-protect
(repeat-times :times times
:function (lambda (mode)
(declare (ignore mode))
(nyxt::run command)))
(setf (command-dispatcher *browser*) #'dispatch-command
*repeat-times-stack* 0)))))
(make-instance
'hooks:handler
:name 'repeat-command-dispatcher
:fn
(lambda (command)
(if (eq 'repeat-key (name command))
(dispatch-command command)
(unwind-protect
(repeat-times :times times
:function (lambda (mode)
(declare (ignore mode))
(nyxt::run command)))
(setf *repeat-times-stack* 0)
(hooks:remove-hook (dispatch-command-hook (current-buffer))
'repeat-command-dispatcher)
t)))))

(define-command-global repeat-key
(&key (times (or
(ignore-errors
(parse-integer
(keymaps:key-value (nyxt::last-key (current-window)))))
(keymaps:key-value (nyxt::last-key (current-buffer)))))
(ignore-errors
(parse-integer
(prompt1 :prompt "Repeat for X times"
:input "4"
:hide-suggestion-count-p t
:sources 'prompter:raw-source))))))
"Repeat the command bound to the user-pressed keybinding TIMES times."
(setf *repeat-times-stack* (+ times (* 10 *repeat-times-stack*))
(command-dispatcher *browser*) (make-repeat-command-dispatcher *repeat-times-stack*))
(setf *repeat-times-stack* (+ times (* 10 *repeat-times-stack*)))
(hooks:remove-hook (dispatch-command-hook (current-buffer))
'repeat-command-dispatcher)
(hooks:add-hook (dispatch-command-hook (current-buffer))
(make-repeat-command-dispatcher *repeat-times-stack*))
(echo "Press a key sequence for command to repeat ~R times:" *repeat-times-stack*))