Skip to content

Commit 81ce7fd

Browse files
sirzeratormaxauthority
authored andcommitted
Fixes and refactor in hints module (#597)
* Remove duplicated code in hints initialization and cleanup * Move hints keys handling to hints module * Fix a bug with hints and links containing a 0 When following a link containing a "0", the status bar would always switch to error because of an assertion on 0. This was caused by the double usage of the "0" in hints, both the default (empty) value and the number 0 (part of the default hintchars). This replaces the empty value with null and adds a check so that we don't consider the first char as a hint unless pressed after another hint char. * Convert an assertion to a check in hints _checkUnique When following a link, pressing two hint chars in a row (contained in the link text), would return a loud error because the otherwise valid string sequence would result in a failed assertion. * Fix <BS> in hints module Disconnected, can't determine since when from the history. * Remove _canUpdate and followFirst flags in hints onEvent _canUpdate : if we're in onEvent, something changed in the hints, so we always update. If it's not needed, return early. followFirst : only used with <Return>, call directly instead. * Fix macros mode exiting on hints with letter 'q' Fixes issue #361 * Fix hints in fullscreen Fullscreen window is not accessible right away through window.gBrowser. This debounces the hints generation back on the command stack so window.gBrowser gets set. Fixes issue #419.
1 parent b3bd807 commit 81ce7fd

File tree

2 files changed

+89
-87
lines changed

2 files changed

+89
-87
lines changed

common/content/events.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -878,14 +878,15 @@ const Events = Module("events", {
878878
let url = typeof(buffer) != "undefined" ? buffer.URL : "";
879879

880880
if (modes.isRecording) {
881-
if (key == "q" && liberator.mode != modes.INSERT && liberator.mode != modes.TEXTAREA) { // TODO: should not be hardcoded
881+
if (key == "q" && !(liberator.mode & (modes.INSERT | modes.TEXTAREA | modes.COMMAND_LINE))) { // TODO: should not be hardcoded
882882
modes.isRecording = false;
883883
liberator.echomsg("Recorded macro '" + this._currentMacro + "'");
884884
killEvent();
885885
return;
886886
}
887-
else if (!mappings.hasMap(liberator.mode, this._input.buffer + key, url))
887+
else if (!mappings.hasMap(liberator.mode, this._input.buffer + key, url)) {
888888
this._macros.set(this._currentMacro, this._macros.get(this._currentMacro) + key);
889+
}
889890
}
890891

891892
if (key == "<C-c>")
@@ -966,14 +967,9 @@ const Events = Module("events", {
966967
throw killEvent();
967968
}
968969

969-
// All of these special cases for hint mode are driving
970-
// me insane! -Kris
971970
if (modes.extended & modes.HINTS) {
972971
// under HINT mode, certain keys are redirected to hints.onEvent
973-
if (key == "<Return>" || key == "<Tab>" || key == "<S-Tab>"
974-
|| key == mappings.getMapLeader()
975-
|| (key == "<BS>" && hints.previnput == "number")
976-
|| (hints._isHintNumber(key) && !hints.escNumbers)) {
972+
if (hints.canHandleKey(key)) {
977973
hints.onEvent(event);
978974
this._input.buffer = "";
979975
throw killEvent();

common/content/hints.js

Lines changed: 85 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,11 @@ const Hints = Module("hints", {
1111
requires: ["config"],
1212

1313
init: function () {
14-
1514
this._hintMode = null;
16-
this._submode = ""; // used for extended mode, can be "o", "t", "y", etc.
17-
this._hintString = ""; // the typed string part of the hint is in this string
18-
this._hintNumber = 0; // only the numerical part of the hint
19-
this._usedTabKey = false; // when we used <Tab> to select an element
20-
this._prevInput = ""; // record previous user input type, "text" || "number"
15+
this._submode = ""; // used for extended mode, can be "o", "t", "y", etc.
2116
this._extendedhintCount = null; // for the count argument of Mode#action (extended hint only)
2217

23-
this._pageHints = [];
24-
this._validHints = []; // store the indices of the "hints" array with valid elements
25-
this._tabNavigation = {}; // for navigating between valid hints when TAB key is pressed
26-
27-
this._activeTimeout = null; // needed for hinttimeout > 0
28-
this._canUpdate = false;
29-
30-
// keep track of the documents which we generated the hints for
31-
// this._docs = { doc: document, start: start_index in hints[], end: end_index in hints[] }
32-
this._docs = [];
18+
this._reset();
3319

3420
const Mode = Hints.Mode;
3521
Mode.defaultValue("tags", function () function () options.hinttags);
@@ -88,18 +74,30 @@ const Hints = Module("hints", {
8874
* Reset hints, so that they can be cleanly used again.
8975
*/
9076
_reset: function () {
91-
statusline.updateField("input", "");
92-
this._hintString = "";
93-
this._hintNumber = 0;
94-
this._usedTabKey = false;
95-
this._prevInput = "";
77+
this._hintString = ""; // the typed string part of the hint is in this string
9678
this._pageHints = [];
97-
this._validHints = [];
98-
this._tabNavigation = {};
99-
this._canUpdate = false;
79+
this._validHints = []; // store the indices of the "hints" array with valid elements
80+
this._tabNavigation = {}; // for navigating between valid hints when TAB key is pressed
81+
82+
this._resetInput();
83+
84+
// keep track of the documents which we generated the hints for
85+
// this._docs = { doc: document, start: start_index in hints[], end: end_index in hints[] }
10086
this._docs = [];
101-
hints.escNumbers = false;
10287

88+
this._clearTimeout();
89+
},
90+
91+
_resetInput: function() {
92+
this._hintNumber = null; // only the numerical part of the hint
93+
this._usedTabKey = false; // when we used <Tab> to select an element
94+
this._prevInput = ""; // record previous user input type, "text" || "number"
95+
},
96+
97+
/**
98+
* Clear _activeTimeout, a handle to delayed event (setTimeout)
99+
*/
100+
_clearTimeout: function() {
103101
if (this._activeTimeout)
104102
clearTimeout(this._activeTimeout);
105103
this._activeTimeout = null;
@@ -109,7 +107,11 @@ const Hints = Module("hints", {
109107
* Display the current status to the user.
110108
*/
111109
_updateStatusline: function () {
112-
statusline.updateField("input", (hints.escNumbers ? mappings.getMapLeader() : "") + (this._hintNumber ? this._num2chars(this._hintNumber) : ""));
110+
statusline.updateField(
111+
"input",
112+
(hints.escNumbers ? mappings.getMapLeader() : "") +
113+
(this._hintNumber !== null ? this._num2chars(this._hintNumber) : "")
114+
);
113115
},
114116

115117
/**
@@ -450,7 +452,7 @@ const Hints = Module("hints", {
450452
let valid = validHint(hint.text);
451453
let hintnumchars = this._num2chars(hintnum);
452454
let display = valid && (
453-
this._hintNumber == 0 ||
455+
this._hintNumber === null ||
454456
hintnumchars.indexOf(String(activeHintChars)) == 0
455457
);
456458

@@ -563,6 +565,8 @@ const Hints = Module("hints", {
563565
styles.removeSheet(true, "hint-positions");
564566

565567
this._reset();
568+
statusline.updateField("input", "");
569+
hints.escNumbers = false;
566570
},
567571

568572
_num2chars: function (num) {
@@ -644,9 +648,13 @@ const Hints = Module("hints", {
644648
},
645649

646650
_checkUnique: function () {
647-
if (this._hintNumber == 0)
651+
if (
652+
this._hintNumber === null ||
653+
this._hintNumber === this._chars2num(options.hintchars[0]) ||
654+
this._hintNumber > this._validHints.length
655+
) {
648656
return;
649-
liberator.assert(this._hintNumber <= this._validHints.length);
657+
}
650658

651659
// if we write a numeric part like 3, but we have 45 hints, only follow
652660
// the hint after a timeout, as the user might have wanted to follow link 34
@@ -671,12 +679,9 @@ const Hints = Module("hints", {
671679
this._prevInput = "text";
672680

673681
// clear any timeout which might be active after pressing a number
674-
if (this._activeTimeout) {
675-
clearTimeout(this._activeTimeout);
676-
this._activeTimeout = null;
677-
}
682+
this._clearTimeout();
678683

679-
this._hintNumber = 0;
684+
this._hintNumber = null;
680685
this._hintString = commandline.command;
681686
this._updateStatusline();
682687
this._showHints();
@@ -926,17 +931,19 @@ const Hints = Module("hints", {
926931

927932
this._submode = minor;
928933
this._hintString = filter || "";
929-
this._hintNumber = 0;
930-
this._usedTabKey = false;
931-
this._prevInput = "";
932-
this._canUpdate = false;
934+
this._resetInput();
933935

934-
this._generate(win);
936+
try {
937+
this._generate(win);
938+
} catch (e) {
939+
setTimeout(function() {
940+
hints._generate(win);
941+
}, 0)
942+
}
935943

936944
// get all keys from the input queue
937945
liberator.threadYield(true);
938946

939-
this._canUpdate = true;
940947
this._showHints();
941948

942949
if (this._validHints.length == 0) {
@@ -983,14 +990,28 @@ const Hints = Module("hints", {
983990
this._removeHints(0);
984991
},
985992

993+
/**
994+
* Return true if key is a valid entry point for hints handling
995+
*/
996+
canHandleKey: function(key) {
997+
return (
998+
["<Return>", "<Tab>", "<S-Tab>", mappings.getMapLeader()].indexOf(key) > -1 ||
999+
(key == "<BS>" && hints._prevInput === "number") ||
1000+
(
1001+
hints._isHintNumber(key) &&
1002+
!hints.escNumbers &&
1003+
(key !== options.hintchars[0] || this._prevInput === "number")
1004+
)
1005+
);
1006+
},
1007+
9861008
/**
9871009
* Handle a hint mode event.
9881010
*
9891011
* @param {Event} event The event to handle.
9901012
*/
9911013
onEvent: function (event) {
9921014
let key = events.toString(event);
993-
let followFirst = false;
9941015

9951016
// clear any timeout which might be active after pressing a number
9961017
if (this._activeTimeout) {
@@ -1000,13 +1021,12 @@ const Hints = Module("hints", {
10001021

10011022
switch (key) {
10021023
case "<Return>":
1003-
followFirst = true;
1004-
break;
1005-
1024+
this._processHints(true);
1025+
return;
10061026
case "<Tab>":
10071027
case "<S-Tab>":
10081028
this._usedTabKey = true;
1009-
if (this._hintNumber == 0)
1029+
if (this._hintNumber === null)
10101030
this._hintNumber = 1;
10111031

10121032
let oldId = this._hintNumber;
@@ -1020,14 +1040,14 @@ const Hints = Module("hints", {
10201040
return;
10211041

10221042
case "<BS>":
1023-
if (this._hintNumber > 0 && !this._usedTabKey) {
1043+
if (this._hintNumber !== null && !this._usedTabKey) {
10241044
this._hintNumber = Math.floor(this._hintNumber / 10);
1025-
if (this._hintNumber == 0)
1026-
this._prevInput = "text";
1045+
if (this._hintNumber === 0)
1046+
this._resetInput();
10271047
}
10281048
else {
10291049
this._usedTabKey = false;
1030-
this._hintNumber = 0;
1050+
this._hintNumber = null;
10311051
liberator.beep();
10321052
return;
10331053
}
@@ -1036,49 +1056,35 @@ const Hints = Module("hints", {
10361056
case mappings.getMapLeader():
10371057
hints.escNumbers = !hints.escNumbers;
10381058
if (hints.escNumbers && this._usedTabKey) // this._hintNumber not used normally, but someone may wants to toggle
1039-
this._hintNumber = 0; // <tab>s ? this._reset. Prevent to show numbers not entered.
1059+
this._hintNumber = null; // <tab>s ? this._reset. Prevent to show numbers not entered.
10401060

10411061
this._updateStatusline();
10421062
return;
10431063

10441064
default:
1045-
if (this._isHintNumber(key)) {
1046-
this._prevInput = "number";
1047-
1048-
let oldHintNumber = this._hintNumber;
1049-
if (this._hintNumber == 0 || this._usedTabKey) {
1050-
this._usedTabKey = false;
1051-
this._hintNumber = this._chars2num(key);
1052-
}
1053-
else
1054-
this._hintNumber = this._chars2num(this._num2chars(this._hintNumber) + key);
1055-
1056-
this._updateStatusline();
1057-
1058-
if (!this._canUpdate)
1059-
return;
1065+
if (this._hintNumber !== null) {
1066+
this._hintNumber = this._chars2num(this._num2chars(this._hintNumber) + key);
1067+
}
1068+
else {
1069+
this._usedTabKey = false;
1070+
this._hintNumber = this._chars2num(key);
1071+
}
1072+
this._prevInput = "number";
10601073

1061-
if (this._docs.length == 0) {
1062-
this._generate();
1063-
this._showHints();
1064-
}
1065-
this._showActiveHint(this._hintNumber, oldHintNumber || 1);
1074+
let oldHintNumber = this._hintNumber;
10661075

1067-
liberator.assert(this._hintNumber != 0);
1076+
this._showActiveHint(this._hintNumber, oldHintNumber || 1);
10681077

1069-
this._checkUnique();
1070-
}
1078+
this._checkUnique();
10711079
}
10721080

10731081
this._updateStatusline();
10741082

1075-
if (this._canUpdate) {
1076-
if (this._docs.length == 0 && this._hintString.length > 0)
1077-
this._generate();
1078-
1079-
this._showHints();
1080-
this._processHints(followFirst);
1083+
if (this._docs.length == 0 && this._hintString.length > 0) {
1084+
this._generate();
10811085
}
1086+
this._showHints();
1087+
this._processHints(false);
10821088
}
10831089

10841090
// FIXME: add resize support

0 commit comments

Comments
 (0)