debugger: Use libreadline for the prompt (#11)

* debugger: Use libreadline for the prompt

This fixes the issue where ^D would put the debugger into an infinite
loop, and adds support for persistent history, with familiar
keybindings.

I originally tried to make this new dependency optional, but your
usage of make doesn’t really tend itself to this, feel free to tell me
if you prefer another option.

Co-authored-by: Yannik Marchand <ymarchand@me.com>
This commit is contained in:
linkmauve 2021-12-01 08:14:07 +01:00 committed by GitHub
parent 63b9001111
commit 70974277af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 8 deletions

View file

@ -11,12 +11,12 @@ SRC += $(shell find src/ -type f -name "*.c")
OBJS = $(patsubst src/%,build/%.o,$(SRC))
main: $(OBJS)
$(CXX) -o $@ $(LDFLAGS) $(OBJS) -lcrypto
$(CXX) -o $@ $(LDFLAGS) $(OBJS) -lreadline -lhistory -lcrypto
build/%.o: src/%
mkdir -p $(dir $@)
@mkdir -p $(dir $@)
$(CXX) $(SRCFLAGS) -c -o $@ $<
clean:
rm -rf build
rm -f main

View file

@ -3,10 +3,12 @@
#include "debugger/expression.h"
#include "debugger/common.h"
#include "emulator.h"
#include "history.h"
#include "common/sys.h"
#include "common/buffer.h"
#include <readline/readline.h>
#include <algorithm>
@ -159,14 +161,21 @@ void Debugger::show(int core) {
DebugInterface *debugger = getInterface();
std::string format = StringUtils::format("%%s:%s> ", debugger->format());
Sys::out->write(format, debugger->name(), debugger->pc());
std::string prompt = StringUtils::format(format, debugger->name(), debugger->pc());
std::string line = Sys::in->readline();
std::vector<std::string> args;
char *line = readline(prompt.c_str());
if (!line) {
ArgParser parser(debugger->getContext(), args);
quit(&parser);
return;
}
History::append(line);
std::string current;
for (char c : line) {
for (char c : std::string(line)) {
if (c == ' ') {
if (!current.empty()) {
args.push_back(current);

33
src/history.cpp Normal file
View file

@ -0,0 +1,33 @@
#include "history.h"
#include <readline/history.h>
#include <sys/stat.h>
#include <cstdlib>
namespace History {
std::string filename;
void init() {
using_history();
char *home = getenv("HOME");
char *xdg_data = getenv("XDG_DATA_HOME");
std::string directory;
if (xdg_data && xdg_data[0] == '/')
directory = std::string(xdg_data) + "/wiiu-firmware-emulator";
else
directory = std::string(home) + "/.local/share/wiiu-firmware-emulator";
mkdir(directory.c_str(), 0755);
filename = directory + "/history";
read_history(filename.c_str());
}
void append(char *line) {
add_history(line);
write_history(filename.c_str());
}
}

9
src/history.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include <string>
namespace History {
void init();
void append(char *line);
}

View file

@ -1,10 +1,12 @@
#include "emulator.h"
#include "history.h"
#include "common/logger.h"
int main(int argc, const char *argv[]) {
Logger::init(Logger::DEBUG);
History::init();
Emulator *emulator = new Emulator();
emulator->run();
delete emulator;