Skip to content

Commit

Permalink
Support runtime errors (unhandled exceptions), shortcut (discarded sy…
Browse files Browse the repository at this point in the history
…mbols) handles multiline strings, general code refactor/improvements
  • Loading branch information
AndreiRegiani committed Jul 25, 2018
1 parent 7ecaf84 commit 683fd42
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 41 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
* Runs on Linux, macOS and Windows
* Auto-indent (`if`, `for`, `proc`, `var`, ...)
* Arrow keys support (command history and line navigation)
* Prints out value and type of discarded expressions: ```>>> x```
* Uses current `nim` compiler in PATH
* Runs in the current directory: `import` your local modules (access to exported* symbols)
* Preload existing source code (access to non-exported* symbols): `inim example.nim`
* Colorized output (red for errors, cyan for results)
* Prints out value and type of discarded expressions: ```>>> x```
* Colorized output

## Contributing
Pull requests and suggestions are welcome.
2 changes: 1 addition & 1 deletion inim.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.3.0"
version = "0.3.1"
author = "Andrei Regiani"
description = "Interactive Nim Shell / REPL / Playground"
license = "MIT"
Expand Down
84 changes: 46 additions & 38 deletions src/inim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type App = ref object
var app:App

const
INimVersion = "0.3.0"
INimVersion = "0.3.1"
indentSpaces = " "
indentTriggers = [",", "=", ":", "var", "let", "const", "type", "import",
"object", "enum"] # endsWith
Expand Down Expand Up @@ -68,12 +68,48 @@ proc getFileData(path: string): string =
except:
result = nil

proc compilationSuccess(current_statement, output: string) =
if len(tempIndentCode) > 0:
validCode &= tempIndentCode
else:
validCode &= current_statement & "\n"
let lines = output.splitLines

# Print only output you haven't seen
stdout.setForegroundColor(fgCyan, true)
let new_lines = lines[currentOutputLine..^1]

for index, line in new_lines:
# Skip last empty line (otherwise blank line is displayed after command)
if index+1 == len(new_lines) and line == "":
continue
echo line

currentOutputLine = len(lines)-1
stdout.resetAttributes()
stdout.flushFile()

proc bufferRestoreValidCode() =
buffer.close()
buffer = open(bufferSource, fmWrite)
buffer.write(validCode)
buffer.flushFile()

proc showError(output: string) =
## 'Discarded' errors will be handled to print its value and type.
## Other errors print only relevant message without file and line number info.
## e.g. "inim_1520787258.nim(2, 6) Error: undeclared identifier: 'foo'"
# Runtime errors:
if output.contains("Error: unhandled exception:"):
stdout.setForegroundColor(fgRed, true)
echo output.splitLines()[^3] # e.g. "Error: unhandled exception: index out of bounds [IndexError]"
stdout.resetAttributes()
stdout.flushFile()
return

# Compilation errors:

# Prints only relevant message without file and line number info.
# e.g. "inim_1520787258.nim(2, 6) Error: undeclared identifier: 'foo'"
# Becomes: "Error: undeclared identifier: 'foo'"
let pos = output.find(")") + 2
# "Error: expression 'foo' is of type 'int' and has to be discarded"
var message = output[pos..^1].strip

# Discarded error: shortcut to print values: >>> foo
Expand All @@ -97,17 +133,10 @@ proc showError(output: string) =

let (output, status) = compileCode()
if status == 0:
let lines = output.splitLines()
stdout.setForegroundColor(fgCyan, true)
echo lines[^2] # ^1 is empty line, ^2 is last stdout
stdout.resetAttributes()
stdout.flushFile()
currentOutputLine = len(lines)-1
compilationSuccess(shortcut, output)
else:
stdout.setForegroundColor(fgRed, true)
echo output.splitLines()[0]
stdout.resetAttributes()
stdout.flushFile()
bufferRestoreValidCode()
showError(output)

# Display all other errors
else:
Expand Down Expand Up @@ -195,33 +224,12 @@ proc runForever() =

# Succesful compilation, expression is valid
if status == 0:
if len(tempIndentCode) > 0:
validCode &= tempIndentCode
else:
validCode &= myline & "\n"
let lines = output.splitLines

# Print only output you haven't seen
stdout.setForegroundColor(fgCyan, true)
let new_lines = lines[currentOutputLine..^1]

for index, line in new_lines:
# Skip last empty line (otherwise blank line is displayed after command)
if index+1 == len(new_lines) and line == "":
continue
echo line

currentOutputLine = len(lines)-1
stdout.resetAttributes()
stdout.flushFile()
compilationSuccess(myline, output)

# Compilation error
else:
# Write back valid code to buffer
buffer.close()
buffer = open(bufferSource, fmWrite)
buffer.write(validCode)
buffer.flushFile()
bufferRestoreValidCode()
showError(output)
indentLevel = 0

Expand Down

0 comments on commit 683fd42

Please sign in to comment.