Implement convert and while + file-based editing
This commit is contained in:
50
src/index.ts
50
src/index.ts
@@ -6,21 +6,26 @@ import {Parser} from "./vm/parser.js";
|
||||
import {commands} from "./vm/commands/index.js";
|
||||
import {Executor} from "./vm/vm.js";
|
||||
import {ConsoleDisplay, OutputManager, WlClipboard} from "./vm/output.js";
|
||||
import {processPath} from "./vm/commands/command.js";
|
||||
import {processPath, unwrapString} from "./vm/commands/command.js";
|
||||
import * as fs from "node:fs";
|
||||
|
||||
;(async () => {
|
||||
const lifecycle = new Lifecycle()
|
||||
|
||||
// Setup the input reader & logging:
|
||||
const input = new Input()
|
||||
input.adoptLifecycle(lifecycle)
|
||||
input.subscribe(line => log.verbose('input', { line }))
|
||||
|
||||
// Chain on the lexer:
|
||||
const lexer = new Lexer(input)
|
||||
lexer.subscribe(token => log.verbose('token', token))
|
||||
|
||||
// Chain on the parser:
|
||||
const parser = new Parser(commands, lexer)
|
||||
parser.subscribe(exec => log.verbose('exec', exec))
|
||||
|
||||
// Chain on the VM executor:
|
||||
const output: OutputManager = {
|
||||
display: new ConsoleDisplay,
|
||||
clipboard: new WlClipboard,
|
||||
@@ -29,10 +34,12 @@ import * as fs from "node:fs";
|
||||
const exec = new Executor(output, parser, input)
|
||||
exec.adoptLifecycle(lifecycle)
|
||||
|
||||
// A little bit of window dressing:
|
||||
console.log('`str` : An interactive string manipulation environment')
|
||||
console.log('Copyright (C) 2026 Garrett Mills <shout@garrettmills.dev>')
|
||||
console.log('')
|
||||
|
||||
// If the user has an rc-file, execute it:
|
||||
const rcFile = processPath('~/.str.rc')
|
||||
if ( fs.existsSync(rcFile) ) {
|
||||
log.verbose('rc', { rcFile })
|
||||
@@ -43,8 +50,49 @@ import * as fs from "node:fs";
|
||||
console.log('Successfully loaded ~/.str.rc\n')
|
||||
}
|
||||
|
||||
// If the user specified a filepath, load it as the initial subject:
|
||||
const editingFile: string|undefined = process.argv[2]
|
||||
if ( editingFile ) {
|
||||
log.debug('rc', { editingFile })
|
||||
if ( !fs.existsSync(editingFile) ) {
|
||||
log.error('rc', 'Could not open file: ' + editingFile)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const editingFileContent = fs.readFileSync(editingFile).toString()
|
||||
log.info('rc', 'Read file: ' + editingFile)
|
||||
log.verbose('rc', { editingFileContent })
|
||||
await exec.tapVM(async vm => {
|
||||
await vm.replaceContextMatchingTerm({
|
||||
override: editingFileContent,
|
||||
})
|
||||
|
||||
await vm.outputSubject()
|
||||
})
|
||||
}
|
||||
|
||||
// Print the subject after each command:
|
||||
exec.subscribe(state => state.outputSubject())
|
||||
|
||||
// Start the prompt:
|
||||
input.setupPrompt()
|
||||
|
||||
// If we were editing a file, save the contents on close:
|
||||
lifecycle.onClose(async () => {
|
||||
log.debug('rc', { cleanupAndExit: true, editingFile })
|
||||
if ( editingFile ) {
|
||||
await exec.tapVM(vm =>
|
||||
vm.tapInPlace(ctx => {
|
||||
const editingFileOutputContent = unwrapString(ctx.getSubject())
|
||||
log.verbose('rc', { editingFileOutputContent })
|
||||
fs.writeFileSync(editingFile, editingFileOutputContent)
|
||||
log.info('rc', 'Wrote file: ' + editingFile)
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
process.on('SIGINT', () => lifecycle.close())
|
||||
process.on('SIGTERM', () => lifecycle.close())
|
||||
process.on('SIGQUIT', () => lifecycle.close())
|
||||
})()
|
||||
|
||||
Reference in New Issue
Block a user