571eb786 |
1 | import * as path from "path"; |
2 | import * as ffi from "ffi"; |
3 | import * as fs from "fs"; |
4 | |
5 | // IMPORTANT: choose one |
6 | const RL_LIB = "libreadline"; // NOTE: libreadline is GPL |
7 | //var RL_LIB = "libedit"; |
8 | |
9 | const HISTORY_FILE = path.join(process.env.HOME, ".mal-history"); |
10 | |
11 | const rllib = ffi.Library(RL_LIB, { |
12 | "readline": ["string", ["string"]], |
13 | "add_history": ["int", ["string"]], |
14 | }); |
15 | |
16 | let rlHistoryLoaded = false; |
17 | |
18 | export function readline(prompt?: string): string | null { |
19 | prompt = prompt || "user> "; |
20 | |
21 | if (!rlHistoryLoaded) { |
22 | rlHistoryLoaded = true; |
23 | let lines: string[] = []; |
24 | if (fs.existsSync(HISTORY_FILE)) { |
25 | lines = fs.readFileSync(HISTORY_FILE).toString().split("\n"); |
26 | } |
27 | // Max of 2000 lines |
28 | lines = lines.slice(Math.max(lines.length - 2000, 0)); |
29 | for (let i = 0; i < lines.length; i++) { |
30 | if (lines[i]) { rllib.add_history(lines[i]); } |
31 | } |
32 | } |
33 | |
34 | const line = rllib.readline(prompt); |
35 | if (line) { |
36 | rllib.add_history(line); |
37 | try { |
38 | fs.appendFileSync(HISTORY_FILE, line + "\n"); |
39 | } catch (exc) { |
40 | // ignored |
41 | } |
42 | } |
43 | |
44 | return line; |
45 | }; |