Compare commits

...

4 Commits

Author SHA1 Message Date
Sekulum Forka 15df6c4a82 Merge branch 'master' of https://gitea.com/seculumforka/fsh 2021-05-12 16:11:48 +02:00
Sekulum Forka 5ebbc60ccb Builtins: Added the exit builtin 2021-05-12 15:43:40 +02:00
Sekulum Forka 23592c5e15 Builtins: Added set, setenv, and echo builtins 2021-05-12 14:44:24 +02:00
Sekulum Forka b1c9159155 Substitute and parseCommand: The now recognise variables and deal with them as needed 2021-05-12 13:32:08 +02:00
1 changed files with 58 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import streams
import osproc
import strtabs
import os
import strutils
# globals
var shellVariables = newStringTable(modeCaseSensitive)
@ -16,6 +17,14 @@ var envVariables = newStringTable(modeCaseSensitive)
for k, v in envPairs():
envVariables[k]=v
# list of builtin commands
let builtins: array[4, string] = [
"set",
"setenv",
"echo",
"exit",
]
# forward declarations
proc eval(cmd: string): string
proc substitute(strm: Stream, delim = ";\p"): string
@ -47,7 +56,7 @@ proc readLiteral(strm: Stream): string =
# a forward declaration. Fuck this shit
proc readSubstitution(strm: Stream): string
# readInterpelation reads the interpelation in etween [ and ]
# readInterpelation reads the interpelation in between [ and ]
proc readInterpelation(strm: Stream): string =
while not strm.atEnd():
let c = strm.readChar()
@ -185,11 +194,57 @@ proc parseCommand(cmd: string): seq[string] =
discard strm.skipSpaces()
else: newitem.add(c)
# runBuiltin runs a shell builtin
proc runBuiltin(builtin: string, args: openArray[string]): string =
case builtin:
of "set":
if args.len < 2:
raise newException(Exception, "Set: not enough arguments provided")
shellVariables[args[0]] = args[1..^1].join(" ")
return ""
of "setenv":
if args.len < 2:
raise newException(Exception, "setenv: Not enough arguments provided")
try:
envVariables[args[0]] = args[1..^1].join(":")
putEnv(args[0], args[1..^1].join(":"))
except OSError as e:
raise newException(Exception, "setenv: " & e.msg)
return ""
of "echo":
if args[0] == "-n":
return args[1..^1].join(" ")
return args.join(" ") & "\p"
of "exit":
if args.len == 0:
quit(0)
elif args.len == 1:
try:
quit(args[0].parseInt)
except ValueError:
quit(0)
else:
try:
let exitcode=args[0].parseInt
if exitcode > 0:
stderr.write(args[1..^1].join(" "), "\p")
else:
stdout.write(args[1..^1].join(" "), "\p")
quit(exitcode)
except ValueError:
stdout.write(args.join(" "), "\p")
quit(0)
else:
raise newException(Exception, "Fsh: No such builtin implemented")
# executes executes the command. For now it involves catting the command and printing it
proc execute(cmd: string): int =
let parsed = cmd.parseCommand
let progname = parsed[0]
let args = parsed[1..parsed.high]
if progname in builtins:
stdout.write(runBuiltin(progname, args))
return 0
let ps = startProcess(progname, args=args, options={poUsePath, poParentStreams})
result = ps.waitForExit
ps.close
@ -199,6 +254,8 @@ proc eval(cmd: string): string =
let parsed = cmd.parseCommand
let progname=parsed[0]
let args = parsed[1..parsed.high]
if progname in builtins:
return runBuiltin(progname, args)
let ps = startProcess(progname, args=args, options={poUsePath})
result=ps.outputStream.readAll
ps.close