cd and pwd

This commit is contained in:
Chris Wanstrath 2025-09-28 15:53:45 -07:00
parent 30dde3349f
commit 8544327f42
11 changed files with 79 additions and 22 deletions

View File

@ -7,10 +7,11 @@ import { NOSE_WWW } from "app/src/config"
import { isBinaryFile } from "app/src/utils" import { isBinaryFile } from "app/src/utils"
import { highlight } from "../lib/highlight" import { highlight } from "../lib/highlight"
import { projectName, projectDir } from "@/project" import { projectName, projectDir } from "@/project"
import { getState } from "@/session"
export default async function (path: string) { export default async function (path: string) {
const project = projectName() const project = projectName()
const root = projectDir() const root = getState("cwd") || projectDir()
let files: string[] = [] let files: string[] = []

26
app/nose/bin/cd.ts Normal file
View File

@ -0,0 +1,26 @@
import { join, dirname } from "path"
import { readdirSync } from "fs"
import { projectDir } from "@/project"
import { getState, setState } from "@/session"
export default async function (path: string) {
if (path.endsWith("/")) path = path.slice(0, path.length - 1)
const cwd = getState("cwd")
const root = cwd || projectDir()
if (path == "..") {
if (root === projectDir()) return
setState("cwd", dirname(cwd))
return
}
for (const file of readdirSync(root, { withFileTypes: true })) {
if (file.name === path && file.isDirectory()) {
setState("cwd", join(root, file.name))
return
}
}
return { error: `${path} doesn't exist` }
}

View File

@ -6,10 +6,11 @@ import { NOSE_WWW } from "app/src/config"
import { isBinaryFile } from "app/src/utils" import { isBinaryFile } from "app/src/utils"
import { countChar } from "app/src/shared/utils" import { countChar } from "app/src/shared/utils"
import { projectName, projectDir } from "@/project" import { projectName, projectDir } from "@/project"
import { getState } from "@/session"
export default async function (path: string) { export default async function (path: string) {
const project = projectName() const project = projectName()
const root = projectDir() const root = getState("cwd") || projectDir()
let files: string[] = [] let files: string[] = []

View File

@ -1,10 +1,11 @@
import { readdirSync } from "fs" import { readdirSync } from "fs"
import { NOSE_WWW } from "app/src/config" import { NOSE_WWW } from "app/src/config"
import { projectName, projectDir } from "@/project" import { projectName, projectDir } from "@/project"
import { getState } from "@/session"
export default function () { export default function () {
const project = projectName() const project = projectName()
const root = projectDir() const root = getState("cwd") || projectDir()
let files: string[] = [] let files: string[] = []

View File

@ -1,13 +1,16 @@
import { mkdirSync } from "fs" import { mkdirSync } from "fs"
import { join } from "path" import { join } from "path"
import { projectDir, projectFiles } from "@/project" import { projectDir } from "@/project"
import { readdirSync } from "fs"
import { getState } from "@/session"
export default async function (path: string) { export default async function (path: string) {
if (path.endsWith("/")) path = path.slice(0, path.length - 1) if (path.endsWith("/")) path = path.slice(0, path.length - 1)
for (const file of projectFiles()) const root = getState("cwd") || projectDir()
for (const file of readdirSync(root, { withFileTypes: true }))
if (file.name === path) throw `${path} exists` if (file.name === path) throw `${path} exists`
mkdirSync(join(projectDir(), path), { recursive: true }) mkdirSync(join(root, path), { recursive: true })
return `${path} created` return `${path} created`
} }

8
app/nose/bin/pwd.ts Normal file
View File

@ -0,0 +1,8 @@
import { dirname } from "path"
import { projectDir } from "@/project"
import { getState } from "@/session"
export default async function () {
const root = projectDir()
return (getState("cwd") || root).replace(dirname(root), "")
}

View File

@ -1,12 +1,14 @@
import { unlinkSync } from "fs" import { unlinkSync, readdirSync } from "fs"
import { join } from "path" import { join } from "path"
import { projectDir, projectFiles } from "@/project" import { projectDir } from "@/project"
import { getState } from "@/session"
export default function (path: string) { export default function (path: string) {
let target = "" let target = ""
if (path.endsWith("/")) path = path.slice(0, path.length - 1) if (path.endsWith("/")) path = path.slice(0, path.length - 1)
for (const file of projectFiles()) { const root = getState("cwd") || projectDir()
for (const file of readdirSync(root, { withFileTypes: true }))
if (file.name === path) { if (file.name === path) {
if (file.isDirectory()) if (file.isDirectory())
return { error: "Use `rmdir` to remove directory" } return { error: "Use `rmdir` to remove directory" }
@ -14,11 +16,10 @@ export default function (path: string) {
target = file.name target = file.name
break break
} }
}
if (!target) if (!target)
return { error: `${path} not found` } return { error: `${path} not found` }
unlinkSync(join(projectDir(), path)) unlinkSync(join(root, path))
return `${path} removed` return `${path} removed`
} }

View File

@ -1,12 +1,14 @@
import { rmdirSync } from "fs" import { rmdirSync, readdirSync } from "fs"
import { join } from "path" import { join } from "path"
import { projectDir, projectFiles } from "@/project" import { projectDir } from "@/project"
import { getState } from "@/session"
export default function (path: string) { export default function (path: string) {
let target = "" let target = ""
if (path.endsWith("/")) path = path.slice(0, path.length - 1) if (path.endsWith("/")) path = path.slice(0, path.length - 1)
for (const file of projectFiles()) { const root = getState("cwd") || projectDir()
for (const file of readdirSync(root, { withFileTypes: true }))
if (file.name === path) { if (file.name === path) {
if (file.isFile()) if (file.isFile())
return { error: "Use `rm` to remove files" } return { error: "Use `rm` to remove files" }
@ -14,11 +16,10 @@ export default function (path: string) {
target = file.name target = file.name
break break
} }
}
if (!target) if (!target)
return { error: `${path} not found` } return { error: `${path} not found` }
rmdirSync(join(projectDir(), path), { recursive: true }) rmdirSync(join(root, path), { recursive: true })
return `${path} removed` return `${path} removed`
} }

View File

@ -1,12 +1,15 @@
import { join } from "path" import { join } from "path"
import { projectDir, projectFiles } from "@/project" import { readdirSync } from "fs"
import { projectDir } from "@/project"
import { getState } from "@/session"
export default async function (path: string) { export default async function (path: string) {
if (path.endsWith("/")) path = path.slice(0, path.length - 1) if (path.endsWith("/")) path = path.slice(0, path.length - 1)
for (const file of projectFiles()) const root = getState("cwd") || projectDir()
for (const file of readdirSync(root, { withFileTypes: true }))
if (file.name === path) throw `${path} exists` if (file.name === path) throw `${path} exists`
await Bun.write(join(projectDir(), path), "") await Bun.write(join(root, path), "")
return `${path} created` return `${path} created`
} }

View File

@ -23,5 +23,5 @@ export function projectDir(): string {
} }
export function projectFiles(): Dirent[] { export function projectFiles(): Dirent[] {
return readdirSync(projectDir(), { withFileTypes: true }) return readdirSync(projectDir(), { recursive: true, withFileTypes: true })
} }

View File

@ -7,6 +7,7 @@ export type Session = {
taskId?: string taskId?: string
sessionId?: string sessionId?: string
project?: string project?: string
cwd?: string
ws?: any ws?: any
} }
@ -14,6 +15,17 @@ export type Session = {
const g = globalThis as typeof globalThis & { __thread?: AsyncLocalStorage<Session> } const g = globalThis as typeof globalThis & { __thread?: AsyncLocalStorage<Session> }
export const ALS = g.__thread ??= new AsyncLocalStorage<Session>() export const ALS = g.__thread ??= new AsyncLocalStorage<Session>()
export function getState(): Session | undefined { export function getState(key?: keyof Session): Session | any | undefined {
return ALS.getStore() const store = ALS.getStore()
if (!store) return
if (key) return store[key]
return store
}
export function setState(key: keyof Session, value: any) {
const store = ALS.getStore()
if (!store) return
store[key] = value
} }