mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-03 07:33:45 +00:00
add auto formatting and experimental hooks feature
This commit is contained in:
143
packages/opencode/src/format/index.ts
Normal file
143
packages/opencode/src/format/index.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { App } from '../app/app'
|
||||
import { BunProc } from '../bun'
|
||||
import { Config } from '../config/config'
|
||||
import { Log } from '../util/log'
|
||||
import path from 'path'
|
||||
|
||||
export namespace Format {
|
||||
const log = Log.create({ service: 'format' })
|
||||
|
||||
const state = App.state('format', async () => {
|
||||
const hooks: Record<string, Hook[]> = {}
|
||||
for (const item of FORMATTERS) {
|
||||
if (await item.enabled()) {
|
||||
for (const ext of item.extensions) {
|
||||
const list = hooks[ext] ?? []
|
||||
list.push({
|
||||
command: item.command,
|
||||
environment: item.environment,
|
||||
})
|
||||
hooks[ext] = list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cfg = await Config.get()
|
||||
for (const [file, items] of Object.entries(
|
||||
cfg.experimental?.hook?.file_edited ?? {},
|
||||
)) {
|
||||
for (const item of items) {
|
||||
const list = hooks[file] ?? []
|
||||
list.push({
|
||||
command: item.command,
|
||||
environment: item.environment,
|
||||
})
|
||||
hooks[file] = list
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hooks,
|
||||
}
|
||||
})
|
||||
|
||||
export async function run(file: string) {
|
||||
log.info('formatting', { file })
|
||||
const { hooks } = await state()
|
||||
const ext = path.extname(file)
|
||||
const match = hooks[ext]
|
||||
if (!match) return
|
||||
|
||||
for (const item of match) {
|
||||
log.info('running', { command: item.command })
|
||||
const proc = Bun.spawn({
|
||||
cmd: item.command.map((x) => x.replace('$FILE', file)),
|
||||
cwd: App.info().path.cwd,
|
||||
env: item.environment,
|
||||
})
|
||||
const exit = await proc.exited
|
||||
if (exit !== 0)
|
||||
log.error('failed', {
|
||||
command: item.command,
|
||||
...item.environment,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
interface Hook {
|
||||
command: string[]
|
||||
environment?: Record<string, string>
|
||||
}
|
||||
|
||||
interface Native {
|
||||
name: string
|
||||
command: string[]
|
||||
environment?: Record<string, string>
|
||||
extensions: string[]
|
||||
enabled(): Promise<boolean>
|
||||
}
|
||||
|
||||
const FORMATTERS: Native[] = [
|
||||
{
|
||||
name: 'prettier',
|
||||
extensions: [
|
||||
'.js',
|
||||
'.jsx',
|
||||
'.mjs',
|
||||
'.cjs',
|
||||
'.ts',
|
||||
'.tsx',
|
||||
'.mts',
|
||||
'.cts',
|
||||
'.html',
|
||||
'.htm',
|
||||
'.css',
|
||||
'.scss',
|
||||
'.sass',
|
||||
'.less',
|
||||
'.vue',
|
||||
'.svelte',
|
||||
'.json',
|
||||
'.jsonc',
|
||||
'.yaml',
|
||||
'.yml',
|
||||
'.toml',
|
||||
'.xml',
|
||||
'.md',
|
||||
'.mdx',
|
||||
'.php',
|
||||
'.rb',
|
||||
'.java',
|
||||
'.go',
|
||||
'.rs',
|
||||
'.swift',
|
||||
'.kt',
|
||||
'.kts',
|
||||
'.sol',
|
||||
'.graphql',
|
||||
'.gql',
|
||||
],
|
||||
command: [BunProc.which(), 'run', 'prettier', '--write', '$FILE'],
|
||||
environment: {
|
||||
BUN_BE_BUN: '1',
|
||||
},
|
||||
async enabled() {
|
||||
try {
|
||||
const proc = Bun.spawn({
|
||||
cmd: [BunProc.which(), 'run', 'prettier', '--version'],
|
||||
cwd: App.info().path.cwd,
|
||||
env: {
|
||||
BUN_BE_BUN: '1',
|
||||
},
|
||||
stdout: 'ignore',
|
||||
stderr: 'ignore',
|
||||
})
|
||||
const exit = await proc.exited
|
||||
return exit === 0
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user