github-search-cli 9.9.0 → 9.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +51 -0
- package/README.md +38 -32
- package/dist/cli.js +450 -106
- package/docs/HOW-TO.md +3 -2
- package/package.json +2 -2
- package/release-notes/9.10.0.md +137 -0
- package/src/help.ts +21 -4
- package/src/tui/mouse.ts +349 -0
- package/src/tui.ts +378 -106
package/dist/cli.js
CHANGED
|
@@ -2153,7 +2153,7 @@ var cached = null;
|
|
|
2153
2153
|
function getVersion() {
|
|
2154
2154
|
if (cached) return cached;
|
|
2155
2155
|
if (true) {
|
|
2156
|
-
cached = "9.
|
|
2156
|
+
cached = "9.10.0";
|
|
2157
2157
|
return cached;
|
|
2158
2158
|
}
|
|
2159
2159
|
try {
|
|
@@ -3874,6 +3874,135 @@ if (import.meta.main && false) {
|
|
|
3874
3874
|
launchTrending();
|
|
3875
3875
|
}
|
|
3876
3876
|
|
|
3877
|
+
// src/tui/mouse.ts
|
|
3878
|
+
var DOUBLE_CLICK_MS = 400;
|
|
3879
|
+
function hitIndexForY(geometry, screenY) {
|
|
3880
|
+
const pitch = geometry.linesPerItem;
|
|
3881
|
+
if (pitch <= 0) return -1;
|
|
3882
|
+
if (geometry.optionCount <= 0) return -1;
|
|
3883
|
+
const localY = screenY - geometry.screenY;
|
|
3884
|
+
if (localY < 0 || localY >= geometry.height) return -1;
|
|
3885
|
+
const row = Math.floor(localY / pitch);
|
|
3886
|
+
const index = geometry.scrollOffset + row;
|
|
3887
|
+
const last = geometry.optionCount - 1;
|
|
3888
|
+
if (index < 0) return 0;
|
|
3889
|
+
return index > last ? last : index;
|
|
3890
|
+
}
|
|
3891
|
+
function selectRowGeometry(select) {
|
|
3892
|
+
const internal = select;
|
|
3893
|
+
return {
|
|
3894
|
+
screenY: select.screenY,
|
|
3895
|
+
height: select.height,
|
|
3896
|
+
optionCount: select.options.length,
|
|
3897
|
+
scrollOffset: internal.scrollOffset ?? 0,
|
|
3898
|
+
linesPerItem: internal.linesPerItem ?? 0
|
|
3899
|
+
};
|
|
3900
|
+
}
|
|
3901
|
+
function attachClickToSelect(renderer, select, options = {}) {
|
|
3902
|
+
const wheelStep = options.wheelStep ?? 3;
|
|
3903
|
+
let lastClickIndex = -1;
|
|
3904
|
+
let lastClickAt = 0;
|
|
3905
|
+
let lastHovered = -1;
|
|
3906
|
+
select.onMouseDown = (event) => {
|
|
3907
|
+
event.stopPropagation();
|
|
3908
|
+
if (options.keepFocus) event.preventDefault();
|
|
3909
|
+
const index = hitIndexForY(selectRowGeometry(select), event.y);
|
|
3910
|
+
if (index < 0) {
|
|
3911
|
+
lastClickIndex = -1;
|
|
3912
|
+
options.onClickMiss?.();
|
|
3913
|
+
return;
|
|
3914
|
+
}
|
|
3915
|
+
const now = Date.now();
|
|
3916
|
+
const alreadySelected = select.getSelectedIndex() === index;
|
|
3917
|
+
const isDouble = alreadySelected && index === lastClickIndex && now - lastClickAt < DOUBLE_CLICK_MS;
|
|
3918
|
+
lastClickIndex = index;
|
|
3919
|
+
lastClickAt = now;
|
|
3920
|
+
if (isDouble) {
|
|
3921
|
+
lastClickIndex = -1;
|
|
3922
|
+
options.onOpen?.();
|
|
3923
|
+
return;
|
|
3924
|
+
}
|
|
3925
|
+
select.setSelectedIndex(index);
|
|
3926
|
+
};
|
|
3927
|
+
select.onMouseScroll = (event) => {
|
|
3928
|
+
event.stopPropagation();
|
|
3929
|
+
const direction = event.scroll?.direction;
|
|
3930
|
+
if (direction === "up") select.moveUp(wheelStep);
|
|
3931
|
+
else if (direction === "down") select.moveDown(wheelStep);
|
|
3932
|
+
else return;
|
|
3933
|
+
renderer.requestRender();
|
|
3934
|
+
};
|
|
3935
|
+
attachHoverHighlight(renderer, select, {
|
|
3936
|
+
onHover: (index) => {
|
|
3937
|
+
lastHovered = index;
|
|
3938
|
+
options.onHoverRow?.(index);
|
|
3939
|
+
},
|
|
3940
|
+
// A stale row must never outlive the options it pointed at.
|
|
3941
|
+
onLeave: () => {
|
|
3942
|
+
lastHovered = -1;
|
|
3943
|
+
}
|
|
3944
|
+
});
|
|
3945
|
+
return {
|
|
3946
|
+
reset() {
|
|
3947
|
+
lastClickIndex = -1;
|
|
3948
|
+
lastClickAt = 0;
|
|
3949
|
+
},
|
|
3950
|
+
get lastHovered() {
|
|
3951
|
+
return lastHovered;
|
|
3952
|
+
}
|
|
3953
|
+
};
|
|
3954
|
+
}
|
|
3955
|
+
function attachHoverHighlight(renderer, select, options = {}) {
|
|
3956
|
+
const idleBackground = select.backgroundColor;
|
|
3957
|
+
const hoverBackground = "#ffffff0f";
|
|
3958
|
+
let hovered = -1;
|
|
3959
|
+
select.onMouseOver = () => {
|
|
3960
|
+
renderer.setMousePointer("pointer");
|
|
3961
|
+
select.backgroundColor = hoverBackground;
|
|
3962
|
+
renderer.requestRender();
|
|
3963
|
+
};
|
|
3964
|
+
select.onMouseOut = () => {
|
|
3965
|
+
renderer.setMousePointer("default");
|
|
3966
|
+
select.backgroundColor = idleBackground;
|
|
3967
|
+
if (hovered !== -1) {
|
|
3968
|
+
hovered = -1;
|
|
3969
|
+
options.onLeave?.();
|
|
3970
|
+
}
|
|
3971
|
+
renderer.requestRender();
|
|
3972
|
+
};
|
|
3973
|
+
select.onMouseMove = (event) => {
|
|
3974
|
+
const index = hitIndexForY(selectRowGeometry(select), event.y);
|
|
3975
|
+
if (index === hovered) return;
|
|
3976
|
+
hovered = index;
|
|
3977
|
+
options.onHover?.(index);
|
|
3978
|
+
};
|
|
3979
|
+
}
|
|
3980
|
+
function attachClickOutside(target, onDismiss) {
|
|
3981
|
+
target.onMouseDown = (event) => {
|
|
3982
|
+
event.stopPropagation();
|
|
3983
|
+
onDismiss();
|
|
3984
|
+
};
|
|
3985
|
+
}
|
|
3986
|
+
function attachClickableBox(renderer, box, handlers) {
|
|
3987
|
+
box.onMouseDown = (event) => {
|
|
3988
|
+
event.stopPropagation();
|
|
3989
|
+
handlers.onActivate();
|
|
3990
|
+
};
|
|
3991
|
+
box.onMouseOver = () => {
|
|
3992
|
+
renderer.setMousePointer("pointer");
|
|
3993
|
+
box.borderColor = handlers.activeBorder;
|
|
3994
|
+
handlers.onStateChange?.();
|
|
3995
|
+
renderer.requestRender();
|
|
3996
|
+
};
|
|
3997
|
+
box.onMouseOut = () => {
|
|
3998
|
+
renderer.setMousePointer("default");
|
|
3999
|
+
box.borderColor = handlers.idleBorder;
|
|
4000
|
+
handlers.onStateChange?.();
|
|
4001
|
+
renderer.requestRender();
|
|
4002
|
+
};
|
|
4003
|
+
}
|
|
4004
|
+
var NON_INTERACTIVE_TEXT = { selectable: false };
|
|
4005
|
+
|
|
3877
4006
|
// src/help.ts
|
|
3878
4007
|
function buildHelpSections() {
|
|
3879
4008
|
return [
|
|
@@ -3895,7 +4024,7 @@ function buildHelpSections() {
|
|
|
3895
4024
|
{ keys: "\u2191 \u2193 / j k", action: "Move selection" },
|
|
3896
4025
|
{ keys: "Enter", action: "Open repo in browser" },
|
|
3897
4026
|
{ keys: "/", action: "Focus search input" },
|
|
3898
|
-
{ keys: "
|
|
4027
|
+
{ keys: "Esc", action: "Open command menu" },
|
|
3899
4028
|
{ keys: "? / Ctrl+H", action: "Toggle this help screen" },
|
|
3900
4029
|
{ keys: "q", action: "Quit" }
|
|
3901
4030
|
]
|
|
@@ -3929,7 +4058,8 @@ function buildHelpSections() {
|
|
|
3929
4058
|
rows: [
|
|
3930
4059
|
{ keys: "1-5", action: "Switch tab: Today \u2192 Week \u2192 Month \u2192 \u2026" },
|
|
3931
4060
|
{ keys: "\u2190 \u2192 / h l", action: "Navigate tabs" }
|
|
3932
|
-
]
|
|
4061
|
+
],
|
|
4062
|
+
note: "Tabs are also clickable."
|
|
3933
4063
|
},
|
|
3934
4064
|
{
|
|
3935
4065
|
title: " Packages Mode ",
|
|
@@ -3938,12 +4068,12 @@ function buildHelpSections() {
|
|
|
3938
4068
|
{ keys: "/", action: "Search npm packages" },
|
|
3939
4069
|
{ keys: "\u2191 \u2193 / j k", action: "Move selection" },
|
|
3940
4070
|
{ keys: "Enter", action: "View package details" },
|
|
3941
|
-
{ keys: "
|
|
4071
|
+
{ keys: "Esc", action: "Open command menu" }
|
|
3942
4072
|
],
|
|
3943
4073
|
note: "Search by name, description, or tags. Sort by downloads or score."
|
|
3944
4074
|
},
|
|
3945
4075
|
{
|
|
3946
|
-
title: " Command Menu (
|
|
4076
|
+
title: " Command Menu (Esc)",
|
|
3947
4077
|
titleColor: "purple",
|
|
3948
4078
|
rows: [
|
|
3949
4079
|
{ keys: "Sort", action: "Cycle sort: best-match \u2192 stars \u2192 \u2026" },
|
|
@@ -3968,7 +4098,7 @@ function buildHelpSections() {
|
|
|
3968
4098
|
{ keys: "History", action: "View search history" },
|
|
3969
4099
|
{ keys: "Help", action: "Show this help screen" }
|
|
3970
4100
|
],
|
|
3971
|
-
note: "Navigate menu with \u2191 \u2193, select with Enter, back with \u2190 / Esc"
|
|
4101
|
+
note: "Navigate menu with \u2191 \u2193, select with Enter, back with \u2190 / Esc. Clicking a row runs it directly. Esc (or the \u2630 menu button) opens this menu; Space types a space in the query."
|
|
3972
4102
|
},
|
|
3973
4103
|
{
|
|
3974
4104
|
title: " Bookmarks Page ",
|
|
@@ -3981,6 +4111,22 @@ function buildHelpSections() {
|
|
|
3981
4111
|
],
|
|
3982
4112
|
note: "A full page, not an overlay \u2014 Esc returns to the mode menu."
|
|
3983
4113
|
},
|
|
4114
|
+
{
|
|
4115
|
+
title: " Mouse ",
|
|
4116
|
+
titleColor: "green",
|
|
4117
|
+
rows: [
|
|
4118
|
+
{ keys: "Click", action: "Select a row / card / tab" },
|
|
4119
|
+
{ keys: "Double-click", action: "Open the repo or run the action" },
|
|
4120
|
+
{ keys: "Scroll wheel", action: "Move the selection / scroll a pane" },
|
|
4121
|
+
{ keys: "Click outside", action: "Dismiss an open overlay" },
|
|
4122
|
+
{ keys: "Click query box", action: "Focus the search input" },
|
|
4123
|
+
{
|
|
4124
|
+
keys: "\u2630 menu button",
|
|
4125
|
+
action: "Open the command menu (bottom-right)"
|
|
4126
|
+
}
|
|
4127
|
+
],
|
|
4128
|
+
note: "Every list is fully clickable; keyboard and mouse are interchangeable."
|
|
4129
|
+
},
|
|
3984
4130
|
{
|
|
3985
4131
|
title: " Overlay Keys ",
|
|
3986
4132
|
titleColor: "teal",
|
|
@@ -5197,7 +5343,7 @@ async function launchBrowser(theme_override) {
|
|
|
5197
5343
|
const compareList = [];
|
|
5198
5344
|
const _quitArmed = false;
|
|
5199
5345
|
const header = new TextRenderable5(renderer, {
|
|
5200
|
-
content: " ghfind \u2014 GitHub repo browser [/]search [
|
|
5346
|
+
content: " ghfind \u2014 GitHub repo browser [/]search [Esc]menu [\u2192]open [?]help [q]uit \xB7 click select \xB7 dbl-click open",
|
|
5201
5347
|
bg: colors.bg,
|
|
5202
5348
|
fg: colors.muted,
|
|
5203
5349
|
height: 1
|
|
@@ -5218,15 +5364,25 @@ async function launchBrowser(theme_override) {
|
|
|
5218
5364
|
const isActive = name === trendingTab;
|
|
5219
5365
|
const label = ` ${name} `;
|
|
5220
5366
|
const tt = new TextRenderable5(renderer, {
|
|
5367
|
+
...NON_INTERACTIVE_TEXT,
|
|
5221
5368
|
content: label,
|
|
5222
5369
|
fg: isActive ? colors.bg : colors.muted,
|
|
5223
5370
|
bg: isActive ? colors.blue : colors.bg,
|
|
5224
5371
|
height: 1
|
|
5225
5372
|
});
|
|
5373
|
+
tt.onMouseDown = (event) => {
|
|
5374
|
+
event.stopPropagation();
|
|
5375
|
+
if (name === trendingTab) return;
|
|
5376
|
+
trendingTab = name;
|
|
5377
|
+
loadTrending();
|
|
5378
|
+
};
|
|
5379
|
+
tt.onMouseOver = () => renderer.setMousePointer("pointer");
|
|
5380
|
+
tt.onMouseOut = () => renderer.setMousePointer("default");
|
|
5226
5381
|
trendingTabTexts.push(tt);
|
|
5227
5382
|
trendingTabBox.add(tt);
|
|
5228
5383
|
if (i < TAB_NAMES.length - 1) {
|
|
5229
5384
|
const sp = new TextRenderable5(renderer, {
|
|
5385
|
+
...NON_INTERACTIVE_TEXT,
|
|
5230
5386
|
content: " ",
|
|
5231
5387
|
fg: colors.muted,
|
|
5232
5388
|
bg: colors.bg,
|
|
@@ -5314,7 +5470,10 @@ async function launchBrowser(theme_override) {
|
|
|
5314
5470
|
const detailText = new TextRenderable5(renderer, {
|
|
5315
5471
|
content: "",
|
|
5316
5472
|
fg: colors.text,
|
|
5317
|
-
wrapMode: "none"
|
|
5473
|
+
wrapMode: "none",
|
|
5474
|
+
// Non-interactive: a left-press here would otherwise be swallowed as a
|
|
5475
|
+
// text-selection drag instead of reaching the click handlers.
|
|
5476
|
+
selectable: false
|
|
5318
5477
|
});
|
|
5319
5478
|
detailBox.add(detailText);
|
|
5320
5479
|
body.add(resultsBox);
|
|
@@ -5329,6 +5488,7 @@ async function launchBrowser(theme_override) {
|
|
|
5329
5488
|
});
|
|
5330
5489
|
root.add(landingBox);
|
|
5331
5490
|
const landingBanner = new TextRenderable5(renderer, {
|
|
5491
|
+
...NON_INTERACTIVE_TEXT,
|
|
5332
5492
|
content: [
|
|
5333
5493
|
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
5334
5494
|
"\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
|
|
@@ -5406,7 +5566,8 @@ async function launchBrowser(theme_override) {
|
|
|
5406
5566
|
card.add(spacerBot);
|
|
5407
5567
|
}
|
|
5408
5568
|
const landingHint = new TextRenderable5(renderer, {
|
|
5409
|
-
|
|
5569
|
+
...NON_INTERACTIVE_TEXT,
|
|
5570
|
+
content: " \u2191\u2193 Navigate \u21E9 Select [b]ookmarks [?]help [q]uit \xB7 click to pick a mode",
|
|
5410
5571
|
fg: colors.muted,
|
|
5411
5572
|
bg: colors.bg,
|
|
5412
5573
|
height: 1,
|
|
@@ -5434,6 +5595,28 @@ async function launchBrowser(theme_override) {
|
|
|
5434
5595
|
}
|
|
5435
5596
|
}
|
|
5436
5597
|
}
|
|
5598
|
+
landingCards.forEach((card, i) => {
|
|
5599
|
+
let lastClickAt = 0;
|
|
5600
|
+
card.onMouseDown = (event) => {
|
|
5601
|
+
event.stopPropagation();
|
|
5602
|
+
const now = Date.now();
|
|
5603
|
+
const isDouble = landingSelected === i && now - lastClickAt < DOUBLE_CLICK_MS;
|
|
5604
|
+
lastClickAt = now;
|
|
5605
|
+
if (isDouble) {
|
|
5606
|
+
landingOptions[i].action();
|
|
5607
|
+
return;
|
|
5608
|
+
}
|
|
5609
|
+
landingSelected = i;
|
|
5610
|
+
updateLandingCards();
|
|
5611
|
+
renderer.requestRender();
|
|
5612
|
+
};
|
|
5613
|
+
card.onMouseOver = () => {
|
|
5614
|
+
renderer.setMousePointer("pointer");
|
|
5615
|
+
};
|
|
5616
|
+
card.onMouseOut = () => {
|
|
5617
|
+
renderer.setMousePointer("default");
|
|
5618
|
+
};
|
|
5619
|
+
});
|
|
5437
5620
|
renderer.keyInput.on("keypress", (key) => {
|
|
5438
5621
|
if (!landingKeysActive(currentMode, currentOverlay)) return;
|
|
5439
5622
|
if (key.name === "up" || key.name === "k") {
|
|
@@ -5498,6 +5681,7 @@ async function launchBrowser(theme_override) {
|
|
|
5498
5681
|
updateDim.visible = false;
|
|
5499
5682
|
if (type === "none") {
|
|
5500
5683
|
currentOverlay = "none";
|
|
5684
|
+
menuButton.visible = true;
|
|
5501
5685
|
if (currentMode === "landing") {
|
|
5502
5686
|
landingBox.visible = true;
|
|
5503
5687
|
body.visible = false;
|
|
@@ -5511,6 +5695,7 @@ async function launchBrowser(theme_override) {
|
|
|
5511
5695
|
return;
|
|
5512
5696
|
}
|
|
5513
5697
|
currentOverlay = type;
|
|
5698
|
+
menuButton.visible = false;
|
|
5514
5699
|
landingBox.visible = false;
|
|
5515
5700
|
if (type !== "leader") {
|
|
5516
5701
|
hideMainContent();
|
|
@@ -5772,7 +5957,8 @@ async function launchBrowser(theme_override) {
|
|
|
5772
5957
|
const compareText = new TextRenderable5(renderer, {
|
|
5773
5958
|
content: "",
|
|
5774
5959
|
fg: colors.text,
|
|
5775
|
-
bg: colors.bg
|
|
5960
|
+
bg: colors.bg,
|
|
5961
|
+
selectable: false
|
|
5776
5962
|
});
|
|
5777
5963
|
compareBox.add(compareText);
|
|
5778
5964
|
root.add(compareBox);
|
|
@@ -5901,7 +6087,8 @@ async function launchBrowser(theme_override) {
|
|
|
5901
6087
|
itemSpacing: 0
|
|
5902
6088
|
});
|
|
5903
6089
|
const leaderFooter = new TextRenderable5(renderer, {
|
|
5904
|
-
|
|
6090
|
+
...NON_INTERACTIVE_TEXT,
|
|
6091
|
+
content: " \u2191\u2193 select Enter run Esc/q close \xB7 click to run click outside to close ",
|
|
5905
6092
|
fg: colors.muted,
|
|
5906
6093
|
bg: colors.surfaceDim,
|
|
5907
6094
|
height: 1,
|
|
@@ -6033,10 +6220,59 @@ async function launchBrowser(theme_override) {
|
|
|
6033
6220
|
neverText.fg = updateSelectedOption === 2 ? colors.yellow : colors.text;
|
|
6034
6221
|
renderer.requestRender();
|
|
6035
6222
|
}
|
|
6223
|
+
function runUpdateOption(index) {
|
|
6224
|
+
updateSelectedOption = index;
|
|
6225
|
+
renderUpdateOptions();
|
|
6226
|
+
const action = ["now", "later", "never"][index];
|
|
6227
|
+
if (action === "now") {
|
|
6228
|
+
showOverlay("none");
|
|
6229
|
+
recordPreUpdateState(cachedVersion ?? "");
|
|
6230
|
+
performUpdate().then((ok) => {
|
|
6231
|
+
if (ok) {
|
|
6232
|
+
setStatus("\u2713 Update complete \u2014 restart ghfind");
|
|
6233
|
+
} else {
|
|
6234
|
+
setStatus("\u2717 Update failed \u2014 check terminal output");
|
|
6235
|
+
}
|
|
6236
|
+
}).catch(() => {
|
|
6237
|
+
setStatus("\u2717 Update failed \u2014 check terminal output");
|
|
6238
|
+
});
|
|
6239
|
+
} else if (action === "never") {
|
|
6240
|
+
suppressUpdateNotices();
|
|
6241
|
+
showOverlay("none");
|
|
6242
|
+
setStatus("Update notices suppressed");
|
|
6243
|
+
} else {
|
|
6244
|
+
snoozeUpdateNotices(3);
|
|
6245
|
+
showOverlay("none");
|
|
6246
|
+
setStatus("Update reminder snoozed for 3 days");
|
|
6247
|
+
}
|
|
6248
|
+
renderer.requestRender();
|
|
6249
|
+
}
|
|
6250
|
+
const updateCards = [
|
|
6251
|
+
[updateNowBox, 0],
|
|
6252
|
+
[laterBox, 1],
|
|
6253
|
+
[neverBox, 2]
|
|
6254
|
+
];
|
|
6255
|
+
for (const [box, index] of updateCards) {
|
|
6256
|
+
attachClickableBox(renderer, box, {
|
|
6257
|
+
onActivate: () => runUpdateOption(index),
|
|
6258
|
+
idleBorder: updateSelectedOption === index ? colors.yellow : colors.border,
|
|
6259
|
+
activeBorder: colors.yellow,
|
|
6260
|
+
// Hovering must not fight the selection highlight, so it only moves the
|
|
6261
|
+
// pointer cursor; the border stays owned by renderUpdateOptions().
|
|
6262
|
+
onStateChange: () => {
|
|
6263
|
+
box.borderColor = updateSelectedOption === index ? colors.yellow : colors.border;
|
|
6264
|
+
}
|
|
6265
|
+
});
|
|
6266
|
+
}
|
|
6267
|
+
attachClickOutside(updateDim, () => {
|
|
6268
|
+
showOverlay("none");
|
|
6269
|
+
renderer.requestRender();
|
|
6270
|
+
});
|
|
6036
6271
|
updateOptionsRow.add(updateNowBox);
|
|
6037
6272
|
updateOptionsRow.add(laterBox);
|
|
6038
6273
|
const updateFooter = new TextRenderable5(renderer, {
|
|
6039
|
-
|
|
6274
|
+
...NON_INTERACTIVE_TEXT,
|
|
6275
|
+
content: " \u2191\u2193/jk/PgUp/PgDn scroll \u2190\u2192 select Enter Esc/q close \xB7 click a button click outside to close",
|
|
6040
6276
|
fg: colors.muted,
|
|
6041
6277
|
bg: colors.surfaceDim,
|
|
6042
6278
|
height: 1,
|
|
@@ -6671,6 +6907,40 @@ async function launchBrowser(theme_override) {
|
|
|
6671
6907
|
paddingX: 1
|
|
6672
6908
|
});
|
|
6673
6909
|
root.add(statusBar);
|
|
6910
|
+
const menuButton = new BoxRenderable5(renderer, {
|
|
6911
|
+
position: "absolute",
|
|
6912
|
+
bottom: 1,
|
|
6913
|
+
right: 1,
|
|
6914
|
+
height: 1,
|
|
6915
|
+
paddingX: 1,
|
|
6916
|
+
backgroundColor: colors.surface,
|
|
6917
|
+
focusable: false
|
|
6918
|
+
});
|
|
6919
|
+
const menuButtonLabel = new TextRenderable5(renderer, {
|
|
6920
|
+
...NON_INTERACTIVE_TEXT,
|
|
6921
|
+
content: "\u2630 menu",
|
|
6922
|
+
fg: colors.muted,
|
|
6923
|
+
bg: colors.surface,
|
|
6924
|
+
height: 1
|
|
6925
|
+
});
|
|
6926
|
+
menuButton.add(menuButtonLabel);
|
|
6927
|
+
root.add(menuButton);
|
|
6928
|
+
menuButton.onMouseDown = (event) => {
|
|
6929
|
+
event.stopPropagation();
|
|
6930
|
+
if (currentOverlay === "leader") showOverlay("none");
|
|
6931
|
+
else showLeaderMenu();
|
|
6932
|
+
renderer.requestRender();
|
|
6933
|
+
};
|
|
6934
|
+
menuButton.onMouseOver = () => {
|
|
6935
|
+
renderer.setMousePointer("pointer");
|
|
6936
|
+
menuButtonLabel.fg = colors.accent;
|
|
6937
|
+
renderer.requestRender();
|
|
6938
|
+
};
|
|
6939
|
+
menuButton.onMouseOut = () => {
|
|
6940
|
+
renderer.setMousePointer("default");
|
|
6941
|
+
menuButtonLabel.fg = colors.muted;
|
|
6942
|
+
renderer.requestRender();
|
|
6943
|
+
};
|
|
6674
6944
|
const statusMgr = new StatusManager((text) => {
|
|
6675
6945
|
statusBar.content = ` ${text}`;
|
|
6676
6946
|
renderer.requestRender();
|
|
@@ -7264,6 +7534,158 @@ ${pack.description ?? ""}`;
|
|
|
7264
7534
|
if (repo) openUrl(repo.url);
|
|
7265
7535
|
}
|
|
7266
7536
|
});
|
|
7537
|
+
attachClickToSelect(renderer, resultsSelect, {
|
|
7538
|
+
keepFocus: true,
|
|
7539
|
+
onOpen: () => resultsSelect.selectCurrent()
|
|
7540
|
+
});
|
|
7541
|
+
function activateOverlaySelection() {
|
|
7542
|
+
switch (currentOverlay) {
|
|
7543
|
+
case "history": {
|
|
7544
|
+
const sel = historySelect.getSelectedOption();
|
|
7545
|
+
if (sel?.value) {
|
|
7546
|
+
const entry = sel.value.entry;
|
|
7547
|
+
showOverlay("none");
|
|
7548
|
+
if (!entry) return;
|
|
7549
|
+
if (entry.mode === "trending") {
|
|
7550
|
+
if (entry.tab)
|
|
7551
|
+
trendingTab = entry.tab;
|
|
7552
|
+
loadTrending();
|
|
7553
|
+
} else {
|
|
7554
|
+
searchInput.value = entry.query;
|
|
7555
|
+
showSearchMode();
|
|
7556
|
+
doSearch(entry.query);
|
|
7557
|
+
}
|
|
7558
|
+
}
|
|
7559
|
+
return;
|
|
7560
|
+
}
|
|
7561
|
+
case "bookmarks": {
|
|
7562
|
+
const sel = bookmarksSelect.getSelectedOption();
|
|
7563
|
+
if (sel?.value)
|
|
7564
|
+
openUrl(sel.value.repo?.url ?? "");
|
|
7565
|
+
return;
|
|
7566
|
+
}
|
|
7567
|
+
case "saved": {
|
|
7568
|
+
const sel = savedSelect.getSelectedOption();
|
|
7569
|
+
if (sel?.value) {
|
|
7570
|
+
const s = sel.value;
|
|
7571
|
+
showOverlay("none");
|
|
7572
|
+
touchSavedSearch(s.name);
|
|
7573
|
+
if (s.mode === "trending") {
|
|
7574
|
+
if (s.tab) trendingTab = s.tab;
|
|
7575
|
+
loadTrending();
|
|
7576
|
+
} else {
|
|
7577
|
+
searchInput.value = s.query;
|
|
7578
|
+
showSearchMode();
|
|
7579
|
+
currentSort = s.sort;
|
|
7580
|
+
currentLimit = s.limit;
|
|
7581
|
+
setToolbar();
|
|
7582
|
+
doSearch(s.query);
|
|
7583
|
+
}
|
|
7584
|
+
}
|
|
7585
|
+
return;
|
|
7586
|
+
}
|
|
7587
|
+
case "topics": {
|
|
7588
|
+
const sel = topicsSelect.getSelectedOption();
|
|
7589
|
+
if (sel?.value) {
|
|
7590
|
+
const topic = sel.value;
|
|
7591
|
+
showOverlay("none");
|
|
7592
|
+
searchInput.value = `topic:${topic.name ?? ""}`;
|
|
7593
|
+
showSearchMode();
|
|
7594
|
+
doSearch(`topic:${topic.name}`);
|
|
7595
|
+
}
|
|
7596
|
+
return;
|
|
7597
|
+
}
|
|
7598
|
+
case "export": {
|
|
7599
|
+
const sel = exportSelect.getSelectedOption();
|
|
7600
|
+
if (sel?.value && currentRepos.length > 0) {
|
|
7601
|
+
const format2 = sel.value;
|
|
7602
|
+
const path = exportToFile(currentRepos, format2);
|
|
7603
|
+
showOverlay("none");
|
|
7604
|
+
setStatus(`\u2713 Exported to ${path}`);
|
|
7605
|
+
} else {
|
|
7606
|
+
setStatus("No results to export");
|
|
7607
|
+
showOverlay("none");
|
|
7608
|
+
}
|
|
7609
|
+
renderer.requestRender();
|
|
7610
|
+
return;
|
|
7611
|
+
}
|
|
7612
|
+
case "share": {
|
|
7613
|
+
const sel = shareSelect.getSelectedOption();
|
|
7614
|
+
if (sel?.value) {
|
|
7615
|
+
const opt = resultsSelect.getSelectedOption();
|
|
7616
|
+
const repo = opt?.value;
|
|
7617
|
+
if (repo) {
|
|
7618
|
+
const text = formatShare(repo, sel.value);
|
|
7619
|
+
copyToClipboard(text).then((ok) => {
|
|
7620
|
+
showOverlay("none");
|
|
7621
|
+
setStatus(ok ? "\u2713 Copied!" : "Clipboard not available");
|
|
7622
|
+
});
|
|
7623
|
+
}
|
|
7624
|
+
}
|
|
7625
|
+
renderer.requestRender();
|
|
7626
|
+
return;
|
|
7627
|
+
}
|
|
7628
|
+
case "help": {
|
|
7629
|
+
showOverlay("none");
|
|
7630
|
+
renderer.requestRender();
|
|
7631
|
+
return;
|
|
7632
|
+
}
|
|
7633
|
+
default:
|
|
7634
|
+
return;
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
function attachOverlayMouse(box, select) {
|
|
7638
|
+
attachClickToSelect(renderer, select, {
|
|
7639
|
+
onOpen: () => activateOverlaySelection(),
|
|
7640
|
+
onClickMiss: () => {
|
|
7641
|
+
showOverlay("none");
|
|
7642
|
+
renderer.requestRender();
|
|
7643
|
+
}
|
|
7644
|
+
});
|
|
7645
|
+
attachClickOutside(box, () => {
|
|
7646
|
+
showOverlay("none");
|
|
7647
|
+
renderer.requestRender();
|
|
7648
|
+
});
|
|
7649
|
+
}
|
|
7650
|
+
attachOverlayMouse(historyBox, historySelect);
|
|
7651
|
+
attachOverlayMouse(bookmarksBox, bookmarksSelect);
|
|
7652
|
+
attachOverlayMouse(savedBox, savedSelect);
|
|
7653
|
+
attachOverlayMouse(topicsBox, topicsSelect);
|
|
7654
|
+
attachOverlayMouse(exportBox, exportSelect);
|
|
7655
|
+
attachOverlayMouse(shareBox, shareSelect);
|
|
7656
|
+
for (const panel of [helpBox, orgBox, readmeBox, compareBox, notifsBox]) {
|
|
7657
|
+
attachClickOutside(panel, () => {
|
|
7658
|
+
showOverlay("none");
|
|
7659
|
+
renderer.requestRender();
|
|
7660
|
+
});
|
|
7661
|
+
}
|
|
7662
|
+
for (const scroller of [helpScroll, orgScroll, readmeScroll, updateScroll]) {
|
|
7663
|
+
scroller.onMouseScroll = (event) => {
|
|
7664
|
+
event.stopPropagation();
|
|
7665
|
+
};
|
|
7666
|
+
}
|
|
7667
|
+
attachClickToSelect(renderer, leaderSelect, {
|
|
7668
|
+
onOpen: () => {
|
|
7669
|
+
const entry = leaderSelect.getSelectedOption()?.value;
|
|
7670
|
+
if (!entry) return;
|
|
7671
|
+
if (entry.type === "category") {
|
|
7672
|
+
pushMenuLevel(` Menu > ${entry.name}`, entry.name, entry.children, 0);
|
|
7673
|
+
} else {
|
|
7674
|
+
resetMenu();
|
|
7675
|
+
showOverlay("none");
|
|
7676
|
+
entry.action();
|
|
7677
|
+
}
|
|
7678
|
+
renderer.requestRender();
|
|
7679
|
+
},
|
|
7680
|
+
onClickMiss: () => {
|
|
7681
|
+
showOverlay("none");
|
|
7682
|
+
renderer.requestRender();
|
|
7683
|
+
}
|
|
7684
|
+
});
|
|
7685
|
+
attachClickOutside(leaderDim, () => {
|
|
7686
|
+
showOverlay("none");
|
|
7687
|
+
renderer.requestRender();
|
|
7688
|
+
});
|
|
7267
7689
|
renderer.keyInput.on("keypress", (key) => {
|
|
7268
7690
|
if (tokenPromptBox.visible) {
|
|
7269
7691
|
if (key.name === "escape") {
|
|
@@ -7357,21 +7779,7 @@ ${pack.description ?? ""}`;
|
|
|
7357
7779
|
return;
|
|
7358
7780
|
}
|
|
7359
7781
|
if (key.name === "enter" || key.name === "return") {
|
|
7360
|
-
|
|
7361
|
-
if (sel?.value) {
|
|
7362
|
-
const entry = sel.value.entry;
|
|
7363
|
-
showOverlay("none");
|
|
7364
|
-
if (!entry) return;
|
|
7365
|
-
if (entry.mode === "trending") {
|
|
7366
|
-
if (entry.tab)
|
|
7367
|
-
trendingTab = entry.tab;
|
|
7368
|
-
loadTrending();
|
|
7369
|
-
} else {
|
|
7370
|
-
searchInput.value = entry.query;
|
|
7371
|
-
showSearchMode();
|
|
7372
|
-
doSearch(entry.query);
|
|
7373
|
-
}
|
|
7374
|
-
}
|
|
7782
|
+
activateOverlaySelection();
|
|
7375
7783
|
return;
|
|
7376
7784
|
}
|
|
7377
7785
|
return;
|
|
@@ -7390,9 +7798,7 @@ ${pack.description ?? ""}`;
|
|
|
7390
7798
|
return;
|
|
7391
7799
|
}
|
|
7392
7800
|
if (key.name === "enter" || key.name === "return") {
|
|
7393
|
-
|
|
7394
|
-
if (sel?.value)
|
|
7395
|
-
openUrl(sel.value.repo?.url ?? "");
|
|
7801
|
+
activateOverlaySelection();
|
|
7396
7802
|
return;
|
|
7397
7803
|
}
|
|
7398
7804
|
return;
|
|
@@ -7409,54 +7815,21 @@ ${pack.description ?? ""}`;
|
|
|
7409
7815
|
return;
|
|
7410
7816
|
}
|
|
7411
7817
|
if (key.name === "enter" || key.name === "return") {
|
|
7412
|
-
|
|
7413
|
-
if (sel?.value) {
|
|
7414
|
-
const s = sel.value;
|
|
7415
|
-
showOverlay("none");
|
|
7416
|
-
touchSavedSearch(s.name);
|
|
7417
|
-
if (s.mode === "trending") {
|
|
7418
|
-
if (s.tab) trendingTab = s.tab;
|
|
7419
|
-
loadTrending();
|
|
7420
|
-
} else {
|
|
7421
|
-
searchInput.value = s.query;
|
|
7422
|
-
showSearchMode();
|
|
7423
|
-
currentSort = s.sort;
|
|
7424
|
-
currentLimit = s.limit;
|
|
7425
|
-
setToolbar();
|
|
7426
|
-
doSearch(s.query);
|
|
7427
|
-
}
|
|
7428
|
-
}
|
|
7818
|
+
activateOverlaySelection();
|
|
7429
7819
|
return;
|
|
7430
7820
|
}
|
|
7431
7821
|
return;
|
|
7432
7822
|
}
|
|
7433
7823
|
if (currentOverlay === "topics") {
|
|
7434
7824
|
if (key.name === "enter" || key.name === "return") {
|
|
7435
|
-
|
|
7436
|
-
if (sel?.value) {
|
|
7437
|
-
const topic = sel.value;
|
|
7438
|
-
showOverlay("none");
|
|
7439
|
-
searchInput.value = `topic:${topic.name ?? ""}`;
|
|
7440
|
-
showSearchMode();
|
|
7441
|
-
doSearch(`topic:${topic.name}`);
|
|
7442
|
-
}
|
|
7825
|
+
activateOverlaySelection();
|
|
7443
7826
|
return;
|
|
7444
7827
|
}
|
|
7445
7828
|
return;
|
|
7446
7829
|
}
|
|
7447
7830
|
if (currentOverlay === "export") {
|
|
7448
7831
|
if (key.name === "enter" || key.name === "return") {
|
|
7449
|
-
|
|
7450
|
-
if (sel?.value && currentRepos.length > 0) {
|
|
7451
|
-
const format2 = sel.value;
|
|
7452
|
-
const path = exportToFile(currentRepos, format2);
|
|
7453
|
-
showOverlay("none");
|
|
7454
|
-
setStatus(`\u2713 Exported to ${path}`);
|
|
7455
|
-
} else {
|
|
7456
|
-
setStatus("No results to export");
|
|
7457
|
-
showOverlay("none");
|
|
7458
|
-
}
|
|
7459
|
-
renderer.requestRender();
|
|
7832
|
+
activateOverlaySelection();
|
|
7460
7833
|
return;
|
|
7461
7834
|
}
|
|
7462
7835
|
return;
|
|
@@ -7485,26 +7858,13 @@ ${pack.description ?? ""}`;
|
|
|
7485
7858
|
}
|
|
7486
7859
|
if (currentOverlay === "share") {
|
|
7487
7860
|
if (key.name === "enter" || key.name === "return") {
|
|
7488
|
-
|
|
7489
|
-
if (sel?.value) {
|
|
7490
|
-
const opt = resultsSelect.getSelectedOption();
|
|
7491
|
-
const repo = opt?.value;
|
|
7492
|
-
if (repo) {
|
|
7493
|
-
const text = formatShare(repo, sel.value);
|
|
7494
|
-
copyToClipboard(text).then((ok) => {
|
|
7495
|
-
showOverlay("none");
|
|
7496
|
-
setStatus(ok ? "\u2713 Copied!" : "Clipboard not available");
|
|
7497
|
-
});
|
|
7498
|
-
}
|
|
7499
|
-
}
|
|
7500
|
-
renderer.requestRender();
|
|
7861
|
+
activateOverlaySelection();
|
|
7501
7862
|
return;
|
|
7502
7863
|
}
|
|
7503
7864
|
return;
|
|
7504
7865
|
}
|
|
7505
7866
|
if (currentOverlay === "help") {
|
|
7506
|
-
|
|
7507
|
-
renderer.requestRender();
|
|
7867
|
+
activateOverlaySelection();
|
|
7508
7868
|
return;
|
|
7509
7869
|
}
|
|
7510
7870
|
if (currentOverlay === "update") {
|
|
@@ -7529,29 +7889,7 @@ ${pack.description ?? ""}`;
|
|
|
7529
7889
|
return;
|
|
7530
7890
|
}
|
|
7531
7891
|
if (key.name === "enter" || key.name === "return") {
|
|
7532
|
-
|
|
7533
|
-
if (action === "now") {
|
|
7534
|
-
showOverlay("none");
|
|
7535
|
-
recordPreUpdateState(cachedVersion ?? "");
|
|
7536
|
-
performUpdate().then((ok) => {
|
|
7537
|
-
if (ok) {
|
|
7538
|
-
setStatus("\u2713 Update complete \u2014 restart ghfind");
|
|
7539
|
-
} else {
|
|
7540
|
-
setStatus("\u2717 Update failed \u2014 check terminal output");
|
|
7541
|
-
}
|
|
7542
|
-
}).catch(() => {
|
|
7543
|
-
setStatus("\u2717 Update failed \u2014 check terminal output");
|
|
7544
|
-
});
|
|
7545
|
-
} else if (action === "never") {
|
|
7546
|
-
suppressUpdateNotices();
|
|
7547
|
-
showOverlay("none");
|
|
7548
|
-
setStatus("Update notices suppressed");
|
|
7549
|
-
} else {
|
|
7550
|
-
snoozeUpdateNotices(3);
|
|
7551
|
-
showOverlay("none");
|
|
7552
|
-
setStatus("Update reminder snoozed for 3 days");
|
|
7553
|
-
}
|
|
7554
|
-
renderer.requestRender();
|
|
7892
|
+
runUpdateOption(updateSelectedOption);
|
|
7555
7893
|
return;
|
|
7556
7894
|
}
|
|
7557
7895
|
return;
|
|
@@ -7574,8 +7912,14 @@ ${pack.description ?? ""}`;
|
|
|
7574
7912
|
toggleGraph();
|
|
7575
7913
|
return;
|
|
7576
7914
|
}
|
|
7577
|
-
if (key.name === "
|
|
7578
|
-
|
|
7915
|
+
if (key.name === "escape") {
|
|
7916
|
+
if (currentOverlay !== "none") {
|
|
7917
|
+
showOverlay("none");
|
|
7918
|
+
setToolbar();
|
|
7919
|
+
} else {
|
|
7920
|
+
showLeaderMenu();
|
|
7921
|
+
}
|
|
7922
|
+
renderer.requestRender();
|
|
7579
7923
|
return;
|
|
7580
7924
|
}
|
|
7581
7925
|
if (!searchInput.focused && errorHint) {
|