-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Your Name
committed
Sep 30, 2024
1 parent
a1c8472
commit 4b4fb36
Showing
7 changed files
with
207 additions
and
6 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { CmdLet } from '../../commands/cmdlet.js'; | ||
import { Command } from '../../commands/command.js'; | ||
import { Input, InputInterceptLine } from '../../io/input.js'; | ||
import { Output } from '../../io/output.js'; | ||
import { Parser } from '../../io/parser.js'; | ||
import { Token } from '../../io/token.js'; | ||
import { Macro, Macros } from '../../macros/macros.js'; | ||
import { Var } from '../../vars/var.js'; | ||
import { Vars } from '../../vars/vars.js'; | ||
|
||
export class MacroCmdLet extends CmdLet implements InputInterceptLine { | ||
name = 'm'; | ||
category = 'misc'; | ||
help = 'manage macros'; | ||
private static readonly USAGE: string = `Usage: m | ||
m - show all macros | ||
m name - create, modify or display a macro | ||
name the name of the macro | ||
m name ${CmdLet.DELETE_CHAR} - delete a macro | ||
name the name of the macro to delete`; | ||
|
||
private current: string | null = null; | ||
private commands: string[] = []; | ||
|
||
public runSync(tokens: Token[]): Var { | ||
const retWithNameAndHash = this.runDelete(tokens); | ||
if (retWithNameAndHash !== null) return retWithNameAndHash; | ||
|
||
const retWithNameAndPointer = this.runSet(tokens); | ||
if (retWithNameAndPointer !== null) return retWithNameAndPointer; | ||
|
||
const retWithName = this.runShow(tokens); | ||
if (retWithName !== null) return retWithName; | ||
|
||
return this.usage(); | ||
} | ||
|
||
private runDelete(tokens: Token[]): Var | null { | ||
const vars = this.transform(tokens, [this.parseLiteral, this.parseDelete]); | ||
if (vars === null) return null; | ||
const [name, _] = vars as [string, string]; | ||
|
||
const macro = Macros.delete(name); | ||
if (macro === null) { | ||
Output.writeln(`macro ${Output.green(name)} not set`); | ||
} else { | ||
Output.writeln(`deleted macro ${Output.green(name)}`); | ||
} | ||
return Var.ZERO; | ||
} | ||
|
||
private runSet(tokens: Token[]): Var | null { | ||
const vars = this.transform(tokens, [this.parseLiteral]); | ||
if (vars === null) return null; | ||
const [name] = vars as [string]; | ||
this.commands = []; | ||
this.current = name; | ||
const macro = Macros.get(name); | ||
if (macro === null) { | ||
Output.writeln(`Creating macro '${Output.green(name)}'`); | ||
} else { | ||
Output.writeln(`Modifying macro '${Output.green(name)}'`); | ||
Output.writeln(macro.toString()); | ||
} | ||
Input.setInterceptLine(this); | ||
return Var.ZERO; | ||
} | ||
|
||
addLine(line: string): void { | ||
this.commands.push(line); | ||
} | ||
|
||
clear(): void { | ||
if (this.current != null) { | ||
const macro = new Macro(this.current, []); | ||
Macros.set(macro); | ||
} | ||
} | ||
|
||
done(): void { | ||
if (this.current != null) { | ||
const macro = new Macro(this.current, this.commands); | ||
Macros.set(macro); | ||
} | ||
} | ||
|
||
abort(): void {} | ||
|
||
private runShow(tokens: Token[]): Var | null { | ||
if (tokens.length !== 0) return null; | ||
Output.writeln(Output.blue('Macros:')); | ||
for (const macro of Macros.all()) { | ||
Output.writeln(`${Output.green(macro.name)}:`, true); | ||
|
||
Output.writeln(macro.toString(), true); | ||
|
||
Output.writeln(); | ||
} | ||
return Var.ZERO; | ||
} | ||
|
||
public usage(): Var { | ||
Output.writeln(MacroCmdLet.USAGE); | ||
return Var.ZERO; | ||
} | ||
|
||
public static run(macro: Macro): Var { | ||
let ret = Var.ZERO; | ||
for (const command of macro.commands) { | ||
if (command.length === 0) continue; | ||
if (command.charAt(0) === '#') continue; | ||
|
||
Output.writeln(`${Output.bold(Input.PROMPT)}${command}`); | ||
|
||
if (command.trim().length === 0) continue; | ||
|
||
const parser = new Parser(command.toString()); | ||
const tokens = parser.tokenize(); | ||
ret = Command.runSync(tokens); | ||
Vars.setRet(ret); | ||
Output.writeRet(); | ||
Output.writeln(); | ||
} | ||
return ret; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Output } from '../io/output.js'; | ||
|
||
export class Macro { | ||
private readonly _name: string; | ||
private readonly _commands: string[] = []; | ||
|
||
constructor(name: string, commands: string[]) { | ||
this._name = name; | ||
this._commands = commands; | ||
} | ||
|
||
public get name(): string { | ||
return this._name; | ||
} | ||
|
||
public get commands(): string[] { | ||
return this._commands; | ||
} | ||
|
||
public toString(): string { | ||
return this._commands | ||
.map(l => Output.writeln(` - ${Output.yellow(l)}`)) | ||
.join('\n'); | ||
} | ||
} | ||
|
||
export class Macros { | ||
private static map: Map<string, Macro> = new Map<string, Macro>(); | ||
|
||
public static get(name: string): Macro | null { | ||
return this.map.get(name) ?? null; | ||
} | ||
|
||
public static set(macro: Macro) { | ||
this.map.set(macro.name, macro); | ||
} | ||
|
||
public static delete(name: string): Macro | null { | ||
const macro = this.map.get(name); | ||
if (macro === undefined) return null; | ||
this.map.delete(name); | ||
return macro; | ||
} | ||
|
||
public static all(): Macro[] { | ||
return Array.from(this.map.entries()) | ||
.sort(([k1, _v1], [k2, _v2]) => k1.localeCompare(k2)) | ||
.map(([k, v]) => v); | ||
} | ||
} |