2025-04-01 21:52:04 +00:00

163 lines
3.2 KiB
JavaScript
Executable File

export default class RELP {
constructor(handlers) {
this.handlers = handlers
this.initCommandLine()
}
initCommandLine() {
// Configure line-by-line input mode
process.stdin.setEncoding("utf8")
process.stdin.resume()
process.stdin.setRawMode(true)
// Buffer to store user input
this.inputBuffer = ""
// Show initial prompt
this.showPrompt()
// Handle user input
process.stdin.on("data", (data) => {
const key = data.toString()
// Ctrl+C to exit
if (key === "\u0003") {
process.exit(0)
}
// Enter key
if (key === "\r" || key === "\n") {
// Move to a new line
console.log()
// Process the command
const command = this.inputBuffer.trim()
if (command) {
this.processCommand(command)
}
// Clear the buffer
this.inputBuffer = ""
// Show the prompt again
this.showPrompt()
return
}
// Backspace/Delete
if (key === "\b" || key === "\x7f") {
if (this.inputBuffer.length > 0) {
// Delete a character from the buffer
this.inputBuffer = this.inputBuffer.slice(0, -1)
// Update the line in the terminal
process.stdout.write("\r\x1b[K> " + this.inputBuffer)
}
return
}
// Normal characters
if (key.length === 1 && key >= " ") {
this.inputBuffer += key
process.stdout.write(key)
}
})
// Intercept console.log to keep the prompt visible
const originalConsoleLog = console.log
console.log = (...args) => {
// Clear the current line
process.stdout.write("\r\x1b[K")
// Print the message
originalConsoleLog(...args)
// Reprint the prompt and current buffer
this.showPrompt(false)
}
// Do the same with console.error
const originalConsoleError = console.error
console.error = (...args) => {
// Clear the current line
process.stdout.write("\r\x1b[K")
// Print the error message
originalConsoleError(...args)
// Reprint the prompt and current buffer
this.showPrompt(false)
}
}
showPrompt(newLine = true) {
if (newLine) {
process.stdout.write("\r")
}
process.stdout.write("> " + this.inputBuffer)
}
processCommand(input) {
const inputs = input.split(" ")
const command = inputs[0]
const args = inputs.slice(1)
this.inputBuffer = ""
const commandFn = this.commands.find((relpCommand) => {
if (relpCommand.cmd === command) {
return true
}
if (Array.isArray(relpCommand.aliases)) {
return relpCommand.aliases.includes(command)
}
return false
})
if (!commandFn) {
console.error(`Command not found: ${command}`)
return
}
// Adapter to maintain compatibility with the original API
const callback = (result) => {
if (result) {
console.log(result)
}
}
try {
commandFn.fn(callback, ...args)
} catch (error) {
console.error(`Error executing command: ${error.message}`)
}
}
commands = [
{
cmd: "select",
aliases: ["s", "sel"],
fn: (cb, service) => {
this.handlers.detachAllServicesSTD()
return this.handlers.attachServiceSTD(service)
},
},
{
cmd: "reload",
aliases: ["r"],
fn: () => {
this.handlers.reloadService()
},
},
{
cmd: "exit",
aliases: ["e"],
fn: () => {
process.exit(0)
},
},
]
}