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

WIP: Minibuffer overhaul #1054

Closed
wants to merge 119 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
770d39b
libraries/class-star: Patch process-slot-definition to avoid exportin…
Ambrevar Nov 27, 2020
bb2ee1d
libraries/minibuffer: Initialize.
Ambrevar Nov 24, 2020
8ddf574
Rename keep-exact-matches-in-suggestions to delete-inexact-matches.
Ambrevar Dec 1, 2020
bcf85df
nyxt.asd: Add mk-string-metrics and trivial-package-local-nicknames t…
Ambrevar Dec 11, 2020
4bf8fa4
libraries/minibuffer: Rename initializer and cleanup to constructor a…
Ambrevar Dec 11, 2020
329374c
libraries/minibuffer: Rename ready? to ready-p.
Ambrevar Dec 11, 2020
d5204f0
Draft: Try using dummy text widget to accept input methods. Does not…
Ambrevar Dec 11, 2020
eaa161f
Forward event even when minibuffer is up.
Ambrevar Dec 11, 2020
a1a4a21
Revert "Forward event even when minibuffer is up."
Ambrevar Dec 20, 2020
b473f08
Revert "Draft: Try using dummy text widget to accept input methods. …
Ambrevar Dec 20, 2020
daef71a
GTK: Fix typo in %within-renderer-thread docstring.
Ambrevar Dec 20, 2020
83fd8d9
DRAFT: Add HTML input tag and read from it.
Ambrevar Dec 20, 2020
39ff4bf
Revert "DRAFT: Add HTML input tag and read from it."
Ambrevar Dec 20, 2020
ccb32bb
Add ffi-minibuffer-evaluate-javascript / ffi-minibuffer-evaluate-java…
Ambrevar Dec 20, 2020
cfe9892
libraries/minibuffer: Rename to "prompter".
Ambrevar Dec 20, 2020
5724e77
dir-locals: Add ffi-method.
Ambrevar Dec 20, 2020
6b409f2
libraries/prompter: Finish renaming `minibuffer' to `prompter'.
Ambrevar Dec 20, 2020
2be9e36
libraries/prompter: Add yes-no source.
Ambrevar Dec 20, 2020
12cf63f
Draft: Initial prompt-buffer implementation.
Ambrevar Dec 20, 2020
5bbdf8d
libraries/prompter: Disable must-match-p if there is no filter.
Ambrevar Dec 21, 2020
e84e66b
libraries/prompter: Add return-selection.
Ambrevar Dec 21, 2020
a7ee4f0
libraries/prompter: Fix test indentation and warning.
Ambrevar Dec 21, 2020
95d908e
libraries/prompter: Add "Return result" test.
Ambrevar Dec 21, 2020
95876fa
Draft: Prepare source to welcome prompt-buffer.
Ambrevar Dec 21, 2020
27a84cd
prompt-buffer-mode: Simplify return-selection, add cancel-input, remo…
Ambrevar Dec 21, 2020
c1359b8
Draft: prompt-buffer: Prepare and fix compilation.
Ambrevar Dec 21, 2020
edcce23
libraries/prompter: Allow must-match-p to be nil.
Ambrevar Dec 21, 2020
ada61ee
prompt-buffer: Get set-url2 to not fail.
Ambrevar Dec 21, 2020
c91f57a
Draft: prompt-buffer: Fix init display.
Ambrevar Dec 21, 2020
de3c9ad
libraries/prompter: Don't destroy the minibuffer when returning selec…
Ambrevar Dec 21, 2020
54ad31e
Draft: prompt-buffer: Handle escape input.
Ambrevar Dec 21, 2020
aab2e46
Draft: prompt-buffer: Display suggestions.
Ambrevar Dec 21, 2020
1a87eb2
Draft: prompt-buffer: Refresh candidate list on input change.
Ambrevar Dec 21, 2020
0c2c6fe
libraries/prompter: Mitigate error when cancelling thread.
Ambrevar Dec 21, 2020
addf23e
Draft: prompt-buffer: Update some comments.
Ambrevar Dec 22, 2020
5bc06f8
libraries/prompter: Fix initial suggestion destruction on update.
Ambrevar Dec 22, 2020
d2c203b
libraries/prompter: Include all suggestions on empty input.
Ambrevar Dec 22, 2020
78f766a
prompt-buffer: Display counts.
Ambrevar Dec 22, 2020
283b078
prompt-buffer: Restore style.
Ambrevar Dec 22, 2020
dbdb853
prompt-buffer: Remove unreachable branch in update-suggestion-html.
Ambrevar Dec 22, 2020
b8d2b72
prompt-buffer: Print multiple columns.
Ambrevar Dec 22, 2020
18290d0
libraries/prompter: Add select-next and select-previous.
Ambrevar Dec 22, 2020
1cfe472
libraries/prompter: Return value in return-selection.
Ambrevar Dec 22, 2020
e3d6ba1
libraries/prompter: Fix channel initialization in source.
Ambrevar Dec 22, 2020
7f5a77b
Draft: prompt-buffer: Add select-next and select-previous commands.
Ambrevar Dec 22, 2020
8c9c7a0
prompt-buffer: Scroll into view when selection moves.
Ambrevar Dec 23, 2020
1d61ad3
prompt-buffer: List suggestions around cursor.
Ambrevar Dec 23, 2020
3ff723e
libraries/prompter: Accept STEPS argument in select functions.
Ambrevar Dec 23, 2020
ae3ddfd
prompt-buffer: Add next-page command.
Ambrevar Dec 23, 2020
0703c1c
libraries/prompter: Simplify and fix `select'.
Ambrevar Dec 23, 2020
3a2b04f
libraries/prompter: Fix overflow on last element in `select'.
Ambrevar Dec 23, 2020
f37f240
prompt-buffer: Add select-previous-page.
Ambrevar Dec 23, 2020
3681213
Draft: prompt-buffer: Attempt to fix HTML overflow in suggestion table.
Ambrevar Dec 23, 2020
6196b52
prompt-buffer: Add copy-selection.
Ambrevar Dec 23, 2020
1416363
prompt-buffer: Add prompt-buffer-paste.
Ambrevar Dec 23, 2020
b2af8d3
Fix %paste moving input tag cursor.
Ambrevar Dec 23, 2020
cc5c9d9
libraries/prompter: Fix return-selection on selection.
Ambrevar Dec 23, 2020
789a1aa
libraries/prompter: Add return-input.
Ambrevar Dec 23, 2020
aa3558b
prompt-buffer: Add return-input.
Ambrevar Dec 23, 2020
b205b8c
prompt-buffer-mode: Fix export conflict with `start'.
Ambrevar Dec 23, 2020
ac13f9f
prompt-buffer: Add toggle-mark and toggle-mark-backwards.
Ambrevar Dec 23, 2020
254a189
prompt-buffer: Add current-source and current-selection helpers.
Ambrevar Dec 23, 2020
9823caf
prompt-buffer: Add marked-suggestions helper.
Ambrevar Dec 23, 2020
e7885a1
prompt-buffer: Support marks in copy-selection.
Ambrevar Dec 23, 2020
66a387f
prompt-buffer: Add mark-all, unmark-all, toggle-mark-all.
Ambrevar Dec 23, 2020
d96e3fb
libraries/prompter: Add selected-source, selected-suggestion, all-mar…
Ambrevar Dec 26, 2020
d9c956c
prompt-buffer: Rename current-selection and prompt-buffer-marked-sugg…
Ambrevar Dec 26, 2020
f725a6e
libraries/prompter: Add select-first, select-last.
Ambrevar Dec 26, 2020
1958dee
prompt-buffer: Bind select-first, select-last to M-< and M->.
Ambrevar Dec 26, 2020
2c0cbd0
libraries/prompter: Add select-next-source and select-previous-source.
Ambrevar Dec 26, 2020
e940a9a
prompt-buffer: Bind select-next-source and select-previous-source to …
Ambrevar Dec 26, 2020
31456a6
libraries/prompter: Include input in suggestions if there is no prepr…
Ambrevar Dec 27, 2020
57c68e5
prompt-buffer: Use new global-history-source and new-url-source in se…
Ambrevar Dec 27, 2020
8927d61
prompt-buffer: Add workaround for source without suggestions.
Ambrevar Dec 27, 2020
6aae366
libraries/prompter: Maybe fix ready-p when called multiple times.
Ambrevar Dec 27, 2020
3d37ca8
libraries/prompter: Notify when individual sources are ready.
Ambrevar Dec 27, 2020
a2e5c95
libraries/prompter: Fix possible race condition when resetting ready-…
Ambrevar Dec 27, 2020
80b5db0
libraries/prompter: Simplify all-ready-p.
Ambrevar Dec 27, 2020
49bff4b
prompt-buffer: Print multiple sources together, update them independe…
Ambrevar Dec 27, 2020
b1e5b3e
libraries/prompter: Fix skipping of next suggestion when at end of so…
Ambrevar Dec 27, 2020
06e0af7
libraries/prompter: Fix race condition with next-ready-p.
Ambrevar Dec 29, 2020
a6adca9
libraries/prompter: Make `name' slot mandatory for sources.
Ambrevar Dec 29, 2020
9ae383d
libraries/prompter: Use exported slots of structures and classes in o…
Ambrevar Dec 29, 2020
87d014a
libraries/prompter: Add action helpers.
Ambrevar Dec 30, 2020
db8c6cb
package: Import define-class in nyxt-user and prompt-buffer-mode.
Ambrevar Dec 30, 2020
1da17f2
prompt-buffer: Fix race condition with current-source in update-sugge…
Ambrevar Dec 30, 2020
60ac9df
prompt-buffer: Add initial action support.
Ambrevar Dec 30, 2020
484cbbb
libraries/prompter: Unexport `selection'.
Ambrevar Dec 30, 2020
8a1589d
prompt-buffer: Don't use unexported `selection', use helpers instead.
Ambrevar Dec 30, 2020
d0be2fe
libraries/prompter: Have return-selection run the default action.
Ambrevar Dec 30, 2020
abc7f69
prompt-buffer: Have return-selection run the default action.
Ambrevar Dec 30, 2020
ced33ed
Replace nested `let` with `let*`.
Ambrevar Dec 30, 2020
8d2b7a3
prompt-buffer: Display actions properties (name and docstring).
Ambrevar Dec 30, 2020
e6c99d1
Draft: Add switch-buffer2 (using prompt-buffer).
Ambrevar Dec 30, 2020
2497075
libraries/prompter: Rename and fix the `destructor' method to a `dest…
Ambrevar Dec 30, 2020
bfed892
prompt-buffer: Rename `destructor' to `destroy'.
Ambrevar Dec 30, 2020
b651db9
prompt-buffer: Clean up `value' dereferencing.
Ambrevar Dec 30, 2020
c8fb7ca
prompt-buffer: Implement persistent actions.
Ambrevar Dec 30, 2020
8866e62
libraries/prompter: Call persistent action when `follow-p` is non-nil.
Ambrevar Dec 30, 2020
ebec9f1
libraries/prompter: Call source destructor also over prompter and set…
Ambrevar Dec 30, 2020
f1d93fa
prompt-buffer: Replace manual invokation with `call-persistent-action'.
Ambrevar Dec 30, 2020
3d6f6d9
prompt-buffer: Enable `follow-p' for `buffer-source'.
Ambrevar Dec 30, 2020
37e8cef
libraries/prompter: Add toggle-follow.
Ambrevar Dec 30, 2020
1333847
prompt-buffer: Bind "C-c C-f" to toggle-follow.
Ambrevar Dec 30, 2020
198dfc1
prompt-buffer.lisp: add style for top of input area
jmercouris Jan 25, 2021
95c53b7
prompt-buffer.lisp: rename prompt-input -> prompt-area
jmercouris Jan 25, 2021
63fe08f
prompt-buffer.lisp: remove commented code, updated elsewhere
jmercouris Jan 25, 2021
5f45306
prompt-buffer.lisp: update suggestions style
jmercouris Jan 25, 2021
23f4a9d
prompt-buffer.lisp: set max-suggestion-count to 10
jmercouris Jan 25, 2021
e4161dd
prompt-buffer.lisp: show lighthouse symbol next to source name
jmercouris Jan 26, 2021
99f1409
prompt-buffer.lisp: indent suggestions from a source-name
jmercouris Jan 26, 2021
150379e
prompt-buffer.lisp: remove UPCASE CAPITALIZATION from properties/columns
jmercouris Jan 26, 2021
f895410
prompt-buffer.lisp: tweak appearance of prompt buffer area
jmercouris Jan 26, 2021
37fc55c
prompt-buffer.lisp: rename "cursor" -> "selection"
jmercouris Jan 26, 2021
682074e
renderer-gtk.lisp: set the focus of the widget when switching buffers
jmercouris Jan 27, 2021
b98c70e
renderer-gtk.lisp: set to the focus to the minibuffer if its height i…
jmercouris Jan 27, 2021
d392486
prompt-buffer.lisp: redesign appearance of minibuffer
jmercouris Jan 29, 2021
2eeafba
prompt-buffer.lisp: remove element-in-view-port code
jmercouris Jan 29, 2021
1b42036
prompt-buffer.lisp: clip overflowed content
jmercouris Jan 29, 2021
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
113 changes: 113 additions & 0 deletions libraries/class-star/patch.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
;;;; SPDX-License-Identifier: Public Domain

