Skip to content

Commit f66afa1

Browse files
authored
feat: Shell adapter takes over log formatting and outputs it like it … (#1786)
* feat: Shell adapter takes over log formatting and outputs it like it does other messages, prefixed with [loglevel]. * fix: Having to hit enter to get the Shell adapter prompt to show up when Hubot starts
1 parent 8aa513a commit f66afa1

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/adapters/Shell.mjs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict'
22

3-
import fs from 'node:fs'
4-
import { stat, writeFile, unlink } from 'node:fs/promises'
3+
import { stat, writeFile, unlink, appendFile, readFile } from 'node:fs/promises'
54
import readline from 'node:readline'
65
import Adapter from '../Adapter.mjs'
76
import { TextMessage } from '../Message.mjs'
@@ -23,15 +22,37 @@ const showHelp = () => {
2322
}
2423

2524
const bold = str => `\x1b[1m${str}\x1b[22m`
25+
const green = str => `\x1b[32m${str}\x1b[0m`
26+
const levelColors = {
27+
error: '\x1b[31m',
28+
warn: '\x1b[33m',
29+
debug: '\x1b[35m',
30+
info: '\x1b[34m',
31+
trace: '\x1b[36m',
32+
fatal: '\x1b[91m'
33+
}
34+
const reset = '\x1b[0m'
2635

2736
class Shell extends Adapter {
2837
#rl = null
2938
constructor (robot) {
3039
super(robot)
3140
this.name = 'Shell'
41+
const levels = ['trace', 'debug', 'info', 'warn', 'error', 'fatal']
42+
levels.forEach(level => {
43+
robot.logger[level] = async (...args) => {
44+
const color = levelColors[level] || ''
45+
const msg = `${color}[${level}]${reset} ${args.map(a => typeof a === 'object' ? JSON.stringify(a) : a).join(' ')}`
46+
await this.send({ user: { name: 'Logger', room: 'Shell' } }, msg)
47+
}
48+
})
49+
this.robot.on('scripts have loaded', () => {
50+
this.#rl.prompt()
51+
})
3252
}
3353

3454
async send (envelope, ...strings) {
55+
this.#rl.prompt()
3556
Array.from(strings).forEach(str => console.log(bold(str)))
3657
}
3758

@@ -41,7 +62,7 @@ class Shell extends Adapter {
4162

4263
async reply (envelope, ...strings) {
4364
strings = strings.map((s) => `${envelope.user.name}: ${s}`)
44-
this.send(envelope, ...strings)
65+
await this.send(envelope, ...strings)
4566
}
4667

4768
async run () {
@@ -59,7 +80,7 @@ class Shell extends Adapter {
5980
this.#rl = readline.createInterface({
6081
input: this.robot.stdin ?? process.stdin,
6182
output: this.robot.stdout ?? process.stdout,
62-
prompt: `${this.robot.name ?? this.robot.alias}> `,
83+
prompt: green(`${this.robot.name ?? this.robot.alias}> `),
6384
completer
6485
})
6586
this.#rl.on('line', async (line) => {
@@ -73,6 +94,7 @@ class Shell extends Adapter {
7394
case '\\?':
7495
case 'help':
7596
showHelp()
97+
this.#rl.prompt()
7698
break
7799
case '\\c':
78100
case 'clear':
@@ -99,14 +121,13 @@ class Shell extends Adapter {
99121

100122
this.#rl.on('history', async (history) => {
101123
if (history.length === 0) return
102-
await fs.promises.appendFile(historyPath, `${history[0]}\n`)
124+
await appendFile(historyPath, `${history[0]}\n`)
103125
})
104126

105-
const existingHistory = (await fs.promises.readFile(historyPath, 'utf8')).split('\n')
127+
const existingHistory = (await readFile(historyPath, 'utf8')).split('\n')
106128
existingHistory.reverse().forEach(line => this.#rl.history.push(line))
107129

108130
try {
109-
this.#rl.prompt()
110131
this.emit('connected', this)
111132
} catch (error) {
112133
console.log(error)

test/Shell_test.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ describe('Shell Adapter', () => {
8080
let robot = null
8181
beforeEach(async () => {
8282
robot = new Robot('Shell', false, 'TestHubot')
83+
robot.stdin = new stream.Readable()
84+
robot.stdin._read = () => {}
8385
await robot.loadAdapter()
86+
await robot.run()
8487
})
8588
afterEach(() => {
8689
robot.shutdown()

0 commit comments

Comments
 (0)