// Copyright (C) 2019 xaizek <xaizek@posteo.net>
//
// This file is part of zograscope.
//
// zograscope is free software: you can redistribute it and/or modify
// it under the terms of version 3 of the GNU Affero General Public License as
// published by the Free Software Foundation.
//
// zograscope is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with zograscope. If not, see <http://www.gnu.org/licenses/>.
#include <iostream>
#include <sstream>
#include <vector>
#include "cursed/Init.hpp"
#include "cursed/Input.hpp"
#include "cursed/Label.hpp"
#include "cursed/Placeholder.hpp"
#include "cursed/Screen.hpp"
#include "cursed/Track.hpp"
#include "cursed/utils.hpp"
#include "vle/KeyDispatcher.hpp"
#include "vle/Mode.hpp"
#include "vle/Modes.hpp"
#include "tooling/Traverser.hpp"
#include "tooling/common.hpp"
#include "Highlighter.hpp"
#include "tree.hpp"
#include "FileRegistry.hpp"
#include "ViewManager.hpp"
static int run(const CommonArgs &args, Environment &env);
const char *const usage =
R"(Usage: zs-tui [options...] [paths...]
Paths can specify both files and directories. When no path is specified, "." is
assumed.
)";
const int InputBufferWidth = 10;
int
main(int argc, char *argv[])
{
int result;
try {
Environment env;
env.setup({ argv + 1, argv + argc });
CommonArgs args = env.getCommonArgs();
if (args.help) {
std::cout << usage
<< "\n"
<< "Options:\n";
env.printOptions();
return EXIT_SUCCESS;
}
result = run(args, env);
env.teardown();
} catch (const std::exception &e) {
std::cerr << "ERROR: " << e.what() << '\n';
result = EXIT_FAILURE;
}
return result;
}
// Runs the tool. Returns exit code of the application.
static int
run(const CommonArgs &args, Environment &env)
{
std::vector<std::string> paths = args.pos;
if (paths.empty()) {
paths.emplace_back(".");
}
Config &config = env.getConfig();
FileRegistry registry(env);
if (!Traverser(paths, args.lang, config,
[&](const std::string &path) {
return registry.addFile(path);
}).search()) {
std::cerr << "No matching files were discovered.\n";
return EXIT_FAILURE;
}
cursed::Init init;
cursed::Input input(cursed::Keypad::Enabled);
cursed::Format barBg;
barBg.setBackground(cursed::Color::White);
barBg.setForeground(60);
barBg.setBold(true);
barBg.setReversed(true);
cursed::Format helpBg;
helpBg.setBackground(239);
cursed::Label title;
title.setBackground(barBg);
cursed::Label helpLine;
helpLine.setBackground(helpBg);
cursed::Label statusLine;
statusLine.setBackground(barBg);
cursed::Label inputBuf;
inputBuf.setBackground(barBg);
inputBuf.setFixedSize(InputBufferWidth, 1);
cursed::Track bottomTrack(cursed::Orientation::Horizontal);
bottomTrack.addItem(&statusLine);
bottomTrack.addItem(&inputBuf);
cursed::Placeholder viewPlaceholder;
cursed::Track track;
track.addItem(&title);
track.addItem(&viewPlaceholder);
track.addItem(&helpLine);
track.addItem(&bottomTrack);
ViewContext viewContext = {
.registry = registry,
.quit = false,
.viewChanged = false,
.lang = nullptr,
.node = nullptr,
};
ViewManager viewManager(viewContext, viewPlaceholder);
viewManager.push("files");
auto viewChanged = [&]() {
title.setText(L"[" + cursed::toWide(viewManager.getViewName()) + L"]");
helpLine.setText(viewManager.getViewHelpLine());
statusLine.setText(viewManager.getViewStatusLine());
viewContext.viewChanged = false;
};
viewChanged();
cursed::Screen screen;
screen.replaceTopWidget(&track);
screen.draw();
vle::KeyDispatcher dispatcher;
while (cursed::InputElement ie = input.read()) {
if (ie.isTerminalResize()) {
screen.resize();
screen.draw();
continue;
}
if (!ie.isFunctionalKey()) {
dispatcher.dispatch(ie);
if (viewContext.quit) {
break;
}
if (viewContext.viewChanged) {
viewChanged();
screen.resize();
}
}
statusLine.setText(viewManager.getViewStatusLine());
std::wstring pendingInput = dispatcher.getPendingInput();
int excess = pendingInput.size() - InputBufferWidth;
if (excess > 0) {
pendingInput.erase(0, excess);
}
inputBuf.setText(pendingInput);
screen.draw();
}
return EXIT_SUCCESS;
}
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/zograscope
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/zograscope
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master