Refactor raw mode handling
This commit is contained in:
parent
b30c4d40d6
commit
4a8047a6d4
@ -37,4 +37,4 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const { tcgetattr, tcsetattr, cfmakeraw } = cStdLib.symbols;
|
export const { tcgetattr, tcsetattr, cfmakeraw } = cStdLib.symbols;
|
||||||
export { ptr };
|
export const getPointer = ptr;
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
* The main entrypoint when using Bun as the runtime
|
* The main entrypoint when using Bun as the runtime
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Termios} from './termios'
|
import { getTermios } from "../common/termios";
|
||||||
|
|
||||||
export async function main(): Promise<number> {
|
export async function main(): Promise<number> {
|
||||||
const t = new Termios();
|
const t = await getTermios();
|
||||||
t.enableRawMode();
|
t.enableRawMode();
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
import { STDIN_FILENO, TCSANOW, ITermios, TERMIOS_SIZE } from "../common/termios";
|
|
||||||
import { cfmakeraw, tcgetattr, tcsetattr, ptr } from "./ffi";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation to toggle raw mode with Bun runtime
|
|
||||||
*/
|
|
||||||
export class Termios implements ITermios {
|
|
||||||
/**
|
|
||||||
* Are we in raw mode?
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#inRawMode:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The saved version of the termios struct for cooked/canonical mode
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#cookedTermios: Uint8Array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data for the termios struct we are manipulating
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#termios: Uint8Array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pointer to the termios struct
|
|
||||||
* @private // this.#ptr = ptr(this.#termios);
|
|
||||||
*/
|
|
||||||
#ptr: any;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.#inRawMode = false;
|
|
||||||
|
|
||||||
// These are the TypedArrays linked to the raw pointer data
|
|
||||||
this.#cookedTermios = new Uint8Array(TERMIOS_SIZE);
|
|
||||||
this.#termios = new Uint8Array(TERMIOS_SIZE);
|
|
||||||
|
|
||||||
// The current pointer for C
|
|
||||||
this.#ptr = ptr(this.#termios);
|
|
||||||
}
|
|
||||||
|
|
||||||
get inRawMode() {
|
|
||||||
return this.#inRawMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableRawMode() {
|
|
||||||
if (this.#inRawMode) {
|
|
||||||
throw new Error('Can not enable raw mode when in raw mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current termios settings
|
|
||||||
tcgetattr(STDIN_FILENO, this.#ptr);
|
|
||||||
|
|
||||||
// The #ptr property is pointing to the #termios TypedArray. As the pointer
|
|
||||||
// is manipulated, the TypedArray is as well. We will use this to save
|
|
||||||
// the original canonical/cooked terminal settings for disabling raw mode later.
|
|
||||||
this.#cookedTermios = new Uint8Array(this.#termios, 0, 60);
|
|
||||||
|
|
||||||
// Update termios struct with raw settings
|
|
||||||
cfmakeraw(this.#ptr);
|
|
||||||
|
|
||||||
// Actually set the new termios settings
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, this.#ptr);
|
|
||||||
this.#inRawMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
disableRawMode() {
|
|
||||||
// Don't even bother throwing an error if we try to disable raw mode
|
|
||||||
// and aren't in raw mode. It just doesn't really matter.
|
|
||||||
if (!this.#inRawMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldTermiosPtr = ptr(this.#cookedTermios);
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
|
||||||
|
|
||||||
this.#inRawMode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -30,7 +30,7 @@ export const getRuntime = (): RunTime => {
|
|||||||
*/
|
*/
|
||||||
export const importForRuntime = async (path: string) => {
|
export const importForRuntime = async (path: string) => {
|
||||||
const runtime = getRuntime();
|
const runtime = getRuntime();
|
||||||
const suffix = (runtime === RunTime.Deno) ? '.ts' : '';
|
const suffix = '.ts';
|
||||||
const base = `../${runtime}/`;
|
const base = `../${runtime}/`;
|
||||||
|
|
||||||
const pathParts = path.split('/')
|
const pathParts = path.split('/')
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { importForRuntime } from "./index.ts";
|
||||||
|
|
||||||
export const STDIN_FILENO = 0;
|
export const STDIN_FILENO = 0;
|
||||||
export const STOUT_FILENO = 1;
|
export const STOUT_FILENO = 1;
|
||||||
export const TCSANOW = 0;
|
export const TCSANOW = 0;
|
||||||
@ -24,3 +26,88 @@ export interface ITermios {
|
|||||||
*/
|
*/
|
||||||
disableRawMode(): void;
|
disableRawMode(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getTermios = async () => {
|
||||||
|
// Get the runtime-specific ffi wrappers
|
||||||
|
const { tcgetattr, tcsetattr, cfmakeraw, getPointer } = await importForRuntime('ffi');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation to toggle raw mode with Bun runtime
|
||||||
|
*/
|
||||||
|
class Termios implements ITermios {
|
||||||
|
/**
|
||||||
|
* Are we in raw mode?
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#inRawMode:boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The saved version of the termios struct for cooked/canonical mode
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
#cookedTermios: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data for the termios struct we are manipulating
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
readonly #termios: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pointer to the termios struct
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
readonly #ptr: any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.#inRawMode = false;
|
||||||
|
|
||||||
|
// These are the TypedArrays linked to the raw pointer data
|
||||||
|
this.#cookedTermios = new Uint8Array(TERMIOS_SIZE);
|
||||||
|
this.#termios = new Uint8Array(TERMIOS_SIZE);
|
||||||
|
|
||||||
|
// The current pointer for C
|
||||||
|
this.#ptr = getPointer(this.#termios);
|
||||||
|
}
|
||||||
|
|
||||||
|
get inRawMode() {
|
||||||
|
return this.#inRawMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
enableRawMode() {
|
||||||
|
if (this.#inRawMode) {
|
||||||
|
throw new Error('Can not enable raw mode when in raw mode');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current termios settings
|
||||||
|
tcgetattr(STDIN_FILENO, this.#ptr);
|
||||||
|
|
||||||
|
// The #ptr property is pointing to the #termios TypedArray. As the pointer
|
||||||
|
// is manipulated, the TypedArray is as well. We will use this to save
|
||||||
|
// the original canonical/cooked terminal settings for disabling raw mode later.
|
||||||
|
this.#cookedTermios = new Uint8Array(this.#termios, 0, 60);
|
||||||
|
|
||||||
|
// Update termios struct with raw settings
|
||||||
|
cfmakeraw(this.#ptr);
|
||||||
|
|
||||||
|
// Actually set the new termios settings
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, this.#ptr);
|
||||||
|
this.#inRawMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
disableRawMode() {
|
||||||
|
// Don't even bother throwing an error if we try to disable raw mode
|
||||||
|
// and aren't in raw mode. It just doesn't really matter.
|
||||||
|
if (!this.#inRawMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldTermiosPtr = getPointer(this.#cookedTermios);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
||||||
|
|
||||||
|
this.#inRawMode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Termios();
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* The main entrypoint when using Deno as the runtime
|
* The main entrypoint when using Deno as the runtime
|
||||||
*/
|
*/
|
||||||
import { Termios } from './termios.ts'
|
import {getTermios} from "../common/termios.ts";
|
||||||
|
|
||||||
export async function main(): Promise<number> {
|
export async function main(): Promise<number> {
|
||||||
const t = new Termios();
|
const t = await getTermios()
|
||||||
t.enableRawMode();
|
t.enableRawMode();
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
import { STDIN_FILENO, TCSANOW, ITermios, TERMIOS_SIZE } from "../common/termios.ts";
|
|
||||||
import { cfmakeraw, tcgetattr, tcsetattr, getPointer } from "./ffi.ts";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation to toggle raw mode with Deno runtime
|
|
||||||
*/
|
|
||||||
export class Termios implements ITermios {
|
|
||||||
/**
|
|
||||||
* Are we in raw mode?
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#inRawMode:boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The saved version of the termios struct for cooked/canonical mode
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#cookedTermios: Uint8Array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The data for the termios struct we are manipulating
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#termios: Uint8Array;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pointer to the termios struct
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
#ptr: any;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.#inRawMode = false;
|
|
||||||
|
|
||||||
// These are the TypedArrays linked to the raw pointer data
|
|
||||||
this.#cookedTermios = new Uint8Array(TERMIOS_SIZE);
|
|
||||||
this.#termios = new Uint8Array(TERMIOS_SIZE);
|
|
||||||
|
|
||||||
// The current pointer for C
|
|
||||||
this.#ptr = getPointer(this.#termios);
|
|
||||||
}
|
|
||||||
|
|
||||||
get inRawMode() {
|
|
||||||
return this.#inRawMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableRawMode() {
|
|
||||||
if (this.#inRawMode) {
|
|
||||||
throw new Error('Can not enable raw mode when in raw mode');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current termios settings
|
|
||||||
tcgetattr(STDIN_FILENO, this.#ptr);
|
|
||||||
|
|
||||||
// The #ptr property is pointing to the #termios TypedArray. As the pointer
|
|
||||||
// is manipulated, the TypedArray is as well. We will use this to save
|
|
||||||
// the original canonical/cooked terminal settings for disabling raw mode later.
|
|
||||||
this.#cookedTermios = new Uint8Array(this.#termios, 0, 60);
|
|
||||||
|
|
||||||
// Update termios struct with raw settings
|
|
||||||
cfmakeraw(this.#ptr);
|
|
||||||
|
|
||||||
// Actually set the new termios settings
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, this.#ptr);
|
|
||||||
this.#inRawMode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
disableRawMode() {
|
|
||||||
// Don't even bother throwing an error if we try to disable raw mode
|
|
||||||
// and aren't in raw mode. It just doesn't really matter.
|
|
||||||
if (!this.#inRawMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldTermiosPtr = getPointer(this.#cookedTermios);
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, oldTermiosPtr);
|
|
||||||
|
|
||||||
this.#inRawMode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user