2013-06-06 14:01:32 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2013, Timothy Stack
|
|
|
|
*
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
|
|
|
* list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
|
|
|
* * Neither the name of Timothy Stack nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
2022-03-16 22:38:08 +00:00
|
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
2013-06-06 14:01:32 +00:00
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @file lnav_config.cc
|
|
|
|
*/
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
#include <chrono>
|
|
|
|
#include <iostream>
|
|
|
|
#include <regex>
|
|
|
|
#include <stdexcept>
|
2013-06-06 14:01:32 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "lnav_config.hh"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
#include <glob.h>
|
|
|
|
#include <libgen.h>
|
2013-06-06 14:10:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2013-06-06 14:01:32 +00:00
|
|
|
#include <sys/stat.h>
|
2015-08-10 04:03:23 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
#include "base/auto_fd.hh"
|
2022-04-12 23:07:13 +00:00
|
|
|
#include "base/auto_mem.hh"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "base/auto_pid.hh"
|
2022-03-13 22:49:41 +00:00
|
|
|
#include "base/fs_util.hh"
|
2021-01-17 06:23:20 +00:00
|
|
|
#include "base/injector.bind.hh"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "base/injector.hh"
|
|
|
|
#include "base/lnav_log.hh"
|
2021-05-16 05:39:18 +00:00
|
|
|
#include "base/paths.hh"
|
2020-10-29 04:23:46 +00:00
|
|
|
#include "base/string_util.hh"
|
2020-12-30 21:49:29 +00:00
|
|
|
#include "bin2c.hh"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "config.h"
|
2019-05-15 16:13:56 +00:00
|
|
|
#include "default-config.h"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "styling.hh"
|
2022-04-12 23:07:13 +00:00
|
|
|
#include "view_curses.hh"
|
2022-03-16 22:38:08 +00:00
|
|
|
#include "yajlpp/yajlpp.hh"
|
|
|
|
#include "yajlpp/yajlpp_def.hh"
|
2013-06-06 14:01:32 +00:00
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
using namespace std::chrono_literals;
|
2013-06-06 14:01:32 +00:00
|
|
|
|
2014-03-02 00:35:30 +00:00
|
|
|
static const int MAX_CRASH_LOG_COUNT = 16;
|
2019-07-30 05:18:32 +00:00
|
|
|
static const auto STDIN_CAPTURE_RETENTION = 24h;
|
2014-03-02 00:35:30 +00:00
|
|
|
|
2021-09-22 23:01:03 +00:00
|
|
|
static auto intern_lifetime = intern_string::get_table_lifetime();
|
|
|
|
|
2016-01-05 14:18:58 +00:00
|
|
|
struct _lnav_config lnav_config;
|
2019-05-03 20:50:19 +00:00
|
|
|
struct _lnav_config rollback_lnav_config;
|
2016-01-05 14:18:58 +00:00
|
|
|
static struct _lnav_config lnav_default_config;
|
|
|
|
|
2019-05-03 20:50:19 +00:00
|
|
|
std::map<intern_string_t, source_location> lnav_config_locations;
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
lnav_config_listener* lnav_config_listener::LISTENER_LIST;
|
2016-05-02 03:35:37 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static auto a = injector::bind<archive_manager::config>::to_instance(
|
|
|
|
+[]() { return &lnav_config.lc_archive_manager; });
|
2021-01-17 06:23:20 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static auto fvc = injector::bind<file_vtab::config>::to_instance(
|
|
|
|
+[]() { return &lnav_config.lc_file_vtab; });
|
2021-03-06 00:17:28 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static auto lc = injector::bind<lnav::logfile::config>::to_instance(
|
|
|
|
+[]() { return &lnav_config.lc_logfile; });
|
2021-03-30 05:40:22 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static auto tc = injector::bind<tailer::config>::to_instance(
|
|
|
|
+[]() { return &lnav_config.lc_tailer; });
|
2021-05-20 05:05:21 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static auto scc = injector::bind<sysclip::config>::to_instance(
|
|
|
|
+[]() { return &lnav_config.lc_sysclip; });
|
2021-09-16 04:29:55 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
bool
|
|
|
|
check_experimental(const char* feature_name)
|
2013-06-06 14:01:32 +00:00
|
|
|
{
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* env_value = getenv("LNAV_EXP");
|
2013-06-06 14:01:32 +00:00
|
|
|
|
2021-01-17 06:23:20 +00:00
|
|
|
require(feature_name != nullptr);
|
2013-06-06 14:01:32 +00:00
|
|
|
|
|
|
|
if (env_value && strcasestr(env_value, feature_name)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
ensure_dotlnav()
|
2013-06-06 14:01:32 +00:00
|
|
|
{
|
2022-03-16 22:38:08 +00:00
|
|
|
static const char* subdirs[] = {
|
2019-07-30 05:18:32 +00:00
|
|
|
"",
|
2020-05-07 14:08:59 +00:00
|
|
|
"configs",
|
|
|
|
"configs/default",
|
|
|
|
"configs/installed",
|
2019-07-30 05:18:32 +00:00
|
|
|
"formats",
|
|
|
|
"formats/default",
|
|
|
|
"formats/installed",
|
2020-05-07 14:08:59 +00:00
|
|
|
"staging",
|
2019-07-30 05:18:32 +00:00
|
|
|
"stdin-captures",
|
|
|
|
"crash",
|
|
|
|
};
|
2013-06-06 14:01:32 +00:00
|
|
|
|
2021-05-16 05:39:18 +00:00
|
|
|
auto path = lnav::paths::dotlnav();
|
2013-07-23 12:55:08 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
for (const auto* sub_path : subdirs) {
|
2019-07-30 05:18:32 +00:00
|
|
|
auto full_path = path / sub_path;
|
2014-11-05 17:01:09 +00:00
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
log_perror(mkdir(full_path.c_str(), 0755));
|
2014-11-05 17:01:09 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
lnav_log_crash_dir = strdup(path.c_str());
|
2014-03-02 00:35:30 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
static_root_mem<glob_t, globfree> gl;
|
2019-07-30 05:18:32 +00:00
|
|
|
auto crash_glob = path / "crash/*";
|
2014-03-02 00:35:30 +00:00
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(crash_glob.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) {
|
2022-03-16 22:38:08 +00:00
|
|
|
for (int lpc = 0; lpc < ((int) gl->gl_pathc - MAX_CRASH_LOG_COUNT);
|
2014-03-02 00:35:30 +00:00
|
|
|
lpc++) {
|
2015-09-18 03:55:31 +00:00
|
|
|
log_perror(remove(gl->gl_pathv[lpc]));
|
2014-03-02 00:35:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-30 05:18:32 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
static_root_mem<glob_t, globfree> gl;
|
|
|
|
auto cap_glob = path / "stdin-captures/*";
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(cap_glob.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) {
|
2022-03-16 22:38:08 +00:00
|
|
|
auto old_time
|
|
|
|
= std::chrono::system_clock::now() - STDIN_CAPTURE_RETENTION;
|
2019-07-30 05:18:32 +00:00
|
|
|
|
2020-09-03 05:36:26 +00:00
|
|
|
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
2019-07-30 05:18:32 +00:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(gl->gl_pathv[lpc], &st) == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
if (std::chrono::system_clock::from_time_t(st.st_mtime)
|
|
|
|
> old_time) {
|
2019-07-30 05:18:32 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
log_info("Removing old stdin capture: %s", gl->gl_pathv[lpc]);
|
2019-07-30 05:18:32 +00:00
|
|
|
log_perror(remove(gl->gl_pathv[lpc]));
|
|
|
|
}
|
|
|
|
}
|
2013-08-29 04:22:04 +00:00
|
|
|
}
|
2013-06-06 14:01:32 +00:00
|
|
|
}
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
bool
|
2022-04-30 20:05:42 +00:00
|
|
|
install_from_git(const std::string& repo)
|
2015-08-10 04:03:23 +00:00
|
|
|
{
|
2021-02-01 23:56:37 +00:00
|
|
|
static const std::regex repo_name_converter("[^\\w]");
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2021-05-16 05:39:18 +00:00
|
|
|
auto formats_path = lnav::paths::dotlnav() / "formats";
|
|
|
|
auto configs_path = lnav::paths::dotlnav() / "configs";
|
|
|
|
auto staging_path = lnav::paths::dotlnav() / "staging";
|
2022-03-31 15:59:19 +00:00
|
|
|
auto local_name = std::regex_replace(repo, repo_name_converter, "_");
|
2020-05-07 14:08:59 +00:00
|
|
|
|
|
|
|
auto local_formats_path = formats_path / local_name;
|
|
|
|
auto local_configs_path = configs_path / local_name;
|
|
|
|
auto local_staging_path = staging_path / local_name;
|
|
|
|
|
2021-05-01 15:33:16 +00:00
|
|
|
auto fork_res = lnav::pid::from_fork();
|
|
|
|
if (fork_res.isErr()) {
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"error: cannot fork() to run git: %s\n",
|
2021-05-01 15:33:16 +00:00
|
|
|
fork_res.unwrapErr().c_str());
|
|
|
|
_exit(1);
|
|
|
|
}
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2021-05-01 15:33:16 +00:00
|
|
|
auto git_cmd = fork_res.unwrap();
|
2015-08-10 04:03:23 +00:00
|
|
|
if (git_cmd.in_child()) {
|
2020-10-21 05:55:46 +00:00
|
|
|
if (ghc::filesystem::is_directory(local_formats_path)) {
|
2022-04-30 20:05:42 +00:00
|
|
|
fmt::print("Updating format repo: {}\n", repo);
|
2020-10-21 05:55:46 +00:00
|
|
|
log_perror(chdir(local_formats_path.c_str()));
|
2020-05-07 14:08:59 +00:00
|
|
|
execlp("git", "git", "pull", nullptr);
|
2022-03-16 22:38:08 +00:00
|
|
|
} else if (ghc::filesystem::is_directory(local_configs_path)) {
|
2022-04-30 20:05:42 +00:00
|
|
|
fmt::print("Updating config repo: {}\n", repo);
|
2020-10-21 05:55:46 +00:00
|
|
|
log_perror(chdir(local_configs_path.c_str()));
|
2019-07-30 05:18:32 +00:00
|
|
|
execlp("git", "git", "pull", nullptr);
|
2022-03-16 22:38:08 +00:00
|
|
|
} else {
|
|
|
|
execlp("git",
|
|
|
|
"git",
|
|
|
|
"clone",
|
2022-04-30 20:05:42 +00:00
|
|
|
repo.c_str(),
|
2022-03-16 22:38:08 +00:00
|
|
|
local_staging_path.c_str(),
|
|
|
|
nullptr);
|
2015-08-10 04:03:23 +00:00
|
|
|
}
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
2021-05-01 15:33:16 +00:00
|
|
|
auto finished_child = std::move(git_cmd).wait_for_child();
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
if (!finished_child.was_normal_exit() || finished_child.exit_status() != 0)
|
|
|
|
{
|
2020-05-07 14:08:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (ghc::filesystem::is_directory(local_staging_path)) {
|
2020-05-07 14:08:59 +00:00
|
|
|
auto config_path = local_staging_path / "*.json";
|
|
|
|
static_root_mem<glob_t, globfree> gl;
|
|
|
|
bool found_config_file = false, found_format_file = false;
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(config_path.c_str(), 0, nullptr, gl.inout()) == 0) {
|
2020-05-07 14:08:59 +00:00
|
|
|
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
|
|
|
auto json_file_path = gl->gl_pathv[lpc];
|
|
|
|
auto file_type_result = detect_config_file_type(json_file_path);
|
|
|
|
|
|
|
|
if (file_type_result.isErr()) {
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"error: %s\n",
|
2020-05-07 14:08:59 +00:00
|
|
|
file_type_result.unwrapErr().c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (file_type_result.unwrap() == config_file_type::CONFIG) {
|
|
|
|
found_config_file = true;
|
|
|
|
} else {
|
|
|
|
found_format_file = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_config_file) {
|
2022-03-16 22:38:08 +00:00
|
|
|
rename(local_staging_path.c_str(), local_configs_path.c_str());
|
|
|
|
fprintf(stderr,
|
|
|
|
"info: installed configuration repo -- %s\n",
|
2020-10-21 05:55:46 +00:00
|
|
|
local_configs_path.c_str());
|
2020-05-07 14:08:59 +00:00
|
|
|
} else if (found_format_file) {
|
2022-03-16 22:38:08 +00:00
|
|
|
rename(local_staging_path.c_str(), local_formats_path.c_str());
|
|
|
|
fprintf(stderr,
|
|
|
|
"info: installed format repo -- %s\n",
|
2020-10-21 05:55:46 +00:00
|
|
|
local_formats_path.c_str());
|
2020-05-07 14:08:59 +00:00
|
|
|
} else {
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"error: cannot find a valid lnav configuration or format "
|
|
|
|
"file\n");
|
2020-05-07 14:08:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2015-08-10 04:03:23 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
bool
|
|
|
|
update_installs_from_git()
|
2018-11-09 17:45:19 +00:00
|
|
|
{
|
|
|
|
static_root_mem<glob_t, globfree> gl;
|
2021-05-16 05:39:18 +00:00
|
|
|
auto git_formats = lnav::paths::dotlnav() / "formats/*/.git";
|
2018-11-09 17:45:19 +00:00
|
|
|
bool found = false, retval = true;
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(git_formats.c_str(), GLOB_NOCHECK, nullptr, gl.inout()) == 0) {
|
2018-11-09 17:45:19 +00:00
|
|
|
for (int lpc = 0; lpc < (int) gl->gl_pathc; lpc++) {
|
2022-03-16 22:38:08 +00:00
|
|
|
char* git_dir = dirname(gl->gl_pathv[lpc]);
|
2018-11-09 17:45:19 +00:00
|
|
|
|
|
|
|
printf("Updating formats in %s\n", git_dir);
|
2022-03-25 23:38:11 +00:00
|
|
|
auto pull_cmd
|
|
|
|
= fmt::format(FMT_STRING("cd '{}' && git pull"), git_dir);
|
|
|
|
int ret = system(pull_cmd.c_str());
|
2018-11-09 17:45:19 +00:00
|
|
|
if (ret == -1) {
|
|
|
|
std::cerr << "Failed to spawn command "
|
2022-03-16 22:38:08 +00:00
|
|
|
<< "\"" << pull_cmd << "\": " << strerror(errno)
|
|
|
|
<< std::endl;
|
2018-11-09 17:45:19 +00:00
|
|
|
retval = false;
|
2022-03-16 22:38:08 +00:00
|
|
|
} else if (ret > 0) {
|
2018-11-09 17:45:19 +00:00
|
|
|
std::cerr << "Command "
|
2022-03-16 22:38:08 +00:00
|
|
|
<< "\"" << pull_cmd
|
|
|
|
<< "\" failed: " << strerror(errno) << std::endl;
|
2018-11-09 17:45:19 +00:00
|
|
|
retval = false;
|
|
|
|
}
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2022-03-16 22:38:08 +00:00
|
|
|
printf(
|
|
|
|
"No formats from git repositories found, "
|
|
|
|
"use 'lnav -i extra' to install third-party foramts\n");
|
2018-11-09 17:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static int
|
|
|
|
read_repo_path(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
2015-08-10 04:03:23 +00:00
|
|
|
{
|
2022-03-31 15:59:19 +00:00
|
|
|
auto path = std::string((const char*) str, len);
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2020-05-07 14:08:59 +00:00
|
|
|
install_from_git(path.c_str());
|
2015-08-10 04:03:23 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
static const struct json_path_container format_handlers = {
|
|
|
|
json_path_handler("format-repos#", read_repo_path),
|
|
|
|
};
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
install_extra_formats()
|
2015-08-10 04:03:23 +00:00
|
|
|
{
|
2021-05-16 05:39:18 +00:00
|
|
|
auto config_root = lnav::paths::dotlnav() / "remote-config";
|
2015-09-15 07:24:56 +00:00
|
|
|
auto_fd fd;
|
2015-08-10 04:03:23 +00:00
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (access(config_root.c_str(), R_OK) == 0) {
|
2015-08-10 04:03:23 +00:00
|
|
|
printf("Updating lnav remote config repo...\n");
|
2022-03-25 23:38:11 +00:00
|
|
|
auto pull_cmd = fmt::format(FMT_STRING("cd '{}' && git pull"),
|
|
|
|
config_root.string());
|
|
|
|
log_perror(system(pull_cmd.c_str()));
|
2022-03-16 22:38:08 +00:00
|
|
|
} else {
|
2015-08-10 04:03:23 +00:00
|
|
|
printf("Cloning lnav remote config repo...\n");
|
2022-03-25 23:38:11 +00:00
|
|
|
auto clone_cmd = fmt::format(
|
|
|
|
FMT_STRING(
|
|
|
|
"git clone https://github.com/tstack/lnav-config.git {}"),
|
|
|
|
config_root.string());
|
|
|
|
log_perror(system(clone_cmd.c_str()));
|
2015-08-10 04:03:23 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 05:18:32 +00:00
|
|
|
auto config_json = config_root / "remote-config.json";
|
2022-03-13 22:49:41 +00:00
|
|
|
if ((fd = lnav::filesystem::openp(config_json, O_RDONLY)) == -1) {
|
2015-08-10 04:03:23 +00:00
|
|
|
perror("Unable to open remote-config.json");
|
2022-03-16 22:38:08 +00:00
|
|
|
} else {
|
2022-04-30 20:05:42 +00:00
|
|
|
yajlpp_parse_context ypc_config(
|
|
|
|
intern_string::lookup(config_root.string()), &format_handlers);
|
2015-08-10 04:03:23 +00:00
|
|
|
auto_mem<yajl_handle_t> jhandle(yajl_free);
|
|
|
|
unsigned char buffer[4096];
|
|
|
|
ssize_t rc;
|
|
|
|
|
2019-07-30 05:18:32 +00:00
|
|
|
jhandle = yajl_alloc(&ypc_config.ypc_callbacks, nullptr, &ypc_config);
|
2015-08-10 04:03:23 +00:00
|
|
|
yajl_config(jhandle, yajl_allow_comments, 1);
|
|
|
|
while ((rc = read(fd, buffer, sizeof(buffer))) > 0) {
|
2022-03-16 22:38:08 +00:00
|
|
|
if (yajl_parse(jhandle, buffer, rc) != yajl_status_ok) {
|
2022-04-12 23:07:13 +00:00
|
|
|
auto* msg = yajl_get_error(jhandle, 1, buffer, rc);
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(
|
|
|
|
stderr, "Unable to parse remote-config.json -- %s", msg);
|
2020-12-31 23:24:28 +00:00
|
|
|
yajl_free_error(jhandle, msg);
|
2015-08-10 04:03:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2016-01-05 14:18:58 +00:00
|
|
|
if (yajl_complete_parse(jhandle) != yajl_status_ok) {
|
2022-04-12 23:07:13 +00:00
|
|
|
auto* msg = yajl_get_error(jhandle, 1, buffer, rc);
|
2020-12-31 23:24:28 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
fprintf(stderr, "Unable to parse remote-config.json -- %s", msg);
|
2020-12-31 23:24:28 +00:00
|
|
|
yajl_free_error(jhandle, msg);
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
2015-08-10 04:03:23 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-05 14:18:58 +00:00
|
|
|
|
|
|
|
struct userdata {
|
2022-04-12 23:07:13 +00:00
|
|
|
explicit userdata(std::vector<lnav::console::user_message>& errors)
|
|
|
|
: ud_errors(errors){};
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message>& ud_errors;
|
2016-01-05 14:18:58 +00:00
|
|
|
};
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static void
|
|
|
|
config_error_reporter(const yajlpp_parse_context& ypc,
|
2022-04-12 23:07:13 +00:00
|
|
|
const lnav::console::user_message& msg)
|
2019-05-03 20:50:19 +00:00
|
|
|
{
|
2022-04-12 23:07:13 +00:00
|
|
|
auto* ud = (userdata*) ypc.ypc_userdata;
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
ud->ud_errors.emplace_back(msg);
|
2019-05-03 20:50:19 +00:00
|
|
|
}
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container key_command_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("command")
|
2017-01-21 15:41:28 +00:00
|
|
|
.with_synopsis("<command>")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_description(
|
|
|
|
"The command to execute for the given key sequence. Use a script "
|
|
|
|
"to execute more complicated operations.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_pattern("^[:|;].*")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_example(":goto next hour")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&key_command::kc_cmd),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("alt-msg")
|
2019-05-23 13:28:42 +00:00
|
|
|
.with_synopsis("<msg>")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_description(
|
2022-03-16 22:38:08 +00:00
|
|
|
"The help message to display after the key is pressed.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field<>(&key_command::kc_alt_msg),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct json_path_container keymap_def_handlers = {
|
|
|
|
yajlpp::pattern_property_handler("(?<key_seq>(?:x[0-9a-f]{2})+)")
|
|
|
|
.with_synopsis("<utf8-key-code-in-hex>")
|
|
|
|
.with_description(
|
|
|
|
"Map of key codes to commands to execute. The field names are "
|
|
|
|
"the keys to be mapped using as a hexadecimal representation of "
|
|
|
|
"the UTF-8 encoding. Each byte of the UTF-8 should start with "
|
|
|
|
"an 'x' followed by the hexadecimal representation of the byte.")
|
|
|
|
.with_obj_provider<key_command, key_map>(
|
|
|
|
[](const yajlpp_provider_context& ypc, key_map* km) {
|
|
|
|
key_command& retval
|
|
|
|
= km->km_seq_to_cmd[ypc.ypc_extractor.get_substr(
|
|
|
|
"key_seq")];
|
|
|
|
|
|
|
|
return &retval;
|
|
|
|
})
|
|
|
|
.with_path_provider<key_map>(
|
|
|
|
[](key_map* km, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& iter : km->km_seq_to_cmd) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.with_children(key_command_handlers),
|
|
|
|
};
|
2022-03-16 22:38:08 +00:00
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
static const struct json_path_container keymap_defs_handlers = {
|
|
|
|
yajlpp::pattern_property_handler("(?<keymap_name>[\\w\\-]+)")
|
|
|
|
.with_description("The keymap definitions")
|
|
|
|
.with_obj_provider<key_map, _lnav_config>(
|
|
|
|
[](const yajlpp_provider_context& ypc, _lnav_config* root) {
|
|
|
|
key_map& retval
|
|
|
|
= root->lc_ui_keymaps[ypc.ypc_extractor.get_substr(
|
|
|
|
"keymap_name")];
|
|
|
|
return &retval;
|
|
|
|
})
|
|
|
|
.with_path_provider<_lnav_config>(
|
|
|
|
[](struct _lnav_config* cfg, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& iter : cfg->lc_ui_keymaps) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
|
|
|
})
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_children(keymap_def_handlers),
|
|
|
|
};
|
2017-01-21 15:41:28 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container global_var_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::pattern_property_handler("(?<var_name>\\w+)")
|
2017-03-01 16:44:16 +00:00
|
|
|
.with_synopsis("<name>")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description(
|
|
|
|
"A global variable definition. Global variables can be referenced "
|
|
|
|
"in scripts, SQL statements, or commands.")
|
|
|
|
.with_path_provider<_lnav_config>(
|
2022-03-31 15:59:19 +00:00
|
|
|
[](struct _lnav_config* cfg, std::vector<std::string>& paths_out) {
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& iter : cfg->lc_global_vars) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
2020-05-07 14:08:59 +00:00
|
|
|
})
|
2022-04-12 23:07:13 +00:00
|
|
|
.FOR_FIELD(_lnav_config, lc_global_vars),
|
|
|
|
};
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container style_config_handlers =
|
2020-05-07 14:08:59 +00:00
|
|
|
json_path_container{
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("color")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("#hex|color_name")
|
|
|
|
.with_description(
|
|
|
|
"The foreground color value for this style. The value can be "
|
|
|
|
"the name of an xterm color, the hexadecimal value, or a theme "
|
|
|
|
"variable reference.")
|
|
|
|
.with_example("#fff")
|
|
|
|
.with_example("Green")
|
|
|
|
.with_example("$black")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&style_config::sc_color),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("background-color")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("#hex|color_name")
|
|
|
|
.with_description(
|
2021-02-06 00:04:34 +00:00
|
|
|
"The background color value for this style. The value can be "
|
2020-05-07 14:08:59 +00:00
|
|
|
"the name of an xterm color, the hexadecimal value, or a theme "
|
|
|
|
"variable reference.")
|
|
|
|
.with_example("#2d2a2e")
|
|
|
|
.with_example("Green")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&style_config::sc_background_color),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("underline")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Indicates that the text should be underlined.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&style_config::sc_underline),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("bold")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Indicates that the text should be bolded.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&style_config::sc_bold),
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
|
|
|
.with_definition_id("style");
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container theme_styles_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("identifier")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for identifiers in logs")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_identifier;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("text")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for plain text")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_text;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("alt-text")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for plain text when alternating")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_alt_text;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("error")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for error messages")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_error;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("ok")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for success messages")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_ok;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("warning")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for warning messages")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_warning;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("hidden")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for hidden fields in logs")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_hidden;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("adjusted-time")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for timestamps that have been adjusted")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_adjusted_time;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("skewed-time")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_description(
|
|
|
|
"Styling for timestamps that are different from the received time")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_skewed_time;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("offset-time")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for hidden fields")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_offset_time;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-12-06 05:51:46 +00:00
|
|
|
yajlpp::property_handler("invalid-msg")
|
|
|
|
.with_description("Styling for invalid log messages")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_invalid_msg;
|
|
|
|
})
|
2020-12-06 05:51:46 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("popup")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for popup windows")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_popup;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2021-01-23 21:00:51 +00:00
|
|
|
yajlpp::property_handler("focused")
|
|
|
|
.with_description("Styling for a focused row in a list view")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_focused;
|
|
|
|
})
|
2021-01-23 21:00:51 +00:00
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("disabled-focused")
|
|
|
|
.with_description("Styling for a disabled focused row in a list view")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_disabled_focused;
|
|
|
|
})
|
2021-01-23 21:00:51 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("scrollbar")
|
2019-05-12 13:53:40 +00:00
|
|
|
.with_description("Styling for scrollbars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_scrollbar;
|
|
|
|
})
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h1")
|
|
|
|
.with_description("Styling for top-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[0];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h2")
|
|
|
|
.with_description("Styling for 2nd-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[1];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h3")
|
|
|
|
.with_description("Styling for 3rd-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[2];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h4")
|
|
|
|
.with_description("Styling for 4th-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[3];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h5")
|
|
|
|
.with_description("Styling for 5th-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[4];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("h6")
|
|
|
|
.with_description("Styling for 6th-level headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_header[5];
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-05-23 03:44:18 +00:00
|
|
|
yajlpp::property_handler("hr")
|
|
|
|
.with_description("Styling for horizontal rules")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_hr;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("hyperlink")
|
|
|
|
.with_description("Styling for hyperlinks")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_hyperlink;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-04-30 20:05:42 +00:00
|
|
|
yajlpp::property_handler("list-glyph")
|
|
|
|
.with_description("Styling for glyphs that prefix a list item")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_list_glyph;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-05-11 04:58:32 +00:00
|
|
|
yajlpp::property_handler("breadcrumb")
|
|
|
|
.with_description("Styling for the separator between breadcrumbs")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_breadcrumb;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-05-23 03:44:18 +00:00
|
|
|
yajlpp::property_handler("table-border")
|
|
|
|
.with_description("Styling for table borders")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_table_border;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("table-header")
|
|
|
|
.with_description("Styling for table headers")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_table_header;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("quote-border")
|
|
|
|
.with_description("Styling for quoted-block borders")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_quote_border;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("quoted-text")
|
|
|
|
.with_description("Styling for quoted text blocks")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_quoted_text;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("footnote-border")
|
|
|
|
.with_description("Styling for footnote borders")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_footnote_border;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("footnote-text")
|
|
|
|
.with_description("Styling for footnote text")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_footnote_text;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-06-11 15:39:02 +00:00
|
|
|
yajlpp::property_handler("snippet-border")
|
|
|
|
.with_description("Styling for snippet borders")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_snippet_border;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-04-12 23:07:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct json_path_container theme_syntax_styles_handlers = {
|
2022-05-23 03:44:18 +00:00
|
|
|
yajlpp::property_handler("quoted-code")
|
|
|
|
.with_description("Styling for quoted code blocks")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_quoted_code;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("code-border")
|
|
|
|
.with_description("Styling for quoted-code borders")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_code_border;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
2022-04-12 23:07:13 +00:00
|
|
|
yajlpp::property_handler("keyword")
|
|
|
|
.with_description("Styling for keywords in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_keyword;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("string")
|
|
|
|
.with_description("Styling for single/double-quoted strings in text")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_string;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("comment")
|
|
|
|
.with_description("Styling for comments in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_comment;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("doc-directive")
|
|
|
|
.with_description(
|
|
|
|
"Styling for documentation directives in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_doc_directive;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("variable")
|
|
|
|
.with_description("Styling for variables in text")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_variable;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("symbol")
|
|
|
|
.with_description("Styling for symbols in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_symbol;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("number")
|
|
|
|
.with_description("Styling for numbers in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_number;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("re-special")
|
|
|
|
.with_description(
|
|
|
|
"Styling for special characters in regular expressions")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_re_special;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("re-repeat")
|
|
|
|
.with_description("Styling for repeats in regular expressions")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_re_repeat;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
|
|
|
|
yajlpp::property_handler("diff-delete")
|
|
|
|
.with_description("Styling for deleted lines in diffs")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_diff_delete;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("diff-add")
|
|
|
|
.with_description("Styling for added lines in diffs")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_diff_add;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("diff-section")
|
|
|
|
.with_description("Styling for diffs")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_diff_section;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("file")
|
|
|
|
.with_description("Styling for file names in source files")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_file;
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
};
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container theme_status_styles_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("text")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("warn")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for warnings in status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_warn_status;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("alert")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for alerts in status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_alert_status;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("active")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for activity in status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_active_status;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2021-08-28 05:37:10 +00:00
|
|
|
yajlpp::property_handler("inactive-alert")
|
|
|
|
.with_description("Styling for inactive alert status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_inactive_alert_status;
|
|
|
|
})
|
2021-08-28 05:37:10 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("inactive")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for inactive status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_inactive_status;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:24:23 +00:00
|
|
|
yajlpp::property_handler("title-hotkey")
|
|
|
|
.with_description("Styling for hotkey highlights in titles")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status_title_hotkey;
|
|
|
|
})
|
2020-10-29 04:24:23 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("title")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for title sections of status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status_title;
|
|
|
|
})
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:24:23 +00:00
|
|
|
yajlpp::property_handler("disabled-title")
|
|
|
|
.with_description("Styling for title sections of status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status_disabled_title;
|
|
|
|
})
|
2020-10-29 04:24:23 +00:00
|
|
|
.with_children(style_config_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("subtitle")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_description("Styling for subtitle sections of status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status_subtitle;
|
|
|
|
})
|
2020-10-29 04:24:23 +00:00
|
|
|
.with_children(style_config_handlers),
|
|
|
|
yajlpp::property_handler("hotkey")
|
|
|
|
.with_description("Styling for hotkey highlights of status bars")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
return &root->lt_style_status_hotkey;
|
|
|
|
})
|
2020-10-29 04:24:23 +00:00
|
|
|
.with_children(style_config_handlers),
|
2019-05-03 20:50:19 +00:00
|
|
|
};
|
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
static const struct json_path_container theme_log_level_styles_handlers = {
|
|
|
|
yajlpp::pattern_property_handler(
|
|
|
|
"(?<level>trace|debug5|debug4|debug3|debug2|debug|info|stats|notice|"
|
|
|
|
"warning|error|critical|fatal|invalid)")
|
|
|
|
.with_obj_provider<style_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
style_config& sc = root->lt_level_styles[string2level(
|
|
|
|
ypc.ypc_extractor.get_substr_i("level").get())];
|
|
|
|
|
|
|
|
return ≻
|
|
|
|
})
|
|
|
|
.with_path_provider<lnav_theme>(
|
|
|
|
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
|
|
|
for (int lpc = LEVEL_TRACE; lpc < LEVEL__MAX; lpc++) {
|
|
|
|
paths_out.emplace_back(level_names[lpc]);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.with_children(style_config_handlers),
|
|
|
|
};
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container highlighter_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("pattern")
|
2020-10-29 04:19:57 +00:00
|
|
|
.with_synopsis("regular expression")
|
|
|
|
.with_description("The regular expression to highlight")
|
|
|
|
.FOR_FIELD(highlighter_config, hc_regex),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("style")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_description(
|
|
|
|
"The styling for the text that matches the associated pattern")
|
|
|
|
.with_obj_provider<style_config, highlighter_config>(
|
|
|
|
[](const yajlpp_provider_context& ypc, highlighter_config* root) {
|
|
|
|
return &root->hc_style;
|
|
|
|
})
|
2020-10-29 04:19:57 +00:00
|
|
|
.with_children(style_config_handlers),
|
|
|
|
};
|
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
static const struct json_path_container theme_highlights_handlers = {
|
2022-05-11 04:58:32 +00:00
|
|
|
yajlpp::pattern_property_handler("(?<highlight_name>[\\w\\-]+)")
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_obj_provider<highlighter_config, lnav_theme>(
|
|
|
|
[](const yajlpp_provider_context& ypc, lnav_theme* root) {
|
|
|
|
highlighter_config& hc
|
|
|
|
= root->lt_highlights[ypc.ypc_extractor
|
|
|
|
.get_substr_i("highlight_name")
|
|
|
|
.get()];
|
|
|
|
|
|
|
|
return &hc;
|
|
|
|
})
|
|
|
|
.with_path_provider<lnav_theme>(
|
|
|
|
[](struct lnav_theme* cfg, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& pair : cfg->lt_highlights) {
|
|
|
|
paths_out.emplace_back(pair.first);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.with_children(highlighter_handlers),
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct json_path_container theme_vars_handlers = {
|
|
|
|
yajlpp::pattern_property_handler("(?<var_name>\\w+)")
|
|
|
|
.with_synopsis("name")
|
|
|
|
.with_description("A theme variable definition")
|
|
|
|
.with_path_provider<lnav_theme>(
|
|
|
|
[](struct lnav_theme* lt, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& iter : lt->lt_vars) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.FOR_FIELD(lnav_theme, lt_vars),
|
|
|
|
};
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container theme_def_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("vars")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Variables definitions that are used in this theme.")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(theme_vars_handlers),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("styles")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Styles for log messages.")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(theme_styles_handlers),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("syntax-styles")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Styles for syntax highlighting in text files.")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(theme_syntax_styles_handlers),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("status-styles")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Styles for the user-interface components.")
|
2019-05-03 20:50:19 +00:00
|
|
|
.with_children(theme_status_styles_handlers),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("log-level-styles")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Styles for each log message level.")
|
2020-10-29 04:19:57 +00:00
|
|
|
.with_children(theme_log_level_styles_handlers),
|
|
|
|
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("highlights")
|
2020-10-29 04:19:57 +00:00
|
|
|
.with_description("Styles for text highlights.")
|
|
|
|
.with_children(theme_highlights_handlers),
|
2019-05-03 20:50:19 +00:00
|
|
|
};
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
static const struct json_path_container theme_defs_handlers = {
|
|
|
|
yajlpp::pattern_property_handler("(?<theme_name>[\\w\\-]+)")
|
|
|
|
.with_description("Theme definitions")
|
|
|
|
.with_obj_provider<lnav_theme, _lnav_config>(
|
|
|
|
[](const yajlpp_provider_context& ypc, _lnav_config* root) {
|
|
|
|
lnav_theme& lt
|
|
|
|
= root->lc_ui_theme_defs[ypc.ypc_extractor.get_substr(
|
|
|
|
"theme_name")];
|
2022-03-16 22:38:08 +00:00
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
return <
|
|
|
|
})
|
|
|
|
.with_path_provider<_lnav_config>(
|
|
|
|
[](struct _lnav_config* cfg, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& iter : cfg->lc_ui_theme_defs) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
|
|
|
})
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_children(theme_def_handlers),
|
|
|
|
};
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container ui_handlers = {
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("clock-format")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("format")
|
|
|
|
.with_description("The format for the clock displayed in "
|
|
|
|
"the top-left corner using strftime(3) conversions")
|
|
|
|
.with_example("%a %b %d %H:%M:%S %Z")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&_lnav_config::lc_ui_clock_format),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("dim-text")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("bool")
|
|
|
|
.with_description("Reduce the brightness of text (useful for xterms). "
|
|
|
|
"This setting can be useful when running in an xterm "
|
|
|
|
"where the white color is very bright.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&_lnav_config::lc_ui_dim_text),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("default-colors")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("bool")
|
|
|
|
.with_description(
|
|
|
|
"Use default terminal background and foreground colors "
|
|
|
|
"instead of black and white for all text coloring. This setting "
|
|
|
|
"can be useful when transparent background or alternate color "
|
|
|
|
"theme terminal is used.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&_lnav_config::lc_ui_default_colors),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("keymap")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("keymap_name")
|
|
|
|
.with_description("The name of the keymap to use.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&_lnav_config::lc_ui_keymap),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("theme")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_synopsis("theme_name")
|
|
|
|
.with_description("The name of the theme to use.")
|
2022-04-12 23:07:13 +00:00
|
|
|
.for_field(&_lnav_config::lc_ui_theme),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("theme-defs")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Theme definitions.")
|
|
|
|
.with_children(theme_defs_handlers),
|
2020-10-29 04:23:25 +00:00
|
|
|
yajlpp::property_handler("keymap-defs")
|
2020-05-07 14:08:59 +00:00
|
|
|
.with_description("Keymap definitions.")
|
2021-01-17 06:23:20 +00:00
|
|
|
.with_children(keymap_defs_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container archive_handlers = {
|
2021-01-23 21:00:51 +00:00
|
|
|
yajlpp::property_handler("min-free-space")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_synopsis("<bytes>")
|
2021-02-08 05:30:02 +00:00
|
|
|
.with_description(
|
|
|
|
"The minimum free space, in bytes, to maintain when unpacking "
|
|
|
|
"archives")
|
2021-01-23 21:00:51 +00:00
|
|
|
.with_min_value(0)
|
|
|
|
.for_field(&_lnav_config::lc_archive_manager,
|
|
|
|
&archive_manager::config::amc_min_free_space),
|
2021-01-17 06:23:20 +00:00
|
|
|
yajlpp::property_handler("cache-ttl")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_synopsis("<duration>")
|
2021-02-08 05:30:02 +00:00
|
|
|
.with_description(
|
|
|
|
"The time-to-live for unpacked archives, expressed as a duration "
|
|
|
|
"(e.g. '3d' for three days)")
|
2021-02-15 06:44:14 +00:00
|
|
|
.with_example("3d")
|
|
|
|
.with_example("12h")
|
2021-01-17 06:23:20 +00:00
|
|
|
.for_field(&_lnav_config::lc_archive_manager,
|
|
|
|
&archive_manager::config::amc_cache_ttl),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container file_vtab_handlers = {
|
2021-03-06 00:17:28 +00:00
|
|
|
yajlpp::property_handler("max-content-size")
|
|
|
|
.with_synopsis("<bytes>")
|
|
|
|
.with_description(
|
|
|
|
"The maximum allowed file size for the content column")
|
|
|
|
.with_min_value(0)
|
|
|
|
.for_field(&_lnav_config::lc_file_vtab,
|
|
|
|
&file_vtab::config::fvc_max_content_size),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container logfile_handlers = {
|
2021-03-30 05:40:22 +00:00
|
|
|
yajlpp::property_handler("max-unrecognized-lines")
|
|
|
|
.with_synopsis("<lines>")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_description("The maximum number of lines in a file to use when "
|
|
|
|
"detecting the format")
|
2021-03-30 05:40:22 +00:00
|
|
|
.with_min_value(1)
|
|
|
|
.for_field(&_lnav_config::lc_logfile,
|
|
|
|
&lnav::logfile::config::lc_max_unrecognized_lines),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container ssh_config_handlers = {
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::pattern_property_handler("(?<config_name>\\w+)")
|
|
|
|
.with_synopsis("name")
|
|
|
|
.with_description("Set an SSH configuration value")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_path_provider<_lnav_config>(
|
|
|
|
[](auto* m, std::vector<std::string>& paths_out) {
|
|
|
|
for (const auto& pair : m->lc_tailer.c_ssh_config) {
|
|
|
|
paths_out.emplace_back(pair.first);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_ssh_config),
|
2021-05-20 05:05:21 +00:00
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container ssh_option_handlers = {
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::pattern_property_handler("(?<option_name>\\w+)")
|
|
|
|
.with_synopsis("name")
|
|
|
|
.with_description("Set an option to be passed to the SSH command")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_ssh_options),
|
2021-05-20 05:05:21 +00:00
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container ssh_handlers = {
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::property_handler("command")
|
|
|
|
.with_synopsis("ssh-command")
|
|
|
|
.with_description("The SSH command to execute")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_ssh_cmd),
|
2021-06-02 05:57:32 +00:00
|
|
|
yajlpp::property_handler("transfer-command")
|
|
|
|
.with_synopsis("command")
|
|
|
|
.with_description(
|
|
|
|
"Command executed on the remote host when transferring the file")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_transfer_cmd),
|
2021-06-02 05:57:32 +00:00
|
|
|
yajlpp::property_handler("start-command")
|
|
|
|
.with_synopsis("command")
|
|
|
|
.with_description(
|
|
|
|
"Command executed on the remote host to start the tailer")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_start_cmd),
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::property_handler("flags")
|
|
|
|
.with_description("The flags to pass to the SSH command")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_ssh_flags),
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::property_handler("options")
|
|
|
|
.with_description("The options to pass to the SSH command")
|
|
|
|
.with_children(ssh_option_handlers),
|
|
|
|
yajlpp::property_handler("config")
|
|
|
|
.with_description(
|
|
|
|
"The ssh_config options to pass to SSH with the -o option")
|
|
|
|
.with_children(ssh_config_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container remote_handlers = {
|
2021-09-11 04:01:25 +00:00
|
|
|
yajlpp::property_handler("cache-ttl")
|
|
|
|
.with_synopsis("<duration>")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_description("The time-to-live for files copied from remote "
|
|
|
|
"hosts, expressed as a duration "
|
|
|
|
"(e.g. '3d' for three days)")
|
2021-09-11 04:01:25 +00:00
|
|
|
.with_example("3d")
|
|
|
|
.with_example("12h")
|
2022-03-16 22:38:08 +00:00
|
|
|
.for_field(&_lnav_config::lc_tailer, &tailer::config::c_cache_ttl),
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::property_handler("ssh")
|
|
|
|
.with_description(
|
|
|
|
"Settings related to the ssh command used to contact remote "
|
|
|
|
"machines")
|
|
|
|
.with_children(ssh_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container sysclip_impl_cmd_handlers = json_path_container{
|
2021-09-16 04:29:55 +00:00
|
|
|
yajlpp::property_handler("write")
|
|
|
|
.with_synopsis("<command>")
|
|
|
|
.with_description("The command used to write to the clipboard")
|
|
|
|
.with_example("pbcopy")
|
|
|
|
.for_field(&sysclip::clip_commands::cc_write),
|
|
|
|
yajlpp::property_handler("read")
|
|
|
|
.with_synopsis("<command>")
|
|
|
|
.with_description("The command used to read from the clipboard")
|
|
|
|
.with_example("pbpaste")
|
|
|
|
.for_field(&sysclip::clip_commands::cc_read),
|
|
|
|
}
|
2021-10-18 16:03:12 +00:00
|
|
|
.with_description("Container for the commands used to read from and write to the system clipboard")
|
2021-09-16 04:29:55 +00:00
|
|
|
.with_definition_id("clip-commands");
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container sysclip_impl_handlers = {
|
2021-09-16 04:29:55 +00:00
|
|
|
yajlpp::property_handler("test")
|
|
|
|
.with_synopsis("<command>")
|
|
|
|
.with_description("The command that checks")
|
|
|
|
.with_example("command -v pbcopy")
|
|
|
|
.for_field(&sysclip::clipboard::c_test_command),
|
|
|
|
yajlpp::property_handler("general")
|
|
|
|
.with_description("Commands to work with the general clipboard")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<sysclip::clip_commands, sysclip::clipboard>(
|
|
|
|
[](const yajlpp_provider_context& ypc, sysclip::clipboard* root) {
|
|
|
|
return &root->c_general;
|
|
|
|
})
|
2021-09-16 04:29:55 +00:00
|
|
|
.with_children(sysclip_impl_cmd_handlers),
|
|
|
|
yajlpp::property_handler("find")
|
|
|
|
.with_description("Commands to work with the find clipboard")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<sysclip::clip_commands, sysclip::clipboard>(
|
|
|
|
[](const yajlpp_provider_context& ypc, sysclip::clipboard* root) {
|
|
|
|
return &root->c_find;
|
|
|
|
})
|
2021-09-16 04:29:55 +00:00
|
|
|
.with_children(sysclip_impl_cmd_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container sysclip_impls_handlers = {
|
2021-09-16 04:29:55 +00:00
|
|
|
yajlpp::pattern_property_handler("(?<clipboard_impl_name>[\\w\\-]+)")
|
|
|
|
.with_synopsis("<name>")
|
|
|
|
.with_description("Clipboard implementation")
|
2022-03-16 22:38:08 +00:00
|
|
|
.with_obj_provider<sysclip::clipboard, _lnav_config>(
|
|
|
|
[](const yajlpp_provider_context& ypc, _lnav_config* root) {
|
|
|
|
auto& retval
|
|
|
|
= root->lc_sysclip
|
|
|
|
.c_clipboard_impls[ypc.ypc_extractor.get_substr(
|
|
|
|
"clipboard_impl_name")];
|
|
|
|
return &retval;
|
|
|
|
})
|
|
|
|
.with_path_provider<_lnav_config>(
|
2022-03-31 15:59:19 +00:00
|
|
|
[](struct _lnav_config* cfg, std::vector<std::string>& paths_out) {
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& iter : cfg->lc_sysclip.c_clipboard_impls) {
|
|
|
|
paths_out.emplace_back(iter.first);
|
|
|
|
}
|
|
|
|
})
|
2021-09-16 04:29:55 +00:00
|
|
|
.with_children(sysclip_impl_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container sysclip_handlers = {
|
2021-09-16 04:29:55 +00:00
|
|
|
yajlpp::property_handler("impls")
|
|
|
|
.with_description("Clipboard implementations")
|
|
|
|
.with_children(sysclip_impls_handlers),
|
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
static const struct json_path_container tuning_handlers = {
|
2021-01-17 06:23:20 +00:00
|
|
|
yajlpp::property_handler("archive-manager")
|
|
|
|
.with_description("Settings related to opening archive files")
|
|
|
|
.with_children(archive_handlers),
|
2021-03-06 00:17:28 +00:00
|
|
|
yajlpp::property_handler("file-vtab")
|
|
|
|
.with_description("Settings related to the lnav_file virtual-table")
|
|
|
|
.with_children(file_vtab_handlers),
|
2021-03-30 05:40:22 +00:00
|
|
|
yajlpp::property_handler("logfile")
|
|
|
|
.with_description("Settings related to log files")
|
|
|
|
.with_children(logfile_handlers),
|
2021-05-20 05:05:21 +00:00
|
|
|
yajlpp::property_handler("remote")
|
|
|
|
.with_description("Settings related to remote file support")
|
|
|
|
.with_children(remote_handlers),
|
2021-09-16 04:29:55 +00:00
|
|
|
yajlpp::property_handler("clipboard")
|
|
|
|
.with_description("Settings related to the clipboard")
|
|
|
|
.with_children(sysclip_handlers),
|
2021-01-17 06:23:20 +00:00
|
|
|
};
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
const char* DEFAULT_CONFIG_SCHEMA
|
|
|
|
= "https://lnav.org/schemas/config-v1.schema.json";
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
static const std::set<std::string> SUPPORTED_CONFIG_SCHEMAS = {
|
2022-04-12 23:07:13 +00:00
|
|
|
DEFAULT_CONFIG_SCHEMA,
|
2016-01-05 14:18:58 +00:00
|
|
|
};
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
const char* DEFAULT_FORMAT_SCHEMA
|
|
|
|
= "https://lnav.org/schemas/format-v1.schema.json";
|
2020-12-11 06:32:01 +00:00
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
const std::set<std::string> SUPPORTED_FORMAT_SCHEMAS = {
|
2020-12-11 06:32:01 +00:00
|
|
|
DEFAULT_FORMAT_SCHEMA,
|
2020-12-11 05:18:56 +00:00
|
|
|
};
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static int
|
|
|
|
read_id(yajlpp_parse_context* ypc, const unsigned char* str, size_t len)
|
2020-05-07 14:08:59 +00:00
|
|
|
{
|
2022-03-31 15:59:19 +00:00
|
|
|
auto file_id = std::string((const char*) str, len);
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2020-12-11 05:18:56 +00:00
|
|
|
if (SUPPORTED_CONFIG_SCHEMAS.count(file_id) == 0) {
|
2022-04-12 23:07:13 +00:00
|
|
|
const auto* handler = ypc->ypc_current_handler;
|
|
|
|
attr_line_t notes{"expecting one of the following $schema values:"};
|
|
|
|
|
|
|
|
for (const auto& schema : SUPPORTED_CONFIG_SCHEMAS) {
|
|
|
|
notes.append("\n").append(
|
|
|
|
lnav::roles::symbol(fmt::format(FMT_STRING(" {}"), schema)));
|
|
|
|
}
|
2020-12-11 05:18:56 +00:00
|
|
|
ypc->report_error(
|
2022-04-12 23:07:13 +00:00
|
|
|
lnav::console::user_message::error(
|
|
|
|
attr_line_t("'")
|
|
|
|
.append(lnav::roles::symbol(file_id))
|
|
|
|
.append(
|
|
|
|
"' is not a supported configuration $schema version"))
|
|
|
|
.with_snippet(ypc->get_snippet())
|
|
|
|
.with_note(notes)
|
|
|
|
.with_help(handler->get_help_text(ypc)));
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-03-26 04:32:43 +00:00
|
|
|
const json_path_container lnav_config_handlers = json_path_container {
|
2022-03-25 23:38:11 +00:00
|
|
|
json_path_handler("$schema", read_id)
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_synopsis("<schema-uri>")
|
|
|
|
.with_description("The URI that specifies the schema that describes this type of file")
|
|
|
|
.with_example(DEFAULT_CONFIG_SCHEMA),
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
yajlpp::property_handler("tuning")
|
|
|
|
.with_description("Internal settings")
|
|
|
|
.with_children(tuning_handlers),
|
2021-01-17 06:23:20 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
yajlpp::property_handler("ui")
|
|
|
|
.with_description("User-interface settings")
|
|
|
|
.with_children(ui_handlers),
|
2019-05-15 16:13:56 +00:00
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
yajlpp::property_handler("global")
|
|
|
|
.with_description("Global variable definitions")
|
|
|
|
.with_children(global_var_handlers),
|
|
|
|
}
|
|
|
|
.with_schema_id(*SUPPORTED_CONFIG_SCHEMAS.cbegin());
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2020-09-04 21:39:04 +00:00
|
|
|
class active_key_map_listener : public lnav_config_listener {
|
|
|
|
public:
|
2022-03-16 22:38:08 +00:00
|
|
|
void reload_config(error_reporter& reporter) override
|
2020-09-04 21:39:04 +00:00
|
|
|
{
|
|
|
|
lnav_config.lc_active_keymap = lnav_config.lc_ui_keymaps["default"];
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& pair :
|
|
|
|
lnav_config.lc_ui_keymaps[lnav_config.lc_ui_keymap].km_seq_to_cmd)
|
|
|
|
{
|
|
|
|
lnav_config.lc_active_keymap.km_seq_to_cmd[pair.first]
|
|
|
|
= pair.second;
|
2020-09-04 21:39:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static active_key_map_listener KEYMAP_LISTENER;
|
|
|
|
|
2020-05-07 14:08:59 +00:00
|
|
|
Result<config_file_type, std::string>
|
2022-03-16 22:38:08 +00:00
|
|
|
detect_config_file_type(const ghc::filesystem::path& path)
|
2020-05-07 14:08:59 +00:00
|
|
|
{
|
2022-03-16 22:38:08 +00:00
|
|
|
static const char* id_path[] = {"$schema", nullptr};
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
auto content = TRY(lnav::filesystem::read_file(path));
|
2020-05-07 14:08:59 +00:00
|
|
|
if (startswith(content, "#")) {
|
|
|
|
content.insert(0, "//");
|
|
|
|
}
|
|
|
|
|
|
|
|
char error_buffer[1024];
|
2022-03-31 15:59:19 +00:00
|
|
|
auto content_tree = std::unique_ptr<yajl_val_s, decltype(&yajl_tree_free)>(
|
2020-05-07 14:08:59 +00:00
|
|
|
yajl_tree_parse(content.c_str(), error_buffer, sizeof(error_buffer)),
|
|
|
|
yajl_tree_free);
|
|
|
|
if (content_tree == nullptr) {
|
2022-04-12 23:07:13 +00:00
|
|
|
return Err(
|
|
|
|
fmt::format(FMT_STRING("JSON parsing failed -- {}"), error_buffer));
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
|
|
|
|
2022-03-29 05:00:49 +00:00
|
|
|
auto* id_val = yajl_tree_get(content_tree.get(), id_path, yajl_t_string);
|
2020-05-07 14:08:59 +00:00
|
|
|
if (id_val != nullptr) {
|
2020-12-11 05:18:56 +00:00
|
|
|
if (SUPPORTED_CONFIG_SCHEMAS.count(id_val->u.string)) {
|
2020-05-07 14:08:59 +00:00
|
|
|
return Ok(config_file_type::CONFIG);
|
2022-03-29 05:00:49 +00:00
|
|
|
}
|
|
|
|
if (SUPPORTED_FORMAT_SCHEMAS.count(id_val->u.string)) {
|
2020-12-11 05:18:56 +00:00
|
|
|
return Ok(config_file_type::FORMAT);
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
2022-03-29 05:00:49 +00:00
|
|
|
return Err(fmt::format(
|
2022-04-12 23:07:13 +00:00
|
|
|
FMT_STRING("unsupported configuration version in file -- {}"),
|
2022-03-29 05:00:49 +00:00
|
|
|
id_val->u.string));
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
2022-04-12 23:07:13 +00:00
|
|
|
return Ok(config_file_type::FORMAT);
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static void
|
|
|
|
load_config_from(_lnav_config& lconfig,
|
|
|
|
const ghc::filesystem::path& path,
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message>& errors)
|
2016-01-05 14:18:58 +00:00
|
|
|
{
|
2022-04-30 20:05:42 +00:00
|
|
|
yajlpp_parse_context ypc(intern_string::lookup(path.string()),
|
|
|
|
&lnav_config_handlers);
|
2016-01-05 14:18:58 +00:00
|
|
|
struct userdata ud(errors);
|
|
|
|
auto_fd fd;
|
|
|
|
|
2019-05-03 20:50:19 +00:00
|
|
|
ypc.ypc_locations = &lnav_config_locations;
|
2021-08-16 05:58:58 +00:00
|
|
|
ypc.with_obj(lconfig);
|
2016-01-05 14:18:58 +00:00
|
|
|
ypc.ypc_userdata = &ud;
|
2019-05-04 14:07:39 +00:00
|
|
|
ypc.with_error_reporter(config_error_reporter);
|
2022-03-13 22:49:41 +00:00
|
|
|
if ((fd = lnav::filesystem::openp(path, O_RDONLY)) == -1) {
|
2016-01-05 14:18:58 +00:00
|
|
|
if (errno != ENOENT) {
|
2022-04-12 23:07:13 +00:00
|
|
|
errors.emplace_back(
|
|
|
|
lnav::console::user_message::error(
|
|
|
|
attr_line_t("unable to open configuration file: ")
|
|
|
|
.append(lnav::roles::file(path)))
|
|
|
|
.with_errno_reason());
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
2022-03-16 22:38:08 +00:00
|
|
|
} else {
|
2016-01-05 14:18:58 +00:00
|
|
|
auto_mem<yajl_handle_t> handle(yajl_free);
|
|
|
|
char buffer[2048];
|
|
|
|
ssize_t rc = -1;
|
|
|
|
|
2019-07-30 05:18:32 +00:00
|
|
|
handle = yajl_alloc(&ypc.ypc_callbacks, nullptr, &ypc);
|
2016-01-05 14:18:58 +00:00
|
|
|
yajl_config(handle, yajl_allow_comments, 1);
|
2019-05-03 20:50:19 +00:00
|
|
|
yajl_config(handle, yajl_allow_multiple_values, 1);
|
|
|
|
ypc.ypc_handle = handle;
|
2016-01-05 14:18:58 +00:00
|
|
|
while (true) {
|
|
|
|
rc = read(fd, buffer, sizeof(buffer));
|
|
|
|
if (rc == 0) {
|
|
|
|
break;
|
2022-04-12 23:07:13 +00:00
|
|
|
}
|
|
|
|
if (rc == -1) {
|
2022-03-25 23:38:11 +00:00
|
|
|
errors.emplace_back(
|
2022-04-12 23:07:13 +00:00
|
|
|
lnav::console::user_message::error(
|
|
|
|
attr_line_t("unable to read format file: ")
|
|
|
|
.append(lnav::roles::file(path)))
|
|
|
|
.with_errno_reason());
|
2016-01-05 14:18:58 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-03-16 22:38:08 +00:00
|
|
|
if (ypc.parse((const unsigned char*) buffer, rc) != yajl_status_ok)
|
|
|
|
{
|
2016-01-05 14:18:58 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rc == 0) {
|
2019-05-04 14:07:39 +00:00
|
|
|
ypc.complete_parse();
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static void
|
|
|
|
load_default_config(struct _lnav_config& config_obj,
|
|
|
|
const std::string& path,
|
|
|
|
const bin_src_file& bsf,
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message>& errors)
|
2016-01-05 14:18:58 +00:00
|
|
|
{
|
2022-04-30 20:05:42 +00:00
|
|
|
yajlpp_parse_context ypc_builtin(intern_string::lookup(bsf.get_name()),
|
|
|
|
&lnav_config_handlers);
|
2016-01-05 14:18:58 +00:00
|
|
|
auto_mem<yajl_handle_t> handle(yajl_free);
|
|
|
|
struct userdata ud(errors);
|
|
|
|
|
2019-07-30 05:18:32 +00:00
|
|
|
handle = yajl_alloc(&ypc_builtin.ypc_callbacks, nullptr, &ypc_builtin);
|
2019-05-15 16:13:56 +00:00
|
|
|
ypc_builtin.ypc_locations = &lnav_config_locations;
|
2019-05-03 20:50:19 +00:00
|
|
|
ypc_builtin.with_handle(handle);
|
2016-01-05 14:18:58 +00:00
|
|
|
ypc_builtin.with_obj(config_obj);
|
2019-05-03 20:50:19 +00:00
|
|
|
ypc_builtin.with_error_reporter(config_error_reporter);
|
2016-01-05 14:18:58 +00:00
|
|
|
ypc_builtin.ypc_userdata = &ud;
|
2019-05-15 16:13:56 +00:00
|
|
|
|
|
|
|
if (path != "*") {
|
|
|
|
ypc_builtin.ypc_ignore_unused = true;
|
|
|
|
ypc_builtin.ypc_active_paths.insert(path);
|
|
|
|
}
|
|
|
|
|
2016-01-05 14:18:58 +00:00
|
|
|
yajl_config(handle, yajl_allow_comments, 1);
|
2019-05-03 20:50:19 +00:00
|
|
|
yajl_config(handle, yajl_allow_multiple_values, 1);
|
2020-12-30 21:49:29 +00:00
|
|
|
if (ypc_builtin.parse(bsf.to_string_fragment()) == yajl_status_ok) {
|
2019-05-04 14:07:39 +00:00
|
|
|
ypc_builtin.complete_parse();
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
static void
|
|
|
|
load_default_configs(struct _lnav_config& config_obj,
|
|
|
|
const std::string& path,
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message>& errors)
|
2016-01-05 14:18:58 +00:00
|
|
|
{
|
2020-12-30 21:49:29 +00:00
|
|
|
for (auto& bsf : lnav_config_json) {
|
|
|
|
load_default_config(config_obj, path, bsf, errors);
|
2017-01-21 15:41:28 +00:00
|
|
|
}
|
2019-05-15 16:13:56 +00:00
|
|
|
}
|
2017-01-21 15:41:28 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
2022-03-31 15:59:19 +00:00
|
|
|
load_config(const std::vector<ghc::filesystem::path>& extra_paths,
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message>& errors)
|
2019-05-15 16:13:56 +00:00
|
|
|
{
|
2021-05-16 05:39:18 +00:00
|
|
|
auto user_config = lnav::paths::dotlnav() / "config.json";
|
2018-05-25 13:32:01 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
for (auto& bsf : lnav_config_json) {
|
2022-03-16 22:38:08 +00:00
|
|
|
auto sample_path = lnav::paths::dotlnav() / "configs" / "default"
|
2022-03-29 05:00:49 +00:00
|
|
|
/ fmt::format(FMT_STRING("{}.sample"), bsf.get_name());
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
auto fd = auto_fd(lnav::filesystem::openp(
|
|
|
|
sample_path, O_WRONLY | O_TRUNC | O_CREAT, 0644));
|
2020-12-30 21:49:29 +00:00
|
|
|
auto sf = bsf.to_string_fragment();
|
|
|
|
if (fd == -1 || write(fd.get(), sf.data(), sf.length()) == -1) {
|
2021-03-20 20:39:35 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"error:unable to write default config file: %s -- %s\n",
|
|
|
|
sample_path.c_str(),
|
|
|
|
strerror(errno));
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-21 15:41:28 +00:00
|
|
|
{
|
2020-12-30 21:49:29 +00:00
|
|
|
load_default_configs(lnav_default_config, "*", errors);
|
|
|
|
load_default_configs(lnav_config, "*", errors);
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& extra_path : extra_paths) {
|
2020-05-07 14:08:59 +00:00
|
|
|
auto config_path = extra_path / "configs/*/*.json";
|
2019-05-03 20:50:19 +00:00
|
|
|
static_root_mem<glob_t, globfree> gl;
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(config_path.c_str(), 0, nullptr, gl.inout()) == 0) {
|
2020-05-07 14:08:59 +00:00
|
|
|
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
2021-08-16 05:58:58 +00:00
|
|
|
load_config_from(lnav_config, gl->gl_pathv[lpc], errors);
|
|
|
|
if (errors.empty()) {
|
2022-03-16 22:38:08 +00:00
|
|
|
load_config_from(
|
|
|
|
lnav_default_config, gl->gl_pathv[lpc], errors);
|
2021-08-16 05:58:58 +00:00
|
|
|
}
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-16 22:38:08 +00:00
|
|
|
for (const auto& extra_path : extra_paths) {
|
2020-05-07 14:08:59 +00:00
|
|
|
auto config_path = extra_path / "formats/*/config.*.json";
|
|
|
|
static_root_mem<glob_t, globfree> gl;
|
2019-05-03 20:50:19 +00:00
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
if (glob(config_path.c_str(), 0, nullptr, gl.inout()) == 0) {
|
2020-05-07 14:08:59 +00:00
|
|
|
for (size_t lpc = 0; lpc < gl->gl_pathc; lpc++) {
|
2021-08-16 05:58:58 +00:00
|
|
|
load_config_from(lnav_config, gl->gl_pathv[lpc], errors);
|
|
|
|
if (errors.empty()) {
|
2022-03-16 22:38:08 +00:00
|
|
|
load_config_from(
|
|
|
|
lnav_default_config, gl->gl_pathv[lpc], errors);
|
2021-08-16 05:58:58 +00:00
|
|
|
}
|
2019-05-03 20:50:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-16 05:58:58 +00:00
|
|
|
load_config_from(lnav_config, user_config, errors);
|
2017-01-21 15:41:28 +00:00
|
|
|
}
|
2016-05-02 03:35:37 +00:00
|
|
|
|
2019-05-03 20:50:19 +00:00
|
|
|
reload_config(errors);
|
|
|
|
|
|
|
|
rollback_lnav_config = lnav_config;
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
|
|
|
reset_config(const std::string& path)
|
2016-01-05 14:18:58 +00:00
|
|
|
{
|
2022-04-12 23:07:13 +00:00
|
|
|
std::vector<lnav::console::user_message> errors;
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2020-12-30 21:49:29 +00:00
|
|
|
load_default_configs(lnav_config, path, errors);
|
2019-05-03 20:50:19 +00:00
|
|
|
|
|
|
|
reload_config(errors);
|
2020-05-07 14:08:59 +00:00
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
for (const auto& err : errors) {
|
|
|
|
log_debug("reset %s", err.um_message.get_string().c_str());
|
2020-05-07 14:08:59 +00:00
|
|
|
}
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
|
|
|
|
2022-03-31 15:59:19 +00:00
|
|
|
std::string
|
2022-03-16 22:38:08 +00:00
|
|
|
save_config()
|
2016-01-05 14:18:58 +00:00
|
|
|
{
|
2019-05-08 12:30:59 +00:00
|
|
|
yajlpp_gen gen;
|
2022-03-29 05:00:49 +00:00
|
|
|
auto filename = fmt::format(FMT_STRING("config.json.{}.tmp"), getpid());
|
2021-05-16 05:39:18 +00:00
|
|
|
auto user_config_tmp = lnav::paths::dotlnav() / filename;
|
|
|
|
auto user_config = lnav::paths::dotlnav() / "config.json";
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2019-05-08 12:30:59 +00:00
|
|
|
yajl_gen_config(gen, yajl_gen_beautify, true);
|
|
|
|
yajlpp_gen_context ygc(gen, lnav_config_handlers);
|
2022-03-31 15:59:19 +00:00
|
|
|
std::vector<std::string> errors;
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
ygc.with_default_obj(lnav_default_config).with_obj(lnav_config);
|
2019-05-08 12:30:59 +00:00
|
|
|
ygc.gen();
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2019-05-08 12:30:59 +00:00
|
|
|
{
|
|
|
|
auto_fd fd;
|
2016-01-05 14:18:58 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
if ((fd = lnav::filesystem::openp(
|
|
|
|
user_config_tmp, O_WRONLY | O_CREAT | O_TRUNC, 0600))
|
|
|
|
== -1)
|
|
|
|
{
|
|
|
|
return "error: unable to save configuration -- "
|
2022-03-31 15:59:19 +00:00
|
|
|
+ std::string(strerror(errno));
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
2022-03-29 05:00:49 +00:00
|
|
|
|
|
|
|
string_fragment bits = gen.to_string_fragment();
|
|
|
|
|
|
|
|
log_perror(write(fd, bits.data(), bits.length()));
|
2016-01-05 14:18:58 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
rename(user_config_tmp.c_str(), user_config.c_str());
|
2019-05-08 12:30:59 +00:00
|
|
|
|
2016-01-05 14:18:58 +00:00
|
|
|
return "info: configuration saved";
|
|
|
|
}
|
2016-05-02 03:35:37 +00:00
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
void
|
2022-04-12 23:07:13 +00:00
|
|
|
reload_config(std::vector<lnav::console::user_message>& errors)
|
2016-05-02 03:35:37 +00:00
|
|
|
{
|
2022-03-16 22:38:08 +00:00
|
|
|
lnav_config_listener* curr = lnav_config_listener::LISTENER_LIST;
|
2016-05-02 03:35:37 +00:00
|
|
|
|
2020-10-21 05:55:46 +00:00
|
|
|
while (curr != nullptr) {
|
2022-03-16 22:38:08 +00:00
|
|
|
auto reporter = [&errors](const void* cfg_value,
|
|
|
|
const std::string& errmsg) {
|
2019-05-03 20:50:19 +00:00
|
|
|
auto cb = [&cfg_value, &errors, &errmsg](
|
2022-03-16 22:38:08 +00:00
|
|
|
const json_path_handler_base& jph,
|
2022-03-31 15:59:19 +00:00
|
|
|
const std::string& path,
|
2022-03-16 22:38:08 +00:00
|
|
|
void* mem) {
|
2019-05-03 20:50:19 +00:00
|
|
|
if (mem != cfg_value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-03-16 22:38:08 +00:00
|
|
|
auto loc_iter
|
|
|
|
= lnav_config_locations.find(intern_string::lookup(path));
|
2019-05-03 20:50:19 +00:00
|
|
|
if (loc_iter == lnav_config_locations.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-12 23:07:13 +00:00
|
|
|
errors.emplace_back(
|
|
|
|
lnav::console::user_message::error(
|
|
|
|
attr_line_t()
|
|
|
|
.append("invalid value for property ")
|
|
|
|
.append_quoted(lnav::roles::symbol(path)))
|
|
|
|
.with_reason(errmsg)
|
|
|
|
.with_snippet(
|
|
|
|
lnav::console::snippet::from(
|
2022-04-30 20:05:42 +00:00
|
|
|
loc_iter->second.sl_source, "")
|
2022-04-12 23:07:13 +00:00
|
|
|
.with_line(loc_iter->second.sl_line_number)));
|
2019-05-03 20:50:19 +00:00
|
|
|
};
|
|
|
|
|
2022-03-25 23:38:11 +00:00
|
|
|
for (const auto& jph : lnav_config_handlers.jpc_children) {
|
2020-05-07 14:08:59 +00:00
|
|
|
jph.walk(cb, &lnav_config);
|
2019-05-03 20:50:19 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
curr->reload_config(reporter);
|
2016-05-02 03:35:37 +00:00
|
|
|
curr = curr->lcl_next;
|
|
|
|
}
|
2018-05-10 13:44:03 +00:00
|
|
|
}
|