Compare commits
5 Commits
eff52bf920
...
75819e9abc
Author | SHA1 | Date |
---|---|---|
Sekulum Forka | 75819e9abc | |
Sekulum Forka | c2ba92518e | |
Sekulum Forka | 3d7bf1029e | |
Sekulum Forka | 8c48eb9057 | |
Sekulum Forka | 2a732eb569 |
51
src/fsh.nim
51
src/fsh.nim
|
@ -10,7 +10,8 @@ import os
|
|||
import strutils
|
||||
|
||||
# globals
|
||||
var shellVariables = newStringTable(modeCaseSensitive)
|
||||
# shellVariables are an array of vars
|
||||
var shellVariables = @[newStringTable(modeCaseSensitive)]
|
||||
# Environment variables get defined in a separate var
|
||||
var envVariables = newStringTable(modeCaseSensitive)
|
||||
# populate the table
|
||||
|
@ -18,15 +19,19 @@ for k, v in envPairs():
|
|||
envVariables[k]=v
|
||||
|
||||
# list of builtin commands
|
||||
let builtins: array[6, string] = [
|
||||
let builtins: array[7, string] = [
|
||||
"set",
|
||||
"setenv",
|
||||
"echo",
|
||||
"exit",
|
||||
"if",
|
||||
"cd",
|
||||
"let",
|
||||
]
|
||||
|
||||
# number of frames to be used for builtins like set
|
||||
var numframes: int=1
|
||||
|
||||
# Exception types
|
||||
type
|
||||
ShellError= object of CatchableError
|
||||
|
@ -88,8 +93,10 @@ proc readLiteral(strm: Stream): string =
|
|||
case c:
|
||||
of '{':
|
||||
numbraces.inc
|
||||
result.add('{')
|
||||
of '}':
|
||||
numbraces = numbraces - 1
|
||||
if numbraces != 0: result.add('}')
|
||||
of '\\':
|
||||
if strm.peekChar notin {'{', '}'}: result.add(strm.readChar)
|
||||
result.add(strm.readChar)
|
||||
|
@ -191,9 +198,10 @@ proc readVariable(strm: Stream): string =
|
|||
# evalVariable finds a value of a variable
|
||||
proc evalVariable(vari: string): string =
|
||||
if vari == "$": return "$"
|
||||
if shellVariables.hasKey(vari):
|
||||
result=shellVariables[vari]
|
||||
elif envVariables.hasKey(vari):
|
||||
for i in countdown((numframes-1), 0):
|
||||
let frame = shellVariables[i]
|
||||
if frame.hasKey(vari): return frame[vari]
|
||||
if envVariables.hasKey(vari):
|
||||
result = envVariables[vari]
|
||||
else:
|
||||
raise newShellVariableException("No such variable", vari)
|
||||
|
@ -252,7 +260,7 @@ proc runBuiltin(builtin: string, args: openArray[string]): (string, int) =
|
|||
of "set":
|
||||
if args.len < 2:
|
||||
raise newShellCommandException("Not enough arguments provided", "set")
|
||||
shellVariables[args[0]] = args[1..^1].join(" ")
|
||||
shellVariables[numframes-1][args[0]] = args[1..^1].join(" ")
|
||||
return ("", 0)
|
||||
of "setenv":
|
||||
if args.len < 2:
|
||||
|
@ -310,20 +318,37 @@ proc runBuiltin(builtin: string, args: openArray[string]): (string, int) =
|
|||
of "cd":
|
||||
try:
|
||||
if args.len == 0:
|
||||
shellVariables["LASTPWD"] = getCurrentDir()
|
||||
shellVariables[0]["LASTPWD"] = getCurrentDir()
|
||||
setCurrentDir(getHomeDir())
|
||||
return ("", 0)
|
||||
else:
|
||||
if args[0] == "-":
|
||||
let LASTPWD = getCurrentDir()
|
||||
setCurrentDir(shellVariables["LASTPWD"])
|
||||
shellVariables["LASTPWD"] = LASTPWD
|
||||
setCurrentDir(shellVariables[0]["LASTPWD"])
|
||||
shellVariables[0]["LASTPWD"] = LASTPWD
|
||||
return ("", 0)
|
||||
shellVariables["LASTPWD"] = getCurrentDir()
|
||||
shellVariables[0]["LASTPWD"] = getCurrentDir()
|
||||
setCurrentDir(args[0])
|
||||
return ("", 0)
|
||||
except OsError as e:
|
||||
raise newShellCommandException("No such directory", "cd")
|
||||
of "let":
|
||||
if args.len < 2:
|
||||
raise newShellCommandException("Not enough arguments provided", "let")
|
||||
shellVariables.add(newStringTable(modeCaseSensitive))
|
||||
numframes.inc
|
||||
let varvals = args[0].parseCommand
|
||||
for varval in varvals:
|
||||
let varval_parsed = varval.parseCommand
|
||||
if varval_parsed.len < 2:
|
||||
raise newShellCommandException("Missingvalue to go with key", "let")
|
||||
let vari = varval_parsed[0]
|
||||
let val = varval_parsed[1]
|
||||
shellVariables[numframes-1][vari]=val
|
||||
result[0] = args[1].eval
|
||||
discard shellVariables.pop
|
||||
numframes.dec
|
||||
result[1] = 0
|
||||
else:
|
||||
raise newShellCommandException("No such builtin implemented", builtin)
|
||||
|
||||
|
@ -374,12 +399,12 @@ when isMainModule:
|
|||
setControlCHook(ctrlc)
|
||||
let stdinstrm = stdin.newFileStream
|
||||
# Set the default prompt
|
||||
shellVariables["PROMPT"] = "$PWD \\$"
|
||||
stdout.write(shellVariables["PROMPT"].newStringStream.substitute)
|
||||
shellVariables[0]["PROMPT"] = "$PWD \\$"
|
||||
stdout.write(shellVariables[0]["PROMPT"].newStringStream.substitute)
|
||||
while not stdinstrm.atEnd():
|
||||
try:
|
||||
discard stdinstrm.readCommand.execute
|
||||
stdout.write(shellVariables["PROMPT"].newStringStream.substitute)
|
||||
stdout.write(shellVariables[0]["PROMPT"].newStringStream.substitute)
|
||||
except ShellError, ShellCommandError, ShellVariableError:
|
||||
let e = getCurrentException()
|
||||
stderr.write(e.msg, "\n")
|
||||
|
|
Loading…
Reference in New Issue