Re: Custom Scrollabe Text File Viewer
By: Codefenix to Digital Man on Wed Nov 06 2024 09:38 am
script load the file into memory in chunks (how printfile() works by
default).
That's interesting. Like just use the frame object as a kind of viewport for the lines I want to display, and use the up/down/etc to control which range of lines come into view. Seems very doable. Thanks for the thought.
Ok, this version does exactly that. It still reads the entire file into memory, but it only writes a screen's worth of text to the frame at a time. Now it's much faster and has handled everything I've thrown at it. The largest file I tried was 1,599 KB, and it handled it with ease. I don't personally plan on displaying files higher than the megabyte teritory, at least not currently. I also ditched the scrollbar in favor of a simple percentage indicator in the bottom right. Other than that, it works basically like the one I demo'd earlier.
If I keep working on this, I might try to add a CTRL+F option for finding text, but probably not much else. For now it suits my needs just fine.
// viewfile.js ============================================= start //
load("sbbsdefs.js");
load("frame.js");
load("attr_conv.js");
const OPTIONS = " " + ascii(24) + " / " + ascii(25) +
" / pg-up / pg-dn / home / end / q: quit";
function init_display() {
const w = console.screen_columns;
const h = console.screen_rows;
const f = { top: new Frame(1, 1, w, h, BG_BLACK|LIGHTGRAY) };
f.topbar = new Frame(1, 1, w, 1, BG_LIGHTGRAY|BLACK, f.top);
f.output = new Frame(1, 2, w, h - 2, BG_BLACK|LIGHTGRAY, f.top);
f.bottombar = new Frame(1, h, w, 1, BG_LIGHTGRAY|BLACK, f.top);
f.output.word_wrap = true;
f.bottombar.putmsg(OPTIONS);
f.top.open();
return f;
}
function get_lines_for_screen (lines, start, end) {
var viewport = [];
for (var i = start; i < end; i++) {
viewport.push(lines[i]);
}
return "\n" + viewport.join("\n") + "\n";
}
function viewfile(file_name, file_title, start_at_top) {
var title = file_title ? file_title : file_getname(file_name);
var exit_viewer = false;
var key_pressed;
var line_index;
var file_lines = [];
var max_lines;
var move_viewport = false;
const frames = init_display();
if (file_exists(file_name)) {
log(LOG_INFO, "Loading " + title);
frames.topbar.putmsg("Loading " + title.substr(0, 65) + "...");
frames.top.cycle();
var txt = new File(file_name);
if (txt.open("r")) {
file_lines = convertAttrsToSyncPerSysCfg(txt.read()
).replace(/\f/g, "").split(/\r?\n/);
txt.close();
}
max_lines = file_lines.length - frames.output.height;
line_index = start_at_top ? 0 : max_lines;
frames.output.putmsg( get_lines_for_screen(file_lines, line_index,
line_index + frames.output.height) );
frames.output.scrollTo(0, 1); // WHY???
frames.bottombar.gotoxy( frames.bottombar.width-10, 1);
frames.bottombar.putmsg( format( "[%.3d%%]",
Math.round((line_index / max_lines) * 100)) );
log(LOG_INFO, "Done loading: " + title);
frames.topbar.clear();
frames.topbar.putmsg("Viewing: " + title.substr(0, 70));
frames.top.cycle();
while (!js.terminated && !exit_viewer) {
switch (console.inkey(K_NONE, 5).toUpperCase()) {
case KEY_UP:
line_index = line_index - 1;
move_viewport = true;
break;
case KEY_DOWN:
line_index = line_index + 1;
move_viewport = true;
break;
case KEY_PAGEUP:
line_index = line_index - frames.output.height;
move_viewport = true;
break;
case KEY_PAGEDN:
line_index = line_index + frames.output.height;
move_viewport = true;
break;
case KEY_HOME:
line_index = 0;
move_viewport = true;
break;
case KEY_END:
line_index = max_lines;
move_viewport = true;
break;
case KEY_ESC:
case "Q":
exit_viewer = true;
break;
}
if (move_viewport) {
if (line_index < 0) {
line_index = 0;
}
if (line_index > max_lines) {
line_index = max_lines;
}
frames.output.clear();
frames.output.putmsg( get_lines_for_screen(file_lines,
line_index, line_index + frames.output.height) );
frames.output.scrollTo(0, 1); // WHY???
frames.output.cycle();
frames.bottombar.gotoxy( frames.bottombar.width-10, 1);
frames.bottombar.putmsg( format( "[%.3d%%]",
Math.round((line_index / max_lines) * 100)) );
frames.bottombar.cycle();
move_viewport = false;
}
}
frames.top.close();
print("\x01q\x01l\x01n"); // resets the screen
} else {
log(LOG_ERROR, "File not found: " + file_name);
}
}
function main(file_name, file_title, scroll_to_top) {
viewfile(file_name, file_title, scroll_to_top);
}
// 1: file path (string)
// 2: title (string; defaults to filename)
// 3: start at top (boolean; default is false)
main(argv[0], argv[1], argv[2]);
// viewfile.js ============================================= end //
|15 ■ ∙ · codefenix · ∙ · ConstructiveChaos BBS · · ∙ ■ ■
|08 ■ ■ ∙ (https/telnet/ssh)://conchaos.synchro.net · ∙ ■
|07
...Everybody should believe in something: I believe I'll have another drink. ---
■ Synchronet ■ -=[ ConstructiveChaos BBS | conchaos.synchro.net ]=-