mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
config: add ‘include’ directive
This allows you to include sub-configurations. For example, theme files. The ‘include’ directive is a top-level keyword. I.e. it cannot be used inside sections. * The included file must be specified with an absolute path * The included file is parsed in its own scope * Nested includes are allowed * Multiple include directives are allowed Closes #555
This commit is contained in:
parent
8262c1f0c2
commit
9055d3d921
3 changed files with 67 additions and 19 deletions
|
|
@ -53,6 +53,8 @@
|
|||
unavailable) (https://codeberg.org/dnkl/foot/issues/487).
|
||||
* `ctrl`+`c` as a default key binding; to cancel search/url mode.
|
||||
* `${window-title}` to `notify`.
|
||||
* Support for including files in `foot.ini`
|
||||
(https://codeberg.org/dnkl/foot/issues/555).
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
68
config.c
68
config.c
|
|
@ -550,11 +550,41 @@ deprecated_url_option(struct config *conf,
|
|||
tll_push_back(conf->notifications, deprecation);
|
||||
}
|
||||
|
||||
static bool parse_config_file(
|
||||
FILE *f, struct config *conf, const char *path, bool errors_are_fatal);
|
||||
|
||||
static bool
|
||||
parse_section_main(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "term") == 0) {
|
||||
if (strcmp(key, "include") == 0) {
|
||||
const char *include_path = value;
|
||||
|
||||
if (include_path[0] != '/') {
|
||||
LOG_AND_NOTIFY_ERR(
|
||||
"%s:%d: [default]: %s: not an absolute path",
|
||||
path, lineno, include_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *include = fopen(include_path, "r");
|
||||
|
||||
if (include == NULL) {
|
||||
LOG_AND_NOTIFY_ERRNO(
|
||||
"%s:%d: [default]: %s: failed to open",
|
||||
path, lineno, include_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = parse_config_file(
|
||||
include, conf, include_path, errors_are_fatal);
|
||||
fclose(include);
|
||||
|
||||
LOG_INFO("imported sub-configuration from %s", include_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
else if (strcmp(key, "term") == 0) {
|
||||
free(conf->term);
|
||||
conf->term = xstrdup(value);
|
||||
}
|
||||
|
|
@ -582,7 +612,7 @@ parse_section_main(const char *key, const char *value, struct config *conf,
|
|||
unsigned width, height;
|
||||
if (sscanf(value, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
|
||||
LOG_AND_NOTIFY_ERR(
|
||||
"%s: %d: [default]: initial-window-size-pixels: "
|
||||
"%s:%d: [default]: initial-window-size-pixels: "
|
||||
"expected WIDTHxHEIGHT, where both are positive integers, "
|
||||
"got '%s'", path, lineno, value);
|
||||
return false;
|
||||
|
|
@ -597,7 +627,7 @@ parse_section_main(const char *key, const char *value, struct config *conf,
|
|||
unsigned width, height;
|
||||
if (sscanf(value, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
|
||||
LOG_AND_NOTIFY_ERR(
|
||||
"%s: %d: [default]: initial-window-size-chars: "
|
||||
"%s:%d: [default]: initial-window-size-chars: "
|
||||
"expected WIDTHxHEIGHT, where both are positive integers, "
|
||||
"got '%s'", path, lineno, value);
|
||||
return false;
|
||||
|
|
@ -876,7 +906,7 @@ parse_section_main(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_bell(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "urgent") == 0)
|
||||
conf->bell.urgent = str_to_bool(value);
|
||||
|
|
@ -898,7 +928,7 @@ parse_section_bell(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_scrollback(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "lines") == 0) {
|
||||
unsigned long lines;
|
||||
|
|
@ -969,7 +999,7 @@ parse_section_scrollback(const char *key, const char *value, struct config *conf
|
|||
|
||||
static bool
|
||||
parse_section_url(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "launch") == 0) {
|
||||
if (!str_to_spawn_template(conf, value, &conf->url.launch, path, lineno,
|
||||
|
|
@ -1062,7 +1092,7 @@ parse_section_url(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_colors(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
size_t key_len = strlen(key);
|
||||
uint8_t last_digit = (unsigned char)key[key_len - 1] - '0';
|
||||
|
|
@ -1118,7 +1148,7 @@ parse_section_colors(const char *key, const char *value, struct config *conf,
|
|||
else if (strcmp(key, "alpha") == 0) {
|
||||
double alpha;
|
||||
if (!str_to_double(value, &alpha) || alpha < 0. || alpha > 1.) {
|
||||
LOG_AND_NOTIFY_ERR("%s: %d: [colors]: alpha: expected a value in the range 0.0-1.0",
|
||||
LOG_AND_NOTIFY_ERR("%s:%d: [colors]: alpha: expected a value in the range 0.0-1.0",
|
||||
path, lineno);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1142,7 +1172,7 @@ parse_section_colors(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_cursor(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "style") == 0) {
|
||||
if (strcmp(value, "block") == 0)
|
||||
|
|
@ -1198,7 +1228,7 @@ parse_section_cursor(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_mouse(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "hide-when-typing") == 0)
|
||||
conf->mouse.hide_when_typing = str_to_bool(value);
|
||||
|
|
@ -1216,7 +1246,7 @@ parse_section_mouse(const char *key, const char *value, struct config *conf,
|
|||
|
||||
static bool
|
||||
parse_section_csd(const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "preferred") == 0) {
|
||||
if (strcmp(value, "server") == 0)
|
||||
|
|
@ -1647,7 +1677,7 @@ parse_key_binding_section(
|
|||
static bool
|
||||
parse_section_key_bindings(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
return parse_key_binding_section(
|
||||
"key-bindings", key, value, BIND_ACTION_KEY_COUNT, binding_action_map,
|
||||
|
|
@ -1657,7 +1687,7 @@ parse_section_key_bindings(
|
|||
static bool
|
||||
parse_section_search_bindings(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
static const char *const search_binding_action_map[] = {
|
||||
[BIND_ACTION_SEARCH_NONE] = NULL,
|
||||
|
|
@ -1692,7 +1722,7 @@ parse_section_search_bindings(
|
|||
static bool
|
||||
parse_section_url_bindings(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
static const char *const url_binding_action_map[] = {
|
||||
[BIND_ACTION_URL_NONE] = NULL,
|
||||
|
|
@ -1848,7 +1878,7 @@ has_mouse_binding_collisions(struct config *conf, const key_combo_list_t *key_co
|
|||
static bool
|
||||
parse_section_mouse_bindings(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
char *pipe_cmd;
|
||||
char **pipe_argv;
|
||||
|
|
@ -1943,7 +1973,7 @@ parse_section_mouse_bindings(
|
|||
static bool
|
||||
parse_section_tweak(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno)
|
||||
const char *path, unsigned lineno, bool errors_are_fatal)
|
||||
{
|
||||
if (strcmp(key, "scaling-filter") == 0) {
|
||||
static const char filters[][12] = {
|
||||
|
|
@ -2100,7 +2130,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar
|
|||
/* Function pointer, called for each key/value line */
|
||||
typedef bool (*parser_fun_t)(
|
||||
const char *key, const char *value, struct config *conf,
|
||||
const char *path, unsigned lineno);
|
||||
const char *path, unsigned lineno, bool errors_are_fatal);
|
||||
|
||||
static const struct {
|
||||
parser_fun_t fun;
|
||||
|
|
@ -2255,7 +2285,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar
|
|||
parser_fun_t section_parser = section_info[section].fun;
|
||||
xassert(section_parser != NULL);
|
||||
|
||||
if (!section_parser(key, value, conf, path, lineno))
|
||||
if (!section_parser(key, value, conf, path, lineno, errors_are_fatal))
|
||||
error_or_continue();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,22 @@ in this order:
|
|||
Default: _monospace:size=8_ (*font*), _not set_ (*font-bold*,
|
||||
*font-italic*, *font-bold-italic*).
|
||||
|
||||
*include*
|
||||
Absolute path to configuration file to import.
|
||||
|
||||
The import file has its own section scope. I.e. the including
|
||||
configuration is still in the default section after the include,
|
||||
regardless of which section the included file ends in.
|
||||
|
||||
The path must be an absolute path.
|
||||
|
||||
Multiple include directives are allowed, but only one path per
|
||||
directive.
|
||||
|
||||
Nested imports are allowed.
|
||||
|
||||
Default: _not set_.
|
||||
|
||||
*line-height*
|
||||
An absolute value, in _points_, that override line height from the
|
||||
font metrics.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue