Skip to content

Commit 2acb1a8

Browse files
pkg browse
1 parent 8d3c887 commit 2acb1a8

4 files changed

Lines changed: 165 additions & 5 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ollieos",
3-
"version": "1.1.3",
3+
"version": "1.1.4",
44
"description": "",
55
"private": true,
66
"main": "server.js",

src/programs/pkg/browse.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import {ANSI, NEWLINE} from "../../term_ctl";
2+
import type { WrappedTerminal } from "../../term_ctl";
3+
import { ProgramMainData } from "../../types"
4+
import {repo_query} from "./index";
5+
6+
// extract from ANSI to make code less verbose
7+
const { STYLE, FG, CURSOR } = ANSI;
8+
9+
const ROWS = 10;
10+
11+
const view_pkg_info = async (term: WrappedTerminal, pkg_name: string) => {
12+
const pkg_data = await repo_query.get_pkg_json(pkg_name);
13+
const pkg_versions = await repo_query.get_pkg_versions(pkg_name);
14+
15+
term.clear();
16+
17+
term.write(NEWLINE);
18+
term.writeln(`${STYLE.bold}${FG.cyan}${pkg_name}`);
19+
term.write(STYLE.dim);
20+
term.writeln("=".repeat(pkg_name.length));
21+
term.writeln(STYLE.reset_all);
22+
23+
term.write(NEWLINE);
24+
term.writeln("Available versions:");
25+
for (const version of pkg_versions) {
26+
term.writeln(` - ${version}`);
27+
}
28+
term.write(NEWLINE);
29+
term.writeln(`Description: ${pkg_data.description || "No description provided."}`);
30+
term.writeln(`Author: ${pkg_data.author || "Unknown"}`);
31+
term.writeln(`License: ${pkg_data.license || "Unknown"}`);
32+
term.write(NEWLINE);
33+
34+
term.writeln(`${STYLE.dim}Press any key to return to the list...${STYLE.reset_all}`);
35+
36+
await term.wait_for_keypress();
37+
}
38+
39+
// TODO: accept name argument to jump to specific package
40+
41+
export const browse_subcommand = async (data: ProgramMainData) => {
42+
// extract from data to make code less verbose
43+
const { args, term } = data;
44+
45+
// remove subcommand name
46+
args.shift();
47+
48+
const provided = await repo_query.get_provided_list();
49+
50+
let offset = 0;
51+
let selected_index = 0;
52+
const draw = () => {
53+
term.clear();
54+
55+
term.write(NEWLINE);
56+
term.writeln("(use up/down arrow keys to scroll, enter to show more info, q to quit)");
57+
term.write(NEWLINE);
58+
term.write(CURSOR.invisible);
59+
60+
// show ... if there are more items above
61+
if (offset > 0) {
62+
term.writeln(` ${STYLE.dim}...${STYLE.reset_all}`);
63+
} else {
64+
term.write(NEWLINE);
65+
}
66+
67+
const slice = provided.slice(offset, offset + ROWS);
68+
for (const [index, name] of slice.entries()) {
69+
if (offset + index === selected_index) {
70+
term.writeln(`${FG.cyan}${STYLE.dim}> ${STYLE.no_bold_or_dim}${STYLE.bold}${name}${STYLE.reset_all}`);
71+
} else {
72+
term.writeln(` ${name}`);
73+
}
74+
}
75+
76+
// show ... if there are more items below
77+
if (offset + ROWS < provided.length) {
78+
term.writeln(` ${STYLE.dim}...${STYLE.reset_all}`);
79+
} else {
80+
term.write(NEWLINE);
81+
}
82+
}
83+
84+
// TODO: type to filter
85+
86+
let quit = false;
87+
while (!quit) {
88+
draw();
89+
90+
const key = await term.wait_for_keypress();
91+
console.log(key);
92+
switch (key.domEvent.key) {
93+
case "q":
94+
quit = true;
95+
break;
96+
case "ArrowUp":
97+
if (selected_index > 0) {
98+
selected_index--;
99+
if (selected_index < offset) {
100+
offset--;
101+
}
102+
}
103+
break;
104+
case "ArrowDown":
105+
if (selected_index < provided.length - 1) {
106+
selected_index++;
107+
if (selected_index >= offset + ROWS) {
108+
offset++;
109+
}
110+
}
111+
break;
112+
case "Enter": {
113+
const pkg_name = provided[selected_index];
114+
await view_pkg_info(term, pkg_name);
115+
break;
116+
}
117+
}
118+
}
119+
120+
term.write(CURSOR.visible);
121+
return 0;
122+
}

src/programs/pkg/index.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {Program} from "../../types";
66
import type {AbstractFileSystem} from "../../filesystem";
77
import {list_subcommand} from "./list";
88
import {info_subcommand} from "./info";
9+
import {browse_subcommand} from "./browse";
910

1011

1112
const REPO_URL = "https://ollieg.codes/pkg_repo";
@@ -133,6 +134,44 @@ export const repo_query = {
133134
}
134135

135136
return await response.text();
137+
},
138+
139+
get_provided_list: async () => {
140+
// repo/provided.txt
141+
const url = append_url_pathnames(repo_url_obj, ["provided.txt"]);
142+
143+
const response = await fetch(url.toString());
144+
if (!response.ok) {
145+
if (response.status === 404) {
146+
return null;
147+
}
148+
149+
throw new Error(`HTTP error! status: ${response.status}`);
150+
}
151+
152+
// newline separated list of provided package names
153+
const data = await response.text();
154+
return data.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
155+
},
156+
157+
get_pkg_versions: async (pkg: string) => {
158+
pkg = encodeURI(pkg);
159+
pkg = pkg.replace(/\./g, "%2E");
160+
161+
// repo/pkgs/pkg/versions.txt
162+
const url = append_url_pathnames(repo_url_obj, ["pkgs", pkg, "versions.txt"]);
163+
const response = await fetch(url.toString());
164+
if (!response.ok) {
165+
if (response.status === 404) {
166+
return null;
167+
}
168+
169+
throw new Error(`HTTP error! status: ${response.status}`);
170+
}
171+
172+
// newline separated list of versions
173+
const data = await response.text();
174+
return data.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
136175
}
137176
}
138177

@@ -461,8 +500,7 @@ export default {
461500
term.writeln(`${PREFABS.error}Not implemented yet.${STYLE.reset_all}`);
462501
break;
463502
case "browse":
464-
term.writeln(`${PREFABS.error}Not implemented yet.${STYLE.reset_all}`);
465-
break;
503+
return await browse_subcommand(data);
466504
case "clean":
467505
term.writeln(`${PREFABS.error}Not implemented yet.${STYLE.reset_all}`);
468506
break;

0 commit comments

Comments
 (0)