Skip to content

Commit 9737166

Browse files
committed
✨ Initial implementation
Implements `queryTerminal` function based on my original script. Includes a manual (self-run) test case.
1 parent 2e0aaa6 commit 9737166

File tree

4 files changed

+95
-0
lines changed

4 files changed

+95
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
> Query for terminfo capabilities using XTGETTCAP
44
5+
## Usage
6+
7+
```js
8+
import { queryTerminal } from "query-terminal";
9+
10+
const answer = await queryTerminal(`<some capability>`);
11+
console.log(answer);
12+
```
13+
514
## Context
615

716
The [supports-hyperlink] issue about [Kitty support][kitty-support] led me to

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
"url": "https://github.com/connorjs"
2020
},
2121
"main": "query-terminal.js",
22+
"exports": {
23+
".": "./query-terminal.js"
24+
},
2225
"type": "module",
2326
"repository": {
2427
"type": "git",

query-terminal.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Some constants for clarity
2+
const ESC = `\x1B`;
3+
const DCS = `${ESC}P`;
4+
const ST = `${ESC}\\`;
5+
const ONE = `1`.charCodeAt(0);
6+
const EQUALS = `=`.charCodeAt(0);
7+
8+
/**
9+
* Returns the DCS query string (XTGETTCAP). Only supports a single query.
10+
*
11+
* > Request Termcap/Terminfo String (XTGETTCAP)
12+
*
13+
* @param query {string} - The query to make.
14+
* @returns The encoded DCS query string
15+
* @see <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
16+
*/
17+
function dcsQuery(query) {
18+
const hex = Buffer.from(query, 'utf8').toString('hex');
19+
return `${DCS}+q${hex}${ST}`;
20+
}
21+
22+
/**
23+
* Returns the DCS answer (to the {@link dcsQuery}). (The part after the `=`.)
24+
*
25+
* > DCS 1 + r Pt ST for valid requests, adding to Pt an = , and
26+
* > the value of the corresponding string that xterm would send,
27+
* > or
28+
* > DCS 0 + r ST for invalid requests.
29+
*
30+
* @param response {Buffer} - The encoded DCS response.
31+
* @returns The answer for valid requests and `undefined` for invalid requests
32+
* @see <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html>
33+
*/
34+
function dcsAnswer(response) {
35+
const success = response[2];
36+
if (success !== ONE) {
37+
return undefined; // Invalid request
38+
}
39+
40+
const index = response.lastIndexOf(EQUALS);
41+
if (index < 0) {
42+
return undefined; // No `=` found, so invalid format
43+
}
44+
45+
const answer = response.subarray(index + 1, -1);
46+
// Answer is an ASCII (UTF-8) string of Hex characters
47+
return Buffer.from(answer.toString(), 'hex').toString();
48+
}
49+
50+
/**
51+
* Query the terminal for Termcap/Terminfo capabilities (XTGETTCAP).
52+
*
53+
* @param query {string} - The requested capability.
54+
* @returns The answer for valid requests and `undefined` for invalid requests
55+
*/
56+
export async function queryTerminal(query) {
57+
return new Promise(function (resolve, reject) {
58+
try {
59+
// Configure stdin to watch for the response
60+
/** @type {import('node:stream').Readable} */
61+
const stdin = process.stdin;
62+
stdin.setRawMode(true);
63+
stdin.resume(); // Listen
64+
stdin.on('data', (data) => {
65+
stdin.pause(); // Stop listening
66+
resolve(dcsAnswer(data));
67+
});
68+
69+
// XTGETTCAP means writing the DCS query to the terminal
70+
process.stdout.write(dcsQuery(query));
71+
72+
} catch (error) {
73+
reject(error);
74+
}
75+
});
76+
}

test/kitty-allow-hyperlinks.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { queryTerminal } from "query-terminal";
2+
3+
// Query for hyperlink specifically
4+
// https://sw.kovidgoyal.net/kitty/kittens/query_terminal/
5+
// https://github.com/kovidgoyal/kitty/blob/master/kittens/query_terminal/main.py
6+
const answer = await queryTerminal(`kitty-query-allow_hyperlinks`);
7+
console.log(answer);

0 commit comments

Comments
 (0)