Move player.stdio

This commit is contained in:
He4eT 2021-02-24 17:56:55 +05:00
commit b9e4269aa4
4 changed files with 6 additions and 5 deletions

62
bin/player.stdio.js Normal file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env node
/**
* @see: https://github.com/curiousdannii/emglken/blob/master/bin/emglken.js
*/
const fs = require('fs')
const minimist = require('minimist')
const CheapGlkOte = require('../src/')
const { handlers } = require('./stdio')
const formats = [
{
id: 'bocfel',
extensions: /z([3458]|blorb)$/,
engine: 'bocfel.js',
},
{
id: 'glulxe',
extensions: /(gblorb|ulx)$/,
engine: 'glulxe.js',
},
{
id: 'git',
extensions: /(gblorb|ulx)$/,
engine: 'git.js',
},
{
id: 'hugo',
extensions: /hex$/,
engine: 'hugo.js',
},
{
id: 'tads',
extensions: /(gam|t3)$/,
engine: 'tads.js',
}
]
const argv = minimist(process.argv.slice(2))
const storyfile = argv._[0]
const format = formats.find(x =>
x.extensions.test(storyfile))
if (!format) {
console.error('Unknown storyfile format.')
process.exit(0)
}
const { glkInterface, sendFn } = CheapGlkOte(handlers)
handlers.setSend(sendFn)
const engine = require('emglken/src/' + format.engine)
const vm = new engine()
vm.prepare(
fs.readFileSync(storyfile),
glkInterface)
vm.start()

145
bin/stdio.js Normal file
View file

@ -0,0 +1,145 @@
/**
* @see: https://github.com/curiousdannii/glkote-term/blob/master/src/glkote-dumb.js
*/
const readline = require('readline')
const MuteStream = require('mute-stream')
const ansiEscapes = require('ansi-escapes')
const stdin = process.stdin
const stdout = new MuteStream()
stdout.pipe(process.stdout)
const rl = readline.createInterface({
input: stdin,
output: stdout,
prompt: ''
})
let send = _ => _
const setSend = fn => {
send = fn
}
const onInit = () => {
if (stdin.isTTY) {
stdin.setRawMode(true)
}
readline.emitKeypressEvents(stdin)
rl.resume()
}
const onUpdateContent = messages =>
messages.text.forEach(({ append, content }) => {
if (!append) {
stdout.write('\n')
}
if (content) {
content.forEach(x => {
if (x.text === '>') return null
if (x.style === 'input') {
if (stdout.isTTY) {
stdout.write(ansiEscapes.eraseLines(2))
stdout.write('> ')
}
}
stdout.write(
typeof x === 'string'
? x
: x.text)
})
}
})
const onUpdateInputs = type => {
type
? attach_handlers(type)
: detach_handlers()
}
const onExit = () => {
detach_handlers()
rl.close()
stdout.write('\n')
}
const onDisable = disable =>
disable
? detach_handlers()
: attach_handlers()
const onFileNameRequest = (tosave, usage, gameid, callback) => {
stdout.write('\n')
rl.question(
'Please enter a file name: ',
filename => callback(filename
? { filename, usage }
: null))
}
const onFileRead = (dirent, israw) =>
void console.log('onFileRead:', dirent)
const onFileWrite = (dirent, content, israw) =>
void console.log('onFileWrite:', dirent, content.length)
const handle_char_input = (str, key) => {
const key_replacements = {
'\x7F': 'delete',
'\t': 'tab',
}
detach_handlers()
// Make sure this char isn't being remembered for the next line input
rl._line_buffer = null
rl.line = ''
// Process special keys
const res =
key_replacements[str] ||
str ||
key.name.replace(/f(\d+)/, 'func$1')
send(res)
}
const attach_handlers = type => {
if (type === 'char') {
stdout.mute()
stdin.on('keypress', handle_char_input)
}
if (type === 'line') {
rl.on('line', handle_line_input)
}
}
const detach_handlers = () => {
stdin.removeListener('keypress', handle_char_input)
rl.removeListener('line', handle_line_input)
stdout.unmute()
}
const handle_line_input = line => {
if (stdout.isTTY) {
stdout.write(ansiEscapes.eraseLines(1))
}
detach_handlers()
send(line)
}
module.exports.handlers = {
onInit,
onUpdateContent,
onDisable,
onUpdateInputs,
onFileNameRequest,
onFileRead,
onFileWrite,
onExit,
setSend
}