chore: fix bugs & qol
This commit is contained in:
59
src/program/Cp.ts
Normal file
59
src/program/Cp.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Item } from '../fs/Item'
|
||||
import type { SimpleStream } from '../utils/SimpleStream'
|
||||
import { Program } from './Program'
|
||||
|
||||
export class Cp extends Program {
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
async Exec(_: SimpleStream<string>, stdout: SimpleStream<string>, workdir: Item, args: string[]): Promise<number> {
|
||||
if (args.length < 3) {
|
||||
stdout.emit("cp: error: missing the first and/or second path arguments\n")
|
||||
return 1
|
||||
}
|
||||
|
||||
let item1: Item
|
||||
let item2: Item
|
||||
|
||||
let destIsDir = false
|
||||
|
||||
// figure out if the items are files or directories
|
||||
try {
|
||||
item1 = await Item.openDir(Item.NormalizePath(args[1].startsWith('/') ? args[1] : `${workdir.GetPath()}/${args[1]}`))
|
||||
} catch {
|
||||
item1 = await Item.open(Item.NormalizePath(args[1].startsWith('/') ? args[1] : `${workdir.GetPath()}/${args[1]}`))
|
||||
}
|
||||
|
||||
try {
|
||||
item2 = await Item.open(Item.NormalizePath(args[2].startsWith('/') ? args[2] : `${workdir.GetPath()}/${args[2]}`))
|
||||
} catch {
|
||||
item2 = await Item.openDir(Item.NormalizePath(args[2].startsWith('/') ? args[2] : `${workdir.GetPath()}/${args[2]}`))
|
||||
destIsDir = true
|
||||
}
|
||||
|
||||
if (!await item1.Exists()) {
|
||||
stdout.emit(`cp: error: source item ${item1.GetPath()} does not exist.\n`)
|
||||
return 2
|
||||
}
|
||||
|
||||
if (await item2.Exists() && !destIsDir) {
|
||||
stdout.emit(`cp: error: destination item ${item2.GetPath()} already exists.\n`)
|
||||
return 2
|
||||
}
|
||||
|
||||
// either copy the item into a destination directory or create a new copy
|
||||
if (destIsDir) {
|
||||
const destChild = await Item.open(Item.NormalizePath(`${item2.GetPath()}/${item1.GetName()}`))
|
||||
await item1.Copy(destChild)
|
||||
stdout.emit(`-> copied ${item1.GetPath()} -> ${destChild.GetPath()}\n`)
|
||||
} else {
|
||||
await item2.Create()
|
||||
await item1.Copy(item2)
|
||||
|
||||
stdout.emit(`-> copied ${item1.GetPath()} -> ${item2.GetPath()}\n`)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ export class Ls extends Program {
|
||||
|
||||
async Exec(_: SimpleStream<string>, stdout: SimpleStream<string>, workdir: Item, args: string[]): Promise<number> {
|
||||
// open the target directory, default to workdir
|
||||
|
||||
const item = args[1]
|
||||
? await Item.openDir(Item.NormalizePath(
|
||||
args[1].startsWith('/')
|
||||
@@ -32,7 +31,7 @@ export class Ls extends Program {
|
||||
stdout.emit(` [ drwx name ]\n`)
|
||||
const items = await item.List()
|
||||
items.forEach(entry => {
|
||||
stdout.emit(` | ${`${(entry.IsDirectory() ? 'd' : '-')}${(entry.IsReadable() ? 'r' : '-')}${(entry.IsWritable() ? 'w' : '-')}${(entry.IsExecutable() ? 'x' : '-')}`.padEnd(8, ' ')} ${entry.GetName()}\n`)
|
||||
stdout.emit(` | ${`${(entry.IsDirectory() ? 'd' : '-')}${(entry.IsReadable() ? 'r' : '-')}${(entry.IsWritable() ? 'w' : '-')}${(entry.IsExecutable() ? 'x' : '-')}`.padEnd(8, ' ')} ${entry.IsDirectory() ? '\x1B[0;30m\x1B[47m' : ''}${entry.GetName()}\x1B[0m\n`)
|
||||
})
|
||||
|
||||
return 0
|
||||
|
||||
@@ -16,30 +16,46 @@ export class Mv extends Program {
|
||||
let item1: Item
|
||||
let item2: Item
|
||||
|
||||
let destIsDir = false
|
||||
|
||||
// figure out if the items are files or directories
|
||||
try {
|
||||
item1 = await Item.openDir(Item.NormalizePath(args[1].startsWith('/') ? args[1] : `${workdir.GetPath()}/${args[1]}`))
|
||||
item2 = await Item.openDir(Item.NormalizePath(args[2].startsWith('/') ? args[2] : `${workdir.GetPath()}/${args[2]}`))
|
||||
} catch {
|
||||
item1 = await Item.open(Item.NormalizePath(args[1].startsWith('/') ? args[1] : `${workdir.GetPath()}/${args[1]}`))
|
||||
}
|
||||
|
||||
try {
|
||||
item2 = await Item.open(Item.NormalizePath(args[2].startsWith('/') ? args[2] : `${workdir.GetPath()}/${args[2]}`))
|
||||
} catch {
|
||||
item2 = await Item.openDir(Item.NormalizePath(args[2].startsWith('/') ? args[2] : `${workdir.GetPath()}/${args[2]}`))
|
||||
destIsDir = true
|
||||
}
|
||||
|
||||
if (await item1.Exists()) {
|
||||
stdout.emit(`mv: error: source directory ${item1.GetPath()} does not exist.\n`)
|
||||
if (!await item1.Exists()) {
|
||||
stdout.emit(`mv: error: source item ${item1.GetPath()} does not exist.\n`)
|
||||
return 2
|
||||
}
|
||||
|
||||
if (await item2.Exists()) {
|
||||
stdout.emit(`mv: error: destination directory ${item2.GetPath()} already exists.\n`)
|
||||
if (await item2.Exists() && !destIsDir) {
|
||||
stdout.emit(`mv: error: destination item ${item2.GetPath()} already exists.\n`)
|
||||
return 2
|
||||
}
|
||||
|
||||
await item2.Create()
|
||||
await item1.Copy(item2)
|
||||
// either move the file into a destination directory or move it to a new path
|
||||
if (destIsDir) {
|
||||
const destChild = await Item.open(Item.NormalizePath(`${item2.GetPath()}/${item1.GetName()}`))
|
||||
await item1.Copy(destChild)
|
||||
stdout.emit(`-> moved ${item1.GetPath()} -> ${destChild.GetPath()}\n`)
|
||||
} else {
|
||||
await item2.Create()
|
||||
await item1.Copy(item2)
|
||||
|
||||
stdout.emit(`-> moved ${item1.GetPath()} -> ${item2.GetPath()}\n`)
|
||||
}
|
||||
|
||||
await item1.Delete()
|
||||
|
||||
stdout.emit(`-> moved ${item1.GetPath()} -> ${item2.GetPath()}\n`)
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
45
src/program/Tree.ts
Normal file
45
src/program/Tree.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Item } from '../fs/Item'
|
||||
import type { SimpleStream } from '../utils/SimpleStream'
|
||||
import { Program } from './Program'
|
||||
|
||||
export class Tree extends Program {
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
async Exec(_: SimpleStream<string>, stdout: SimpleStream<string>, workdir: Item, args: string[]): Promise<number> {
|
||||
// open the target directory, default to workdir
|
||||
const item = args[1]
|
||||
? await Item.openDir(Item.NormalizePath(
|
||||
args[1].startsWith('/')
|
||||
? args[1]
|
||||
: `${workdir.GetPath()}/${args[1]}`
|
||||
))
|
||||
: workdir
|
||||
|
||||
if (args[1] && !item.IsDirectory()) {
|
||||
stdout.emit("tree: error: the provided path is not a directory\n")
|
||||
return 1
|
||||
}
|
||||
|
||||
if (!(await item.Exists())) {
|
||||
stdout.emit(`tree: error: path ${item.GetPath()} doesn't exist\n`)
|
||||
return 2
|
||||
}
|
||||
|
||||
stdout.emit(`-> Tree of item: '${item.GetPath()}'\n`)
|
||||
await this.printTree(stdout, item, 1)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
private async printTree(stdout: SimpleStream<string>, item: Item, depth: number): Promise<void> {
|
||||
const items = await item.List()
|
||||
for (const item of items) {
|
||||
stdout.emit(` ${' |'.repeat(depth)}--+ ${item.IsDirectory() ? '\x1B[0;30m\x1B[47m' : ''}${item.GetName()}\x1B[0m\n`)
|
||||
|
||||
if (item.IsDirectory())
|
||||
await this.printTree(stdout, item, depth + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user