mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-27 06:46:44 -04:00
Add exec bind action
This commit is contained in:
parent
b81b98d47c
commit
0c252d1b05
7 changed files with 43 additions and 10 deletions
1
config.c
1
config.c
|
|
@ -108,6 +108,7 @@ static const char *const binding_action_map[] = {
|
|||
[BIND_ACTION_MINIMIZE] = "minimize",
|
||||
[BIND_ACTION_MAXIMIZE] = "maximize",
|
||||
[BIND_ACTION_FULLSCREEN] = "fullscreen",
|
||||
[BIND_ACTION_EXEC] = "exec",
|
||||
[BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback",
|
||||
[BIND_ACTION_PIPE_VIEW] = "pipe-visible",
|
||||
[BIND_ACTION_PIPE_SELECTED] = "pipe-selected",
|
||||
|
|
|
|||
|
|
@ -812,6 +812,20 @@ e.g. *search-start=none*.
|
|||
|
||||
Default: _not bound_
|
||||
|
||||
*exec*
|
||||
Executes a slave process bound to the same tty as the main
|
||||
session process. The syntax is similar to *pipe-visible* and
|
||||
similar bindings.
|
||||
|
||||
Note that the process is controlling the tty at the same time
|
||||
as the currently running process and it can mess up completely
|
||||
the terminal state. Be careful of what you configure.
|
||||
|
||||
Example:
|
||||
*exec=[clear] Control+Shift+l*
|
||||
|
||||
Default: _not bound_
|
||||
|
||||
*show-urls-launch*
|
||||
Enter URL mode, where all currently visible URLs are tagged with a
|
||||
jump label with a key sequence that will open the URL (and exit
|
||||
|
|
|
|||
17
input.c
17
input.c
|
|
@ -42,6 +42,7 @@
|
|||
#include "vt.h"
|
||||
#include "xmalloc.h"
|
||||
#include "xsnprintf.h"
|
||||
#include "slave.h"
|
||||
|
||||
struct pipe_context {
|
||||
char *text;
|
||||
|
|
@ -204,6 +205,22 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL);
|
||||
return true;
|
||||
|
||||
case BIND_ACTION_EXEC:
|
||||
if (binding->aux->type != BINDING_AUX_PIPE)
|
||||
return true;
|
||||
|
||||
int argc = 0;
|
||||
while(binding->aux->pipe.args[argc]) argc++;
|
||||
|
||||
if (slave_spawn(
|
||||
term->ptmx, argc, term->cwd, binding->aux->pipe.args, NULL,
|
||||
&term->conf->env_vars, term->conf->term, NULL, false, false, NULL) == -1) {
|
||||
LOG_ERRNO("failed to spawn slave for exec action");
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case BIND_ACTION_PIPE_SCROLLBACK:
|
||||
if (term->grid == &term->alt)
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ enum bind_action_normal {
|
|||
BIND_ACTION_MINIMIZE,
|
||||
BIND_ACTION_MAXIMIZE,
|
||||
BIND_ACTION_FULLSCREEN,
|
||||
BIND_ACTION_EXEC,
|
||||
BIND_ACTION_PIPE_SCROLLBACK,
|
||||
BIND_ACTION_PIPE_VIEW,
|
||||
BIND_ACTION_PIPE_SELECTED,
|
||||
|
|
|
|||
16
slave.c
16
slave.c
|
|
@ -205,16 +205,16 @@ emit_notifications(int fd, const user_notifications_t *notifications)
|
|||
|
||||
static noreturn void
|
||||
slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
|
||||
bool login_shell, const user_notifications_t *notifications)
|
||||
bool login_shell, bool init, const user_notifications_t *notifications)
|
||||
{
|
||||
int pts = -1;
|
||||
const char *pts_name = ptsname(ptmx);
|
||||
|
||||
if (grantpt(ptmx) == -1) {
|
||||
if (init && grantpt(ptmx) == -1) {
|
||||
LOG_ERRNO("failed to grantpt()");
|
||||
goto err;
|
||||
}
|
||||
if (unlockpt(ptmx) == -1) {
|
||||
if (init && unlockpt(ptmx) == -1) {
|
||||
LOG_ERRNO("failed to unlockpt()");
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -222,7 +222,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
|
|||
close(ptmx);
|
||||
ptmx = -1;
|
||||
|
||||
if (setsid() == -1) {
|
||||
if (init && setsid() == -1) {
|
||||
LOG_ERRNO("failed to setsid()");
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -233,7 +233,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (ioctl(pts, TIOCSCTTY, 0) < 0) {
|
||||
if (init && ioctl(pts, TIOCSCTTY, 0) < 0) {
|
||||
LOG_ERRNO("failed to configure controlling terminal");
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -254,7 +254,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (tll_length(*notifications) > 0) {
|
||||
if (notifications && tll_length(*notifications) > 0) {
|
||||
int flags = fcntl(pts, F_GETFL);
|
||||
if (flags < 0)
|
||||
goto err;
|
||||
|
|
@ -307,7 +307,7 @@ pid_t
|
|||
slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
|
||||
char *const *envp, const env_var_list_t *extra_env_vars,
|
||||
const char *term_env, const char *conf_shell, bool login_shell,
|
||||
const user_notifications_t *notifications)
|
||||
bool init, const user_notifications_t *notifications)
|
||||
{
|
||||
int fork_pipe[2];
|
||||
if (pipe2(fork_pipe, O_CLOEXEC) < 0) {
|
||||
|
|
@ -393,7 +393,7 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
|
|||
setenv("SHELL", shell_argv[0], 1);
|
||||
|
||||
slave_exec(ptmx, shell_argv, envp != NULL ? envp : environ,
|
||||
fork_pipe[1], login_shell, notifications);
|
||||
fork_pipe[1], login_shell, init, notifications);
|
||||
BUG("Unexpected return from slave_exec()");
|
||||
break;
|
||||
|
||||
|
|
|
|||
2
slave.h
2
slave.h
|
|
@ -9,5 +9,5 @@
|
|||
pid_t slave_spawn(
|
||||
int ptmx, int argc, const char *cwd, char *const *argv, char *const *envp,
|
||||
const env_var_list_t *extra_env_vars, const char *term_env,
|
||||
const char *conf_shell, bool login_shell,
|
||||
const char *conf_shell, bool login_shell, bool init,
|
||||
const user_notifications_t *notifications);
|
||||
|
|
|
|||
|
|
@ -1336,7 +1336,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|||
/* Start the slave/client */
|
||||
if ((term->slave = slave_spawn(
|
||||
term->ptmx, argc, term->cwd, argv, envp, &conf->env_vars,
|
||||
conf->term, conf->shell, conf->login_shell,
|
||||
conf->term, conf->shell, conf->login_shell, true,
|
||||
&conf->notifications)) == -1)
|
||||
{
|
||||
goto err;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue