in src/extension/src/lspclient.ts [389:446]
private async setupCustomOutputChannels(): Promise<void> {
// Clean up any existing output channels and tailed files.
this.cleanupCustomOutput()
const infoFileJson: {string: string} = await this.readServerInfoFile()
for (const [key, outputFilePath] of Object.entries(infoFileJson)) {
// Only watch files that are specified in the info file and have a key in the format of "output:sample".
if (!key.startsWith('output:') || outputFilePath == undefined) {
continue
}
// Extract the display name from the key and set up the channel.
const channelID = key?.split(':')[1] ?? key
const outputChannelName = `Uber LSP Output: ${channelID}`
const channel = vscode.window.createOutputChannel(outputChannelName)
channel.appendLine(`INFO: Output from file: ${outputFilePath}`)
const currentEntry: customOutputChannel = {
channel: channel,
id: channelID,
}
this.customOutputChannels.push(currentEntry)
this.outputChannelClient?.appendLine(
`INFO: Added ${channelID} channel to watch output from ${outputFilePath}.`
)
// Begin tailing the file, and append any new lines to the output channel.
// For memory usage and ease of navigation, limit the number of lines shown in the output panel to CUSTOM_OUTPUT_MAX_LINES.
try {
currentEntry.tail = new Tail(outputFilePath)
let lines = 0
currentEntry.tail.on('line', async (line: string) => {
if (lines > CUSTOM_OUTPUT_MAX_LINES) {
channel.clear()
channel.appendLine(
`INFO: Showing most recent lines. See prior output in: ${outputFilePath}`
)
lines = 0
}
channel.appendLine(line)
lines++
})
// Stop watching on error or deleted file.
// The output channel will remain available until the next time the client is restarted.
currentEntry.tail.on('error', async (err: Error) => {
channel.appendLine(`ERROR: ${err.message}`)
currentEntry.tail!.unwatch()
})
} catch (err) {
const errMsg = err instanceof Error ? err.message : String(err)
currentEntry.channel.appendLine(
`ERROR: Unable to display output in this channel. ${errMsg}`
)
}
}
return
}