There are currently three mutually supportive methods of choosing from
amongst the set of hints; typing numbers, typing text or choosing the
next or previous hints in the sequence.  This patch adds a fourth
method, interactive bisection; it is particularly useful when there
are a large set of hints that are not well distinguished in their
text.  However, it can be awkward to use if the hinted elements are
not arranged in sequence.

Two commands are provided; hints-bisect-forward (bound to M-down) and
hints-bisect-backward (bound to M-up).  On the first use of either of
these command in a hints interaction, a step will be taken half way
through the sequence of hints.  Each subsequent bisect command will
halve the step size in the chosen direction.  A few bisects will
usually get you close to the desired hint.  Using any of the three
other ways to choose a hint will reset the bisection.

Inspired by Luke Gorrie's chop mode for emacs.
---
 modules/bindings/default/hints.js |    2 ++
 modules/hints.js                  |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/modules/bindings/default/hints.js 
b/modules/bindings/default/hints.js
index 6c244f2..0c8d5ed 100644
--- a/modules/bindings/default/hints.js
+++ b/modules/bindings/default/hints.js
@@ -20,6 +20,8 @@ define_key(hint_keymap, "S-tab", "hints-previous");
 define_key(hint_keymap, "up", "hints-previous");
 define_key(hint_keymap, "C-r", "hints-previous");
 define_key(hint_keymap, "C-p", "hints-previous");
+define_key(hint_keymap, "M-down", "hints-bisect-forward");
+define_key(hint_keymap, "M-up", "hints-bisect-backward");
 define_key(hint_keymap, "escape", "minibuffer-abort");
 define_key(hint_keymap, "M-escape", "minibuffer-abort");
 define_key(hint_keymap, "C-g", "minibuffer-abort");
diff --git a/modules/hints.js b/modules/hints.js
index 41e73c9..c65f166 100644
--- a/modules/hints.js
+++ b/modules/hints.js
@@ -100,6 +100,7 @@ function hint_manager (window, xpath_expr, focused_frame, 
focused_element) {
     this.window = window;
     this.hints = [];
     this.valid_hints = [];
+    this.bisection_state = null;
     this.xpath_expr = xpath_expr;
     this.focused_frame = focused_frame;
     this.focused_element = focused_element;
@@ -560,6 +561,7 @@ hints_minibuffer_state.prototype = {
 
     handle_input: function (m) {
         this.clear_auto_exit_timer();
+        this.bisection_state = null;
         this.typed_number = "";
         this.typed_string = m._input_text;
         this.manager.current_hint_string = this.typed_string;
@@ -609,6 +611,7 @@ interactive("hints-handle-number",
     function (I) {
         let s = I.minibuffer.check_state(hints_minibuffer_state);
         s.clear_auto_exit_timer();
+        s.manager.bisection_state = null;
         var ch = String.fromCharCode(I.event.charCode);
         if (hint_digits && ch == "0")
             ch = hint_digits[0];
@@ -633,6 +636,7 @@ interactive("hints-handle-number",
 function hints_backspace (window, s) {
     let m = window.minibuffer;
     s.clear_auto_exit_timer();
+    s.manager.bisection_state = null;
     var l = s.typed_number.length;
     if (l > 0) {
         s.typed_number = s.typed_number.substring(0, --l);
@@ -656,6 +660,7 @@ interactive("hints-backspace", null,
 function hints_next (window, s, count) {
     s.clear_auto_exit_timer();
     s.typed_number = "";
+    s.manager.bisection_state = null;
     var cur = s.manager.current_hint_number - 1;
     var vh = s.manager.valid_hints;
     var vl = s.manager.valid_hints.length;
@@ -677,6 +682,37 @@ interactive("hints-previous", null,
         hints_next(I.window, I.minibuffer.check_state(hints_minibuffer_state), 
-I.p);
     });
 
+function hints_bisect (window, s, dir) {
+    var m = s.manager;
+    var vl = m.valid_hints.length;
+    var curr = m.current_hint_number;
+    s.clear_auto_exit_timer();
+    s.typed_number = "";
+    if (vl > 0) {
+        if (!m.bisection_state)
+            m.bisection_state = {
+                curr: curr,
+                step: dir > 0 ? (vl - curr) : (curr - 1)};
+        m.bisection_state.step /= 2;
+        m.bisection_state.curr += dir * m.bisection_state.step;
+        curr = Math.round(m.bisection_state.curr);
+        if (curr < 1)  curr = 1;
+        if (curr > vl) curr = vl;
+        m.select_hint(curr);
+    }
+    s.update_minibuffer(window.minibuffer);
+}
+
+interactive("hints-bisect-forward", null,
+    function (I) {
+        hints_bisect(I.window, 
I.minibuffer.check_state(hints_minibuffer_state), +1);
+    });
+
+interactive("hints-bisect-backward", null,
+    function (I) {
+        hints_bisect(I.window, 
I.minibuffer.check_state(hints_minibuffer_state), -1);
+    });
+
 function hints_exit (window, s) {
     var cur = s.manager.current_hint_number;
     var elem = null;
-- 
1.7.9.1

_______________________________________________
Conkeror mailing list
[email protected]
https://www.mozdev.org/mailman/listinfo/conkeror

Reply via email to