Skip to content

Commit 5daac73

Browse files
committed
New dependency readline for better REPL UX.
1 parent f5323c2 commit 5daac73

5 files changed

Lines changed: 61 additions & 58 deletions

File tree

CMakeLists.txt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,22 @@ target_link_libraries(lbd PRIVATE
3636
lbdRuntime
3737
)
3838

39+
find_package(PkgConfig REQUIRED)
40+
# Readline.
41+
pkg_check_modules(READLINE REQUIRED readline)
42+
target_include_directories(lbd PRIVATE ${READLINE_INCLUDE_DIRS})
43+
target_link_libraries(lbd PRIVATE ${READLINE_LIBRARIES})
44+
3945
# Fully static build (platform dependent).
4046
option(LBD_STATIC_BUILD "Build fully static binary" OFF)
41-
if(LBD_STATIC_BUILD)
47+
if (LBD_STATIC_BUILD)
4248
target_link_options(lbd PRIVATE -static)
43-
endif()
49+
# Readline depends upon ncurses.
50+
target_link_libraries(lbd PRIVATE ncurses tinfo)
51+
endif ()
4452

4553
# Warnings.
46-
if(MSVC)
47-
target_compile_options(lbd PRIVATE /W4)
48-
else()
49-
target_compile_options(lbd PRIVATE -Wall -Wextra -Wpedantic)
50-
endif()
54+
target_compile_options(lbd PRIVATE -Wall -Wextra -Wpedantic)
5155

5256
# Tests.
5357
enable_testing()

README.md

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,16 @@
1414

1515
### Setup
1616

17-
#### GNU/Linux
18-
1917
```bash
2018
bash ./scripts/setup.sh
2119
```
2220

23-
#### Windows (PowerShell)
24-
25-
```powershell
26-
. .\scripts\setup.ps1
27-
```
28-
2921
### Run Golden Tests
3022

31-
#### GNU/Linux
32-
3323
```bash
3424
bash ./tests/run_tests.sh
3525
```
3626

37-
#### Windows
38-
39-
```powershell
40-
python .\tests\tests.py
41-
```
42-
43-
> Depricated.
44-
4527
## Samples
4628

4729
Booleans and If-Then construct built entirely using Lambda Expressions.
@@ -132,3 +114,7 @@ lbd [options]
132114
## Editor Plugins
133115

134116
1. [GNU Emacs](./editor-plugins/emacs)
117+
118+
## Dependencies
119+
120+
1. [readline](https://tiswww.case.edu/php/chet/readline/rltop.html): For better REPL user experience.

TODO.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
- [EXAMPLES] Add better examples (e.g., Advent of Code snippets).
22
- [DOCS] Fix tests output in README.
3-
- [TOOLING] Step debug kind of functionality in REPL. Inside REPL, while loading a file, load one expression at a time and provide user with some feedback and actions to perform.
43
- [DEV TOOLING] Make a pre-commit-hook which does not allow to push to master, if the tests are failing. Additionally, test whether the `docs/SIGNATURE.txt` is up-to-date or not.
4+
5+
# REPL
6+
- Add support for step-debugging while loading a file (load single expression at a time).
7+
Provide user feedback and actions to perform (gdb kind of).
8+
- Support auto-completion using readline.

scripts/setup.sh

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,31 @@
33
# and creating a Python environment for development.
44
# Should be run from within the PROJECT ROOT.
55

6-
set -e
6+
set -eu
77

8-
# --- CMake Project Setup ---
9-
BuildDir="cmake-build-debug"
10-
if [[ ! -d "$BuildDir" ]]; then
11-
mkdir "$BuildDir"
12-
fi
13-
cd "$BuildDir"
14-
cmake ..
15-
cmake --build .
16-
cd ..
8+
SCRIPTS_DIR_PATH=$(dirname "${BASH_SOURCE[0]}")
9+
ROOT_PATH=$(dirname "$SCRIPTS_DIR_PATH")
10+
BUILD_DIR="$ROOT_PATH/cmake-build-debug"
11+
12+
# Install dependencies.
13+
# TODO: Support installing dependencies in a cross platform manner.
14+
sudo apt-get install -y libreadline-dev
15+
16+
# CMake Project Setup.
17+
mkdir -p "$BUILD_DIR"
18+
cd "$BUILD_DIR"
19+
cmake "$ROOT_PATH"
20+
cmake --build "$BUILD_DIR"
1721

18-
# --- Python Environment Setup ---
19-
VenvDir="venv"
20-
if [[ ! -d "$VenvDir" ]]; then
21-
python3 -m venv "$VenvDir"
22+
# Python Environment Setup.
23+
cd "$ROOT_PATH"
24+
25+
VENV_DIR="venv"
26+
if [[ ! -d "$VENV_DIR" ]]; then
27+
python3 -m venv "$VENV_DIR"
2228
fi
23-
source "$VenvDir/bin/activate"
29+
30+
source "$VENV_DIR/bin/activate"
2431
python -m pip install --upgrade pip
2532
if [[ -f "requirements.txt" ]]; then
2633
pip install -r requirements.txt

src/repl.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
#include <lbd/frontend/parser.h>
88
#include <lbd/runtime/interpreter.h>
99
#include <lbd/exceptions.h>
10+
#include <readline/readline.h>
11+
#include <readline/history.h>
1012

11-
#define onOrOff(val) ((val) ? "on " : "off")
13+
#define ON_OR_OFF(val) ((val) ? "on " : "off")
14+
#define LBD_HISTORY ".lbd_history"
1215

1316
// TODO: Option :t for display type information of a symbol.
1417

@@ -64,10 +67,7 @@ namespace repl
6467
(*sharedEnvironment)->bind(first, second);
6568
}
6669
}
67-
if (resultantOptions.sideEffects)
68-
{
69-
std::cout << std::endl;
70-
}
70+
if (resultantOptions.sideEffects) std::cout << std::endl;
7171
}
7272

