xF: add basic configuration
This commit is contained in:
+8
-8
@@ -37,7 +37,7 @@ image::xP.webp[align="center"]
|
||||
xF
|
||||
--
|
||||
The hybrid terminal/X11 frontend for 'xC'. It has simplified word wrapping,
|
||||
limited colour support, and X11 doesn't support text selection (but in 'xC'
|
||||
limited colour support, and X11 doesn't support text selection (though in 'xC'
|
||||
tradition, it will happily launch embedded gVim on both the input and the log).
|
||||
|
||||
This frontend is perfect for testing.
|
||||
@@ -96,7 +96,7 @@ Building
|
||||
Build-only dependencies: CMake, pkg-config, awk, liberty (included),
|
||||
asciidoctor or asciidoc (recommended but optional), rsvg-convert (for 'xF') +
|
||||
Common runtime dependencies: openssl +
|
||||
Additionally for 'xC': curses, lua >= 5.3 (optional), termo (included) +
|
||||
Additionally for 'xC': any curses, lua >= 5.3 (optional), termo (included) +
|
||||
Additionally for 'xF': ncursesw, libunistring, termo (included),
|
||||
x11 + xft + libpng (X11)
|
||||
|
||||
@@ -125,12 +125,14 @@ For the rest you might want to generate a configuration file:
|
||||
|
||||
$ xB --write-default-config
|
||||
$ xD --write-default-config
|
||||
$ xF --write-default-config
|
||||
|
||||
After making any necessary edits to the file (there are comments to aid you in
|
||||
doing that), simply run the appropriate program with no arguments:
|
||||
|
||||
$ xB
|
||||
$ xD
|
||||
$ xF
|
||||
|
||||
'xB' stays running in the foreground, therefore I recommend launching it inside
|
||||
a Screen or tmux session.
|
||||
@@ -139,12 +141,14 @@ a Screen or tmux session.
|
||||
file or something like `killall` if you want to terminate it. You can run it
|
||||
as a `forking` type systemd user service.
|
||||
|
||||
xP
|
||||
~~
|
||||
Frontends
|
||||
~~~~~~~~~
|
||||
The precondition for running 'xC' frontends is enabling its relay interface:
|
||||
|
||||
/set general.relay_bind = "127.0.0.1:9000"
|
||||
|
||||
xP
|
||||
~~
|
||||
To build the web server, install the Go compiler, and run `make`
|
||||
from the _xP_ directory. Then start the resulting binary, and navigate to
|
||||
the adress you give it as its first argument--in the following example,
|
||||
@@ -156,10 +160,6 @@ For remote use, it's recommended to put 'xP' behind a reverse proxy, with TLS,
|
||||
and some form of HTTP authentication. Pass the external URL of the WebSocket
|
||||
endpoint as the third command line argument in this case.
|
||||
|
||||
xF
|
||||
~~
|
||||
The terminal/X11 frontend needs the relay address on its command line.
|
||||
|
||||
xA
|
||||
~~
|
||||
The Fyne frontend supports all of Linux, FreeBSD, Windows, macOS, Android, and
|
||||
|
||||
@@ -10,7 +10,7 @@ xF - Terminal/X11 frontend for xC
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
*xF* [_OPTION_]... RELAY-ADDRESS
|
||||
*xF* [_OPTION_]... [HOST:PORT]
|
||||
|
||||
Description
|
||||
-----------
|
||||
@@ -18,6 +18,8 @@ Description
|
||||
It normally runs in the terminal, and can also use a graphical interface
|
||||
when built with support for one.
|
||||
|
||||
When an explicit relay address is given, it takes priority over configuration.
|
||||
|
||||
Options
|
||||
-------
|
||||
*-g*, *--gui*::
|
||||
@@ -29,6 +31,11 @@ Options
|
||||
*-V*, *--version*::
|
||||
Output version information and exit.
|
||||
|
||||
*--write-default-cfg*[**=**__PATH__]::
|
||||
Write a configuration file with defaults, show its path and exit.
|
||||
+
|
||||
The file will be appropriately commented.
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
Use https://git.janouch.name/p/xK to report bugs, request features,
|
||||
|
||||
@@ -32,6 +32,16 @@
|
||||
#endif // HAVE_X11
|
||||
#include "liberty/liberty-xui.c"
|
||||
|
||||
// --- Configuration (application-specific) ------------------------------------
|
||||
|
||||
static struct simple_config_item g_config_table[] =
|
||||
{
|
||||
{ "relay", NULL, "Default relay HOST:PORT" },
|
||||
{ "editor", NULL, "TUI editor; $1 filename" },
|
||||
{ "editor_x11", NULL, "GUI editor; $1 Window ID, $2 filename" },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
// --- Relay model -------------------------------------------------------------
|
||||
|
||||
// ~~~ Buffer lines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -449,6 +459,7 @@ struct relay_client
|
||||
|
||||
static struct
|
||||
{
|
||||
struct str_map config; ///< Frontend configuration
|
||||
struct poller poller; ///< Poller
|
||||
bool polling; ///< The event loop is running
|
||||
struct poller_fd signal_event; ///< There are signals to process
|
||||
@@ -3604,16 +3615,25 @@ app_external_editor_launch (struct error **e)
|
||||
bool run_in_terminal = g_xui.ui == &tui_ui;
|
||||
if (!child)
|
||||
{
|
||||
#define LAUNCH(x, ...) execlp (x, x, __VA_ARGS__, g.editor_filename, NULL)
|
||||
if (run_in_terminal)
|
||||
{
|
||||
hard_assert (setpgid (0, 0) != -1);
|
||||
hard_assert (tcsetpgrp (STDOUT_FILENO, getpgrp ()) != -1);
|
||||
|
||||
const char *command = str_map_find (&g.config, "editor");
|
||||
if (command)
|
||||
LAUNCH ("sh", "-c", command, "editor");
|
||||
|
||||
execlp (editor, editor, g.editor_filename, NULL);
|
||||
}
|
||||
#ifdef HAVE_X11
|
||||
#define LAUNCH(x, ...) execlp (x, x, __VA_ARGS__, g.editor_filename, NULL)
|
||||
else
|
||||
{
|
||||
const char *command = str_map_find (&g.config, "editor_x11");
|
||||
if (command)
|
||||
LAUNCH ("sh", "-c", command, "editor_x11", xid);
|
||||
|
||||
// This list is nearly exhaustive, so it's about priorities
|
||||
// and option customisation.
|
||||
LAUNCH ("gvim", "-f", "--socketid", xid);
|
||||
@@ -3625,8 +3645,8 @@ app_external_editor_launch (struct error **e)
|
||||
// XTerm will work better with "XTerm*allowSendEvents: true".
|
||||
LAUNCH ("xterm", "-into", xid, "-e", editor);
|
||||
}
|
||||
#undef LAUNCH
|
||||
#endif // HAVE_X11
|
||||
#undef LAUNCH
|
||||
|
||||
// AppKit offers no similar mechanism.
|
||||
|
||||
@@ -4231,8 +4251,11 @@ static const char g_link_pattern[] =
|
||||
"([^][(){}<>\"'[:space:],.:]|\\([^][(){}<>\"'[:space:]]*\\))";
|
||||
|
||||
static void
|
||||
app_init_context (const char *host, const char *port)
|
||||
app_init_context (void)
|
||||
{
|
||||
g.config = str_map_make (free);
|
||||
simple_config_load_defaults (&g.config, g_config_table);
|
||||
|
||||
poller_init (&g.poller);
|
||||
app_editor_init ();
|
||||
|
||||
@@ -4244,8 +4267,6 @@ app_init_context (const char *host, const char *port)
|
||||
if (!(g.link_re = regex_compile (g_link_pattern, REG_EXTENDED, &e)))
|
||||
exit_fatal ("Failed to compile link regex: %s", e->message);
|
||||
|
||||
g.relay.host = xstrdup (host);
|
||||
g.relay.port = xstrdup (port);
|
||||
g.relay.reconnect_event = poller_timer_make (&g.poller);
|
||||
g.relay.reconnect_event.dispatcher = relay_on_reconnect_timer;
|
||||
|
||||
@@ -4283,6 +4304,8 @@ app_free_context (void)
|
||||
free (g.editor_filename);
|
||||
free (g.editor_running_for);
|
||||
poller_free (&g.poller);
|
||||
|
||||
str_map_free (&g.config);
|
||||
}
|
||||
|
||||
// --- Main --------------------------------------------------------------------
|
||||
@@ -4301,11 +4324,14 @@ app_parse_options (int argc, char *argv[], bool *requested_gui)
|
||||
#endif // HAVE_X11
|
||||
{ 'h', "help", NULL, 0, "display this help and exit" },
|
||||
{ 'V', "version", NULL, 0, "output version information and exit" },
|
||||
{ 'w', "write-default-cfg", "FILENAME",
|
||||
OPT_OPTIONAL_ARG | OPT_LONG_ONLY,
|
||||
"write a default configuration file and exit" },
|
||||
{ 0, NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
struct opt_handler oh = opt_handler_make (argc, argv, opts,
|
||||
"HOST:PORT", "Terminal/X11 frontend for xC.");
|
||||
"[HOST:PORT]", "Terminal/X11 frontend for xC.");
|
||||
int c;
|
||||
while ((c = opt_handler_get (&oh)) != -1)
|
||||
switch (c)
|
||||
@@ -4321,6 +4347,9 @@ app_parse_options (int argc, char *argv[], bool *requested_gui)
|
||||
case 'V':
|
||||
printf (PROGRAM_NAME " " PROGRAM_VERSION "\n");
|
||||
exit (EXIT_SUCCESS);
|
||||
case 'w':
|
||||
call_simple_config_write_default (optarg, g_config_table);
|
||||
exit (EXIT_SUCCESS);
|
||||
default:
|
||||
print_error ("wrong options");
|
||||
opt_handler_usage (&oh, stderr);
|
||||
@@ -4329,31 +4358,45 @@ app_parse_options (int argc, char *argv[], bool *requested_gui)
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc != 1)
|
||||
{
|
||||
opt_handler_usage (&oh, stderr);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
opt_handler_free (&oh);
|
||||
return argv[0];
|
||||
}
|
||||
|
||||
static void
|
||||
app_parse_address (const char *address)
|
||||
{
|
||||
char *copy = xstrdup (address);
|
||||
const char *port = NULL, *host = tokenize_host_port (copy, &port);
|
||||
if (!port)
|
||||
exit_fatal ("missing port number/service name");
|
||||
|
||||
g.relay.host = xstrdup (host);
|
||||
g.relay.port = xstrdup (port);
|
||||
free (copy);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
bool requested_gui = false;
|
||||
char *address = xstrdup (app_parse_options (argc, argv, &requested_gui));
|
||||
const char *port = NULL, *host = tokenize_host_port (address, &port);
|
||||
if (!port)
|
||||
exit_fatal ("missing port number/service name");
|
||||
|
||||
if (!setlocale (LC_CTYPE, ""))
|
||||
print_warning ("failed to set the character locale");
|
||||
if (!setlocale (LC_TIME, ""))
|
||||
print_warning ("failed to set the time locale");
|
||||
|
||||
app_init_context (host, port);
|
||||
free (address);
|
||||
bool requested_gui = false;
|
||||
const char *address = app_parse_options (argc, argv, &requested_gui);
|
||||
|
||||
app_init_context ();
|
||||
|
||||
struct error *e = NULL;
|
||||
if (!simple_config_update_from_file (&g.config, &e))
|
||||
exit_fatal ("error loading configuration: %s", e->message);
|
||||
if (!address)
|
||||
address = str_map_find (&g.config, "relay");
|
||||
if (!address)
|
||||
exit_fatal ("no relay address given and none configured");
|
||||
|
||||
app_parse_address (address);
|
||||
|
||||
signals_init ();
|
||||
g.signal_event = poller_fd_make (&g.poller, g_signal_pipe[0]);
|
||||
|
||||
Reference in New Issue
Block a user