;; This is a hotpatch for hu.dwim.defclass-star which is under the public
;; domain.

(in-package hu.dwim.defclass-star)

(defun process-slot-definition (definition)
(unless (consp definition)
(setf definition (list definition)))
(let ((name (pop definition))
(initform 'missing)
(entire-definition definition))
(assert name)
(push name *slot-names*)
(if (oddp (length definition))
(progn
(setf initform (pop definition))
(setf entire-definition definition)
(when (eq initform :unbound)
(setf initform 'missing)))
(setf initform (getf definition :initform 'missing)))
(assert (every #'keywordp (loop for el :in definition :by #'cddr
collect el))
() "Found non-keywords in ~S" definition)
(destructuring-bind (&key (accessor 'missing) (initarg 'missing)
(reader 'missing) (writer 'missing)
(export 'missing)
&allow-other-keys)
definition
(remf-keywords definition :accessor :reader :writer :initform :initarg :export)
(let ((unknown-keywords (loop for el :in definition :by #'cddr
unless (or (member t *allowed-slot-definition-properties*)
(member el *allowed-slot-definition-properties*))
collect el))
(slot-name-warning-triggered? nil))
(when unknown-keywords
(style-warn "Unexpected properties in slot definition ~S.~%~
The unexpected properties are ~S.~%~
To avoid this warning (pushnew (or T :your-custom-keyword) hu.dwim.defclass-star:*allowed-slot-definition-properties*)"
entire-definition unknown-keywords))
(flet ((provided-p (value)
(and value
(not (eq value 'missing))))
(transform-accessor ()
(funcall *accessor-name-transformer* name entire-definition))
(maybe-warn-for-slot-name ()
(unless (or slot-name-warning-triggered?
(eq (symbol-package name) *package*))
(setf slot-name-warning-triggered? t)
#+nil ;; this generates too many warnings which makes it kinda pointless
(style-warn "defclass* for a slot name ~A while its home package is not *package* (~A). Default generated names will be interned into *package*!"
(fully-qualified-symbol-name name) *package*))))
(prog1
(funcall *slot-definition-transformer*
(append (list name)
(unless (eq initform 'missing)
(list :initform initform))
(if (and (eq accessor 'missing)
(eq reader 'missing)
(eq writer 'missing))
(when *automatic-accessors-p*
(maybe-warn-for-slot-name)
(setf accessor (transform-accessor))
(list :accessor accessor))
(let ((transformed-accessor (transform-accessor)))
(append (progn
(when (eq accessor t)
(setf accessor transformed-accessor))
(when (provided-p accessor)
(list :accessor accessor)))
(progn
(when (eq reader t)
(setf reader transformed-accessor))
(when (provided-p reader)
(list :reader reader)))
(progn
(when (eq writer t)
(setf writer `(setf ,transformed-accessor)))
(when (provided-p writer)
(list :writer writer))))))
(if (eq initarg 'missing)
(when *automatic-initargs-p*
(list :initarg (funcall *initarg-name-transformer* name entire-definition)))
(when initarg
(list :initarg initarg)))
definition))
(when (provided-p accessor)
(pushnew accessor *accessor-names*))
(when (provided-p reader)
(pushnew reader *accessor-names*))
(when (provided-p writer)
(pushnew (second writer) *accessor-names*))
(if (not (eq export 'missing))
(ecase export
(:accessor
(when accessor
(push accessor *symbols-to-export*)))
((:slot :name :slot-name)
(push name *symbols-to-export*))
((t)
;; XXX: The `when' condition was just `accessor' and failed to account for missing accessors.
(when (and accessor (not (eq accessor 'missing)))
(push accessor *symbols-to-export*))
(push name *symbols-to-export*))
((nil)))
(progn
(when *export-accessor-names-p*
;; XXX: Same as above.
(when (and accessor (not (eq accessor 'missing)))
(push accessor *symbols-to-export*)))
(when *export-slot-names-p*
(push name *symbols-to-export*))))))))))
55 changes: 55 additions & 0 deletions libraries/prompter/filter-preprocessor.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
;;;; SPDX-FileCopyrightText: Atlas Engineer LLC
;;;; SPDX-License-Identifier: BSD-3-Clause

(in-package :prompter)

(defun find-exactly-matching-substrings (input suggestion-match-data
&key (substring-length 2))
"Return the list of input substrings that match at least one suggestion.
The substrings must be SUBSTRING-LENGTH characters long or more."
(let ((input-strings (delete-if (lambda (s) (< (length s) substring-length))
(str:split " " input :omit-nulls t))))
(when input-strings
(delete-duplicates
(loop for match-datum in suggestion-match-data
append (remove-if
(lambda (i)
(not (search i match-datum)))
input-strings))
:test #'string=))))

(defun format-properties (properties &optional downcasedp)
(let ((result
(str:join " "
(loop for i on properties by #'cddr
collect (second i)))))
(if downcasedp
(string-downcase result)
result)))

(export-always 'delete-inexact-matches)
(defun delete-inexact-matches (suggestions source input)
"Destructively filter out non-exact matches from SUGGESTIONS.
Return the resulting list.
If any input substring matches exactly (but not necessarily a whole word),
then all suggestions that are not exactly matched by at least one substring are removed.

Suitable as a `prompter-source' `filter-preprocessor'."
;; TODO: Compute match-data separately. Make it customizable.
(dolist (suggestion suggestions)
(setf
(match-data suggestion)
(format-properties
(filtered-properties-suggestion suggestion (active-properties source))
(str:downcasep input))))
(unless (str:empty? input)
(let ((exactly-matching-substrings (find-exactly-matching-substrings
input
(mapcar #'match-data suggestions))))
(when exactly-matching-substrings
(setf suggestions
(delete-if (lambda (suggestion)
(not (loop for i in exactly-matching-substrings
always (search i (match-data suggestion)))))
suggestions)))))
suggestions)
70 changes: 70 additions & 0 deletions libraries/prompter/filter.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
;;;; SPDX-FileCopyrightText: Atlas Engineer LLC
;;;; SPDX-License-Identifier: BSD-3-Clause

(in-package :prompter)

(defun substring-norm (substrings string &key (substring-length 2))
"Return the norm of SUBSTRINGS with regard to STRING.
The norm is closer to 1 if
- substrings start near the beginning of STRING;
- substrings length are closer to the length of STRING.

Only substrings of SUBSTRING-LENGTH characters or more are considered."
;; TODO: Remove duplicates in SUBSTRINGS? Repeats could mean we insist more on it.
(let ((position-factor 1.0)
(length-factor 1.0)
(long-substrings (remove-if (lambda (s) (> substring-length (length s)))
substrings)))
(if long-substrings
(/ (apply #'+
(mapcar (lambda (s)
(let ((position (search s string)))
(if (not position)
0
(/ (+
(* position-factor
(/ 1
;; We use the sqrt to slow down the
;; decrease rate, we want the a
;; position of 10-15 still be >0.1.
(sqrt (1+ position))))
(* length-factor
(/ (min (length s) (length string))
(length string))))
(+ position-factor length-factor)))))
long-substrings))
(length long-substrings))
0)))

(defun to-unicode (input)
"Convert INPUT to (simple-array character) type."
(if (typep input 'base-string)
(coerce input `(simple-array character (,(length input))))
input))

(defun score-suggestion-string (input suggestion-string)
"Return a SUGGESTION's score for INPUT.
A higher score means the suggestion-string comes first."
;; The Jaccard metric seems to provide much better results than, say,
;; Damerau-Levensthein but it's much slower.
;; TODO: Check out fzf for a possibly good scoring algorithm.
(+ (* 1.0 (mk-string-metrics:norm-damerau-levenshtein suggestion-string input))
(* 1.0 (substring-norm (str:split " " input) suggestion-string))))

(defvar score-threshold 0.0 ; TODO: Learn good value and enable low-score filtering.
"The threshold under which suggestions are eleminated.")

(export-always 'score>)
(defun score> (suggestion1 suggestion2)
"Suitable as a `prompter-source' `sort-predicate'."
(> (score suggestion1)
(score suggestion2)))

(export-always 'fuzzy-match)
(defun fuzzy-match (input suggestion)
"Score the SUGGESTION according to a fuzzy string distance to the INPUT."
(setf input (to-unicode input))
(setf (match-data suggestion) (to-unicode (match-data suggestion)))
(setf (score suggestion)
(score-suggestion-string input (match-data suggestion)))
suggestion)
34 changes: 34 additions & 0 deletions libraries/prompter/package.lisp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
;;;; SPDX-FileCopyrightText: Atlas Engineer LLC
;;;; SPDX-License-Identifier: BSD-3-Clause

(in-package cl-user)

(uiop:define-package prompter
(:use #:common-lisp)
(:import-from #:class* #:define-class)
(:import-from #:serapeum #:export-always))

(in-package prompter)

(eval-when (:compile-toplevel :load-toplevel :execute)
(trivial-package-local-nicknames:add-package-local-nickname :alex :alexandria)
(trivial-package-local-nicknames:add-package-local-nickname :sera :serapeum))

(defmacro define-function (name args &body body)
"Eval ARGS then define function over the resulting lambda list.
All ARGS are declared as `ignorable'."
(let ((evaluated-args (eval args)))
`(defun ,name ,evaluated-args
(declare (ignorable ,@(set-difference (mapcar (lambda (arg) (if (listp arg) (first arg) arg))
evaluated-args)
lambda-list-keywords)))
,@body)))

(defun initargs (class-specifier)
"Return CLASS-SPECIFIER initargs as symbols (not keywords)."
(mapcar (lambda (slot)
(intern
(symbol-name
(first (getf (mopu:slot-properties class-specifier slot) :initargs)))
(symbol-package class-specifier)))
(mopu:slot-names class-specifier)))
Loading