7373
subOptions.logger.info("info: file loaded ", filepath);
@@ -97,6 +97,9 @@ namespace repl
9797
{
9898
enableVirtualTerminal();
9999

100+
using_history();
101+
read_history(LBD_HISTORY);
102+
100103
static logs::Logger logger(false, true, false);
101104
optionsValue = {.ownExpression = true, .forceOnEnvironmentDump = false, .debug = debug, .logger = logger};
102105

@@ -110,18 +113,15 @@ namespace repl
110113
{
111114
try
112115
{
113-
// Prompt depends on whether we are continuing a buffer
114-
if (buffer.empty())
115-
{
116-
std::cout << colors::CYAN << "\n>> " << colors::RESET;
117-
}
118-
else
119-
{
120-
std::cout << colors::CYAN << ".. " << colors::RESET;
121-
}
116+
// Prompt depends on whether we are continuing a buffer or not.
117+
std::string prompt = colors::CYAN + std::string(buffer.empty() ? "\n>> " : ".. ") + colors::RESET;
122118
for (size_t i = 0; i < indentLevel; i++) std::cout << " ";
123119

124-
if (!std::getline(std::cin, line)) break; // EOF (C-d / C-z)
120+
char* input = readline(prompt.c_str());
121+
if (!input) break; // EOF (C-d / C-z)
122+
if (*input) add_history(input);
123+
line = std::string(input);
124+
free(input);
125125

126126
// REPL arguments parsing
127127
{
@@ -159,9 +159,9 @@ namespace repl
159159
}, colors::GREEN);
160160
std::cout << std::endl;
161161
printTable({"Options", "State", "Help"}, {
162-
{"debug", onOrOff(optionsValue.debug), "use :debug to toggle"},
162+
{"debug", ON_OR_OFF(optionsValue.debug), "use :debug to toggle"},
163163
{
164-
"force-on-env-dump", onOrOff(optionsValue.forceOnEnvironmentDump),
164+
"force-on-env-dump", ON_OR_OFF(optionsValue.forceOnEnvironmentDump),
165165
"use :force to toggle"
166166
}
167167
}, colors::GREEN);
@@ -275,5 +275,7 @@ namespace repl
275275
optionsValue.logger.error({}, "error: ", ex.what());
276276
}
277277
}
278+
279+
write_history(LBD_HISTORY);
278280
}
279281
}

0 commit comments

Comments
 (0)