diff --git a/config.def.h b/config.def.h index 0c9ab2c..3e9db11 100644 --- a/config.def.h +++ b/config.def.h @@ -467,6 +467,10 @@ static Shortcut shortcuts[] = { #if INVERT_PATCH { TERMMOD, XK_X, invert, { 0 } }, #endif // INVERT_PATCH + #if OSC133_PATCH + { TERMMOD, XK_Z, scrolltoprompt, {.i = -1}, S_PRI }, + { TERMMOD, XK_X, scrolltoprompt, {.i = 1}, S_PRI }, + #endif // OSC133_PATCH }; /* diff --git a/patch/osc133.c b/patch/osc133.c new file mode 100644 index 0000000..6d72453 --- /dev/null +++ b/patch/osc133.c @@ -0,0 +1,27 @@ +void scrolltoprompt(const Arg *arg) { + int x, y; + #if REFLOW_PATCH + int top = term.scr - term.histf; + #else + int top = term.scr - term.histn; + #endif // REFLOW_PATCH + int bot = term.scr + term.row-1; + int dy = arg->i; + Line line; + + if (!dy || tisaltscr()) + return; + + for (y = dy; y >= top && y <= bot; y += dy) { + for (line = TLINE(y), x = 0; x < term.col; x++) { + if (line[x].mode & ATTR_FTCS_PROMPT) + goto scroll; + } + } + +scroll: + if (dy < 0) + kscrollup(&((Arg){ .i = -y })); + else + kscrolldown(&((Arg){ .i = y })); +} diff --git a/patch/osc133.h b/patch/osc133.h new file mode 100644 index 0000000..f5a6c45 --- /dev/null +++ b/patch/osc133.h @@ -0,0 +1 @@ +static void scrolltoprompt(const Arg *); diff --git a/patch/x_include.c b/patch/x_include.c index 73a709a..30b77da 100644 --- a/patch/x_include.c +++ b/patch/x_include.c @@ -46,4 +46,7 @@ #endif #if XRESOURCES_PATCH #include "xresources.c" -#endif \ No newline at end of file +#endif +#if OSC133_PATCH +#include "osc133.c" +#endif diff --git a/patch/x_include.h b/patch/x_include.h index b94317c..78290e1 100644 --- a/patch/x_include.h +++ b/patch/x_include.h @@ -41,3 +41,6 @@ #if XRESOURCES_PATCH #include "xresources.h" #endif +#if OSC133_PATCH +#include "osc133.h" +#endif diff --git a/patches.def.h b/patches.def.h index cb1b958..65d883c 100644 --- a/patches.def.h +++ b/patches.def.h @@ -301,6 +301,13 @@ */ #define OPENURLONCLICK_PATCH 0 +/* This patch allows jumping between prompts by utilizing the OSC 133 escape sequence + * emitted by shells. Must be used with either reflow or scrollback patch. + * + * https://codeberg.org/dnkl/foot#jumping-between-prompts + */ +#define OSC133_PATCH 0 + /* Reflow. * Allows st to be resized without cutting off text when the terminal window is made larger again. * Text wraps when the terminal window is made smaller. diff --git a/st.c b/st.c index 7451f87..7b25227 100644 --- a/st.c +++ b/st.c @@ -2699,6 +2699,25 @@ strhandle(void) tfulldirt(); } return; + #if OSC133_PATCH + case 133: + if (narg < 2) + break; + switch (*strescseq.args[1]) { + case 'A': + term.c.attr.mode |= ATTR_FTCS_PROMPT; + break; + /* We don't handle these arguments yet */ + case 'B': + case 'C': + case 'D': + break; + default: + fprintf(stderr, "erresc: unknown OSC 133 argument: %c\n", *strescseq.args[1]); + break; + } + return; + #endif // OSC133_PATCH } break; case 'k': /* old title set compatibility */ @@ -3449,6 +3468,9 @@ check_control_code: } tsetchar(u, &term.c.attr, term.c.x, term.c.y); + #if OSC133_PATCH + term.c.attr.mode &= ~ATTR_FTCS_PROMPT; + #endif // OSC133_PATCH term.lastc = u; if (width == 2) { diff --git a/st.h b/st.h index 95d1be1..cd6982e 100644 --- a/st.h +++ b/st.h @@ -70,6 +70,9 @@ enum glyph_attribute { ATTR_HIGHLIGHT = 1 << 17, #endif // KEYBOARDSELECT_PATCH ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT, + #if OSC133_PATCH + ATTR_FTCS_PROMPT = 1 << 18, /* OSC 133 ; A ST */ + #endif // OSC133_PATCH }; #if SIXEL_PATCH