Skip to content

Commit

Permalink
Add a permanent history of commands to the address bar.
Browse files Browse the repository at this point in the history
  • Loading branch information
gijsbers committed May 26, 2024
1 parent 38a1e7e commit e8015e8
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 6 deletions.
80 changes: 75 additions & 5 deletions src/aaddressbar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@
#include "default.h"
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <X11/keysym.h>
#include "ywordexp.h"

AddressBar::AddressBar(IApp *app, YWindow *parent):
YInputLine(parent, this),
app(app),
location(0),
restored(0),
curdir(upath::cwd()),
olddir(curdir)
{
loadHistoryTimer->setTimer(500L, this, true);
}

AddressBar::~AddressBar() {
saveHistory();
}

bool AddressBar::handleKey(const XKeyEvent &key) {
Expand Down Expand Up @@ -67,6 +71,9 @@ void AddressBar::handleReturn(bool control) {
if (line.nonempty()) {
history.append(line);
location = history.getCount();
if (saveHistoryTimer == nullptr) {
saveHistoryTimer->setTimer(minute(), this, true);
}
}
if (internal(line))
return;
Expand All @@ -87,8 +94,10 @@ void AddressBar::handleReturn(bool control) {
if (line.isEmpty())
args.replace(control, nullptr);
if (args[0]) {
upath cwd(upath::cwd());
bool change = (cwd != curdir);
bool change = false;
upath cwd;
if (curdir != null && curdir != (cwd = upath::cwd()))
change = true;
if (change)
curdir.chdir();
app->runProgram(args[0], args.getCArray());
Expand All @@ -113,8 +122,10 @@ bool AddressBar::internal(mstring line) {
if (strchr("$~", arg[0]))
arg = upath(arg).expand();
else if (arg == "-")
arg = olddir;
upath newdir((arg[0] == '/') ? upath(arg) : curdir + arg);
arg = (olddir != null) ? olddir.path() : upath::cwd();
upath newdir((arg[0] == '/') ? upath(arg) :
(curdir != null) ? curdir + arg :
upath(upath::cwd()) + arg);
upath realdir = upath(newdir).real();
if (realdir.isEmpty()) {
arg.fmt("%s: %m", newdir.string());
Expand All @@ -124,7 +135,7 @@ bool AddressBar::internal(mstring line) {
arg.fmt("%s: %m", realdir.string());
return setText(arg, true), true;
} else {
olddir = curdir;
olddir = (curdir != null) ? curdir : upath(upath::cwd());
curdir = realdir;
return setText(curdir, true), true;
}
Expand Down Expand Up @@ -176,4 +187,63 @@ void AddressBar::inputEscape(YInputLine* input) {
void AddressBar::inputLostFocus(YInputLine* input) {
}

bool AddressBar::handleTimer(YTimer* timer) {
if (timer == loadHistoryTimer) {
loadHistory();
loadHistoryTimer = null;
}
else if (timer == saveHistoryTimer) {
saveHistory();
saveHistoryTimer = null;
}
else {
return YInputLine::handleTimer(timer);
}
return false;
}

upath AddressBar::historyFile() {
return YApplication::getPrivConfFile("ahistory");
}

void AddressBar::loadHistory() {
upath path(historyFile());
FILE* fp = path.fopen("r");
if (fp) {
char buf[4096];
int n = 0;
while (fgets(buf, sizeof buf, fp))
++n;
rewind(fp);
for (int i = saveLines; i < n && fgets(buf, sizeof buf, fp); ++i)
;
for (int i = 0; i < saveLines && fgets(buf, sizeof buf, fp); ++i) {
char* nl = strchr(buf, '\n');
if (nl)
*nl = '\0';
history.insert(i, buf);
location++;
restored++;
}
fclose(fp);
}
}

void AddressBar::saveHistory() {
if (restored < history.getCount()) {
upath path(historyFile());
FILE* fp = path.fopen("w");
if (fp) {
fchmod(fileno(fp), 0600);
const int first = max(0, history.getCount() - saveLines);
for (int i = first; i < history.getCount(); ++i) {
fputs(history[i], fp);
fputc('\n', fp);
}
fclose(fp);
restored = history.getCount();
}
}
}

// vim: set sw=4 ts=4 et:
13 changes: 12 additions & 1 deletion src/aaddressbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

class IApp;

class AddressBar: public YInputLine, private YInputListener {
class AddressBar:
public YInputLine,
private YInputListener
{
public:
AddressBar(IApp *app, YWindow *parent = nullptr);
virtual ~AddressBar();
Expand All @@ -22,15 +25,23 @@ class AddressBar: public YInputLine, private YInputListener {
void handleReturn(bool control);
bool appendCommand(const char* cmd, class YStringArray& args);
bool internal(mstring line);
void loadHistory();
void saveHistory();
upath historyFile();

void inputReturn(YInputLine* input, bool control);
void inputEscape(YInputLine* input);
void inputLostFocus(YInputLine* input);
bool handleTimer(YTimer* timer);

IApp *app;
MStringArray history;
int location;
int restored;
const int saveLines = 64;
upath curdir, olddir;
lazy<YTimer> loadHistoryTimer;
lazy<YTimer> saveHistoryTimer;
};

#endif
Expand Down

0 comments on commit e8015e8

Please sign in to comment.