diff --git a/LICENSE b/LICENSE index dc534d3..b195a08 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright © 2013 Axel Wagner +Copyright © 2016 Axel Wagner and contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/conf/10-autoexec b/conf/10-autoexec index 3a1d2e4..327e7a4 100644 --- a/conf/10-autoexec +++ b/conf/10-autoexec @@ -28,7 +28,8 @@ function shellex_preexec () { # We write the expanded form of the command to the tempfile, because the # executet shell will not have our aliases or functions available - echo "rm $file\n$3" > $file + echo "rm $file" > $file + echo "$3" >> $file # prevent writing meaningless "zsh $file > /dev/null ...." to history unset HISTFILE diff --git a/doc/autoresize.txt b/doc/autoresize.txt index 40cfc7c..8ecb5f6 100644 --- a/doc/autoresize.txt +++ b/doc/autoresize.txt @@ -12,15 +12,15 @@ shellex, because when is starting it's output, there is not enough space, for the tabcompletion, so even if we immediately resize the terminalwindow, it will be too late and the shell-output is screwed up. -We rectify this, by injecting a custom ioctl-function into urxvt via -LD_PRELOAD, which rewrites all TIOCSWINSZ-requests to have a constant size, -thus faking to the shell that there is more space available, then there -actually is. The actual number of rows is calculated on start of the urxvt and -put into an environment-variable. +We rectify this, by injecting a custom ioctl-function into zsh via LD_PRELOAD, +which rewrites all TIOCGWINSZ-requests to have a constant size. This fakes to +the shell that there is more space available, then there actually is. The +actual number of rows is calculated on start of the urxvt and put into a +temporary file. The size is chosen a bit smaller than the screen, such that if +zsh needs even more space for the tabcompletion than fits on the screen, the +zsh handeling to deal with less space gets active. The filename is generated +with mktemp before either zsh or urxvt start. The file gets unlinked by +preload/main.c once a successful read happened. - - -With the current state, the window of shellex is able to grow automatically -exactly one time. This is, because zsh is spamming the output with '\n', if we -grow it always and we have yet to figure out why and how to stop that. -Shrinking (i.e. when the tab-completion vanishes again) is not implemented yet. +Shrinking after tab completions mostly works fine: Depending on the +tabcompletion settings, shrinking breaks once one hit the maximum size limit. diff --git a/preload/main.c b/preload/main.c index a468bd0..2f9ef8d 100644 --- a/preload/main.c +++ b/preload/main.c @@ -6,6 +6,8 @@ #define _GNU_SOURCE #include #include +#include +#include /* We can not take this from , because it would define the * ioctl-function itself @@ -22,28 +24,46 @@ int ioctl (int d, int request, char *argp) { if (orig_ioctl == NULL) { orig_ioctl = dlsym(RTLD_NEXT, "ioctl"); } + + /* We only care for TIOCGWINSZ ioctls */ + if (request != 0x5413) { + return orig_ioctl(d, request, argp); + } + static int max_rows = -1; + + /* ioctl gets called once before the perl module had the time to determine + * the right size! Leave max_rows negative to indicat that it still needs to + * be read from the SHELLEX_SIZE_FILE */ + if (max_rows < 0 ) { - char *str = getenv("SHELLEX_MAX_ROWS"); - if (str != NULL) { - max_rows = atoi(str); + + char *fname = getenv("SHELLEX_SIZE_FILE"); + if (fname != NULL && fname[0] != '\0') { + FILE *stream = fopen(fname,"r"); + char str[5] = "-500"; + if (stream != NULL) { + char *ret = fgets(str,5,stream); + fclose(stream); + if (ret != NULL) { + /* this may be -500 */ + max_rows = atoi(str); + if (max_rows > 0 ) { + unlink(fname); + } + } + } } } - // We only care for TIOCSWINSZ ioctls - if (request != 0x5414) { - return orig_ioctl(d, request, argp); - } - struct winsize ws = *((struct winsize *)argp); - int fheight = ws.ws_ypixel / ws.ws_row; - if (max_rows < 0) { - ws.ws_row = 80; - ws.ws_ypixel += 80 * fheight; - } else { - ws.ws_row = max_rows; - ws.ws_ypixel += max_rows * fheight; - } + int retval = orig_ioctl(d, request, (char *)argp); + struct winsize *ws = (struct winsize *)argp; + + /* max_rows is still negative at first invocation */ + int fheight = ws->ws_ypixel / ws->ws_row; + ws->ws_row = (max_rows > 0) ? max_rows : 25; + ws->ws_ypixel = ws->ws_row * fheight; - return orig_ioctl(d, request, (char *)&ws); + return retval; } diff --git a/shellex.in b/shellex.in index ecedc0c..040112c 100644 --- a/shellex.in +++ b/shellex.in @@ -4,6 +4,6 @@ # See shellex(1) for information on invocation. # © 2013 Axel Wagner and contributors (see also: LICENSE) - -export LD_PRELOAD="@PREFIX@@LIBDIR@/shellex/shellex_preload.so" -exec urxvt -perl-lib @PREFIX@@LIBDIR@/shellex/urxvt -pe shellex -override-redirect -name shellex $* -e env -u LD_PRELOAD zsh -f +SHELLEX_PRELOAD="@PREFIX@@LIBDIR@/shellex/shellex_preload.so" +export SHELLEX_SIZE_FILE=$(mktemp -t shellex-size-XXXXXXXX) +exec urxvt -perl-lib @PREFIX@@LIBDIR@/shellex/urxvt -pe shellex -override-redirect -name shellex $* -e env LD_PRELOAD=$SHELLEX_PRELOAD zsh -f diff --git a/urxvt/shellex.in b/urxvt/shellex.in index c2f4c4f..95043df 100644 --- a/urxvt/shellex.in +++ b/urxvt/shellex.in @@ -203,7 +203,17 @@ sub on_start { # This environment variable is used by the LD_PRELOAD ioctl-override to # determine the values to send to the shell - $ENV{SHELLEX_MAX_ROWS} = int($self->{h} / $self->fheight); + # TODO revisit communication protocol (from file to pipe?) + # TODO check if user defined their own SHELLEX_MAX_ROWS, which should be used like + #$ENV{SHELLEX_MAX_ROWS} = $sane_max_rows < $ENV{SHELLEX_MAX_ROWS} ? $sane_max_rows : $ENV{SHELLEX_MAX_ROWS} ; + my $sane_max_rows = int($self->{h} / $self->fheight) - 10; + + $ENV{SHELLEX_MAX_ROWS} = $sane_max_rows; + my $filename = $ENV{SHELLEX_SIZE_FILE}; + open(my $fh, '>', $filename); + print $fh "$ENV{SHELLEX_MAX_ROWS}\n"; + close $fh; + print "writing max rows file done\n"; $self->{border} = $self->x_resource('internalBorder'); @@ -223,6 +233,8 @@ sub on_start { my $cfg = gen_conf(); + print "loading config\n"; + $self->tt_write($self->locale_encode("unset LD_PRELOAD\n")); $self->tt_write($self->locale_encode(". $cfg\n")); (); } @@ -243,6 +255,7 @@ sub on_line_update { } } $nrow = $nrow > 0 ? $nrow : 1; + $nrow = $nrow > $ENV{SHELLEX_MAX_ROWS} ? $ENV{SHELLEX_MAX_ROWS} : $nrow; print "resizing to $nrow\n"; # If the window is supposed to be at the bottom, we have to move the @@ -315,6 +328,8 @@ sub on_add_lines { print "add_lines(string = \"$str\")\n"; my $nrow = $self->predict_term_size($string); + $nrow = $nrow > 0 ? $nrow : 1; + $nrow = $nrow > $ENV{SHELLEX_MAX_ROWS} ? $ENV{SHELLEX_MAX_ROWS} : $nrow; print "resizing to $nrow\n"; # If the window is supposed to be at the bottom, we have to move the