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 { ptr };
|
||||
export const getPointer = ptr;
|
||||
|
@ -2,10 +2,10 @@
|
||||
* The main entrypoint when using Bun as the runtime
|
||||
*/
|
||||
|
||||
import {Termios} from './termios'
|
||||
import { getTermios } from "../common/termios";
|
||||
|
||||
export async function main(): Promise<number> {
|
||||
const t = new Termios();
|
||||
const t = await getTermios();
|
||||
t.enableRawMode();
|
||||
|
||||
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) => {
|
||||
const runtime = getRuntime();
|
||||
const suffix = (runtime === RunTime.Deno) ? '.ts' : '';
|
||||
const suffix = '.ts';
|
||||
const base = `../${runtime}/`;
|
||||
|
||||
const pathParts = path.split('/')
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { importForRuntime } from "./index.ts";
|
||||
|
||||
export const STDIN_FILENO = 0;
|
||||
export const STOUT_FILENO = 1;
|
||||
export const TCSANOW = 0;
|
||||
@ -23,4 +25,89 @@ export interface ITermios {
|
||||
* Restores canonical mode
|
||||
*/
|
||||
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
|
||||
*/
|
||||
import { Termios } from './termios.ts'
|
||||
import {getTermios} from "../common/termios.ts";
|
||||
|
||||
export async function main(): Promise<number> {
|
||||
const t = new Termios();
|
||||
const t = await getTermios()
|
||||
t.enableRawMode();
|
||||
|
||||
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