...
 
Commits (3)
Changelog
=========
0.3 - 2018-12-10
----------------
• Miscellaneous maintenance changes
• Updated empty-line treatment
• Changed xrandr parseing
• Cleanup of unused perl modules
• Bugfix: allow symlinks in user .shellex directories
• Use configuration from `$XDG_CONFIG_HOME`
• Enable compinit by default, add ctrl-x r for recent file completion
The slight change in the default completion behaviour is very likely desirable.
In the unlikely chance that a user does not appreciate the change, refer to the
README about how to disable the snippet `20-completion`.
0.2 - 2016-12-27
----------------
• Added optional sudo configuration
......
......@@ -13,6 +13,7 @@ include preload/preload.mk
include shellex.mk
include urxvt/urxvt_shellex.mk
include conf.mk
include format.mk
include doc/man/man.mk
real-all: $(ALL_TARGETS)
......
......@@ -20,10 +20,10 @@ from working. After not much seem to happen in that direction, I decided to
start again, this time using `urxvt` to do the terminal-part, which turned out to
be really easy.
So, this is the early prototype. It is usable and should already work and be
useful, but much is not working yet. I hope this time I will continue the work
for longer ;)
While this had the label “early prototype”, it has worked in daily use quite
reasonably. A few possible improvements were never apparently important enough
to invest serious amounts of time and work into them. Still, contributions are
welcome.
Architecture
============
......@@ -48,13 +48,13 @@ Working:
* Dynamic resizing of the launcher-window e.g. for multiple lines of
suggestions for tab-completions (see [doc/autoresize.txt](doc/autoresize.txt))
Planned, but not Implemented yet:
Planned, but not implemented:
* Buffering/showing some output, for errors etc. We have to think about some
magic way to determine, wether output is helpful or the launcher should be
magic way to determine, whether output is helpful or the launcher should be
hidden immediately
* dmenu-like completion, typing part of a command still completing (maybe zsh
has something to do that?)
* .desktop-file integration
has something to do that? possibly [fzf](https://github.com/junegunn/fzf))
* [.desktop-file integration](https://github.com/pseyfert/shellex-desktop)
* Your ticket here
......@@ -79,7 +79,7 @@ $ make
$ make install
```
for installing in `$(HOME).local`
for installing in `$(HOME)/.local`
```sh
$ git clone git://github.com/Merovius/shellex.git
......@@ -139,6 +139,19 @@ following is a not comprehensive list of highly appreciated ways to contribute:
to maintain the translation.
Customizations
==============
Users are invited to publish their customizations. Either as a contribution
(see above) if these are changes that are a sensible default for all users, or
in their own small packages which contain only the customizations. Especially,
when the customization will be useful for many, but not all users.
Existing customization projects are:
* [pseyfert's customizations](https://github.com/pseyfert/shellex-customizations)
* Your project here
Configuration
=============
......@@ -155,22 +168,27 @@ Resource | Values | Default | Description
shellex.pos | pointer|focus | focus | If pointer, shellex shows the window on the window, the mousepointer is on, else it uses the output, where most of the currently focused window is (falling back to the pointer-method, if the root-window is focused).
shellex.edge | bottom|top | top | On what screenedge to show shellex
The other source of configuration are small shell-script-snippets. When
starting, `shellex` will look into `$HOME/.shellex` and into `/etc/shellex`. It
will then source all the snippets in either location. If there is an
identically named file in both directories, the one in your home will be
preferred.
This makes for a pretty flexible configuration process: Usually there will be a
lot of snippets in `/usr/lib/shellex/conf`, which should be self-contained and
without a lot of side-effects. In `/etc/shellex` there then are some symlinks
to those snippets, making up the default-configuration on this system, together
with administrator-provided additional defaults. Whenever you don't want a
snippet form `/etc/shellex` to be used, just create a symlink of the same name
to `/dev/null` in `$HOME/.shellex`. If you want to create your own snippets,
just put them in `$HOME/.shellex` under a name not used yet and it will be
automatically sourced.
On start, `shellex` assembles a list of snippet basenames by looking at all of
the paths listed below. For each snippet basename, `shellex` loads the first
file it finds when looking through the paths in order:
1. `$XDG_CONFIG_HOME/.shellex`. Typically unset, defaulting to `$HOME/.config/shellex`.
2. `$HOME/.shellex`
3. `/etc/shellex` (shellex defaults, symlinks to `/usr/shellex/conf/`)
To customize shellex, you can do the following things in
`$XDG_CONFIG_HOME/.shellex` or `$HOME/.shellex/`:
1. Overwrite a default by creating a new snippet of the same name
2. Not include a default by creating a symlink to `/dev/null` of the same same
3. Include an example-snippet not used by default, by creating a symlink to `/usr/shellex/snippet`
4. Write you own snippets with a currently unused name
To avoid naming-conflicts in the future, you should add a common suffix to all
your own snippets. Snippets are run in ascending order. By choosing a number
which sorts between/after the existing snippet(s) you can ensure it runs at the
desired time. E.g. if your snippet beeps on errors, name it 15-errorbeep so that
it sorts before 20-nobeep.
Command-line
============
......
......@@ -2,7 +2,7 @@ INSTALL_TARGETS += install-conf install-rc
CLEAN_TARGETS += clean-shellexrc
ALL_TARGETS += conf/shellexrc
default_confs := 10-autoexec 20-nobeep 40-escape 40-home_end 40-setprompt 40-sigint 90-hist 99-clear
default_confs := 10-autoexec 20-completion 20-nobeep 40-escape 40-home_end 40-setprompt 40-sigint 40-recent 90-hist 99-clear
install-conf:
echo "[INSTALL] $@"
......
......@@ -2,7 +2,6 @@
# Make zsh automatically execute a command, when enter is hit
# © 2013 Axel Wagner and contributors (see also: LICENSE)
zmodload zsh/regex
function shellex_preexec () {
# In $1 the command-line is given
# In $3 the command-line with expanded aliases and function-bodies is given
......@@ -21,7 +20,8 @@ preexec_functions=(shellex_preexec)
# https://www.reddit.com/r/zsh/comments/s6t6d/is_there_an_alias_for_an_empty_line/
function empty-buffer-to-exit() {
if [[ $#BUFFER == 0 ]]; then
BUFFER="exit"
fc -P
exit
fi
}
# set special widget, see man zshzle
......
# enable tab completion system
# © 2016 Paul Seyfert and contributors (see also: LICENSE)
autoload -U compinit
compinit -C
# 'ctrl-x r' will complete the 12 last modified (mtime) files/directories
# © 2018 Michael Stapelberg and contributors (see also: LICENSE)
# only add this completion if compinit has been called
if [[ -v _comps ]]
then
# 'ctrl-x r' will complete the 12 last modified (mtime) files/directories
zle -C newest-files complete-word _generic
bindkey '^Xr' newest-files
zstyle ':completion:newest-files:*' completer _files
zstyle ':completion:newest-files:*' file-patterns '*~.*(omN[1,12])'
zstyle ':completion:newest-files:*' menu select yes
zstyle ':completion:newest-files:*' sort false
zstyle ':completion:newest-files:*' matcher-list 'b:=*' # important
fi
......@@ -5,17 +5,31 @@
# get array of all relevant files
# http://stackoverflow.com/a/10981499
# http://unix.stackexchange.com/a/26825
thefiles=(@SYSCONFDIR@/shellex/* $HOME/.shellex/*(.N))
# parentheses after * steer zsh's globbing
# . means "only regular files"
# -. means "regular files and symlinks pointing to regular files"
# N means "empty list in case of no matches"
thefiles=(
@SYSCONFDIR@/shellex/*
${XDG_CONFIG_HOME:-$HOME/.config}/shellex/*(-.N)
$HOME/.shellex/*(-.N)
)
# get the basenames of all files and make unique list
# http://stackoverflow.com/a/9516801
uniquified=( $( for f in "${thefiles[@]}" ; do basename $f ; done | sort -u ) )
# source each file from $HOME/.shellex if it exists there, otherwise from /etc
# source each file from the first of:
# 1. $XDG_CONFIG_HOME/.shellex (typically $HOME/.config/shellex)
# 2. $HOME/.shellex
# 3. @SYSCONFDIR@/shellex
for f in $uniquified
do
# -r checks if file exists and is readable
if [[ -r $HOME/.shellex/$f ]]
# -r checks if file exists and is readable
if [[ -r ${XDG_CONFIG_HOME:-$HOME/.config}/shellex/$f ]]
then
source $HOME/.config/shellex/$f
elif [[ -r $HOME/.shellex/$f ]]
then
source $HOME/.shellex/$f
else
......
shellex (0.3-1) unstable; urgency=low
* Updated Debian Policy standard version
* new upstream version
-- Paul Seyfert <pseyfert.mathphys@gmail.com> Tue, 11 Dec 2018 11:41:56 +0100
shellex (0.2-4) UNRELEASED; urgency=medium
* d/rules: Remove trailing whitespaces
......
......@@ -3,7 +3,7 @@ Section: x11
Priority: optional
Maintainer: Paul Seyfert <pseyfert.mathphys@gmail.com>
Build-Depends: debhelper (>= 9), asciidoc-base, xmlto, docbook-xml
Standards-Version: 4.1.1
Standards-Version: 4.2.1
Homepage: http://github.com/Merovius/shellex
Vcs-Git: https://salsa.debian.org/debian/shellex.git
Vcs-Browser: https://salsa.debian.org/debian/shellex
......
......@@ -7,7 +7,7 @@ template::[header-declarations]
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
<refmiscinfo class="source">shellex</refmiscinfo>
<refmiscinfo class="version">0.2</refmiscinfo>
<refmiscinfo class="version">0.3</refmiscinfo>
<refmiscinfo class="manual">shellex Manual</refmiscinfo>
</refmeta>
<refnamediv>
......
shellex(1)
==========
Paul Seyfert <pseyfert@mathphys.fsk.uni-heidelberg.de>
v0.2, December 2016
Paul Seyfert <pseyfert.mathphys@gmail.com>
v0.3, July 2018
== NAME
......@@ -51,12 +51,16 @@ terminal window.
*shellex* configuration snippets can be found in *@PREFIX@@LIBDIR@/shellex/*.
On start, *shellex* looks into @SYSCONFDIR@/shellex for default-snippets to
source (usually this will be symlinks to *@PREFIX@@LIBDIR@/shellex/*) as well
as into *$HOME/.shellex/* for any user-configuration. If a file of the same
name exists in both locations, it will only use the one in *$HOME/.shellex/*.
On start, *shellex* assembles a list of snippet basenames by looking at all of
the paths listed below. For each snippet basename, *shellex* loads the first
file it finds when looking through the paths in order:
To customize shellex, you can do the following things in *$HOME/.shellex/*:
1. $XDG_CONFIG_HOME/.shellex. Typically unset, defaulting to $HOME/.config/shellex.
2. $HOME/.shellex
3. @SYSCONFDIR@/shellex (shellex defaults, symlinks to *@PREFIX@@LIBDIR@/shellex/conf/*)
To customize shellex, you can do the following things in
*$XDG_CONFIG_HOME/.shellex* or *$HOME/.shellex/*:
1. Overwrite a default by creating a new snippet of the same name
2. Not include a default by creating a symlink to */dev/null* of the same same
......@@ -64,7 +68,10 @@ To customize shellex, you can do the following things in *$HOME/.shellex/*:
4. Write you own snippets with a currently unused name
To avoid naming-conflicts in the future, you should add a common suffix to all
your own snippets.
your own snippets. Snippets are run in ascending order. By choosing a number
which sorts between/after the existing snippet(s) you can ensure it runs at the
desired time. E.g. if your snippet beeps on errors, name it 15-errorbeep so that
it sorts before 20-nobeep.
== AUTHORS
......
format: format_c format_perl format_vim
format_perl: urxvt/shellex.in
echo "[FORMAT] $^"
cd $(shell dirname $^) && perltidy $(shell basename $^)
format_c: preload/main.c
echo "[FORMAT] $^"
clang-format -i $^
format_vim:
echo "[FORMAT]"
for shfile in $(wildcard conf/*) shellex.in; do echo "[FORMAT] $${shfile}"; ./indent.sh $${shfile}; done
.PHONY: format format_c format_perl format_vim
#!/bin/sh
# vim:ft=zsh
# Helper script for CI to auto indent files
# © 2017 Paul Seyfert and contributors (see also: LICENSE)
if [ -f "$1" ]; then
vim -f +"set softtabstop=2" +"set tabstop=2" +"set shiftwidth=2" +"set expandtab" +"gg=G" +":x" $1
else
echo "USAGE: $0 <filename>"
echo "to autoindent file with vim"
fi
exit $?
---
Language: Cpp
# BasedOnStyle: WebKit
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Never
...
......@@ -5,8 +5,8 @@
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* We can not take this from <sys/ioctl.h>, because it would define the
......@@ -19,7 +19,7 @@ struct winsize {
unsigned short ws_ypixel;
};
int ioctl (int d, int request, char *argp) {
int ioctl(int d, int request, char *argp) {
static int (*orig_ioctl)(int, int, char *);
if (orig_ioctl == NULL) {
orig_ioctl = dlsym(RTLD_NEXT, "ioctl");
......@@ -36,19 +36,19 @@ int ioctl (int d, int request, char *argp) {
* 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 ) {
if (max_rows < 0) {
char *fname = getenv("SHELLEX_SIZE_FILE");
if (fname != NULL && fname[0] != '\0') {
FILE *stream = fopen(fname,"r");
FILE *stream = fopen(fname, "r");
char str[5] = "-500";
if (stream != NULL) {
char *ret = fgets(str,5,stream);
char *ret = fgets(str, 5, stream);
fclose(stream);
if (ret != NULL) {
/* this may be -500 */
max_rows = atoi(str);
if (max_rows > 0 ) {
if (max_rows > 0) {
unlink(fname);
}
}
......@@ -56,7 +56,6 @@ int ioctl (int d, int request, char *argp) {
}
}
int retval = orig_ioctl(d, request, (char *)argp);
struct winsize *ws = (struct winsize *)argp;
......
-pt=2
-ce
-l=91
-b
......@@ -4,19 +4,24 @@
# This is the urxvt extension part of shellex.
# © 2013 Axel Wagner and contributors (see also: LICENSE)
use X11::Protocol;
use File::Temp qw|tempfile|;
use File::Basename qw|basename|;
use POSIX qw|ceil|;
use strict;
# The existing Randr-modules on CPAN seem to work only barely, so instead we
# just parse the output of xrandr -q. This is an uglyness, that should go away
# some time in the feature.
# At the time of the original version of this function, the existing
# Randr-modules on CPAN seem to work only barely, so instead we just parse the
# output of xrandr --listactivemonitors. This is an uglyness, that should go
# away some time in the future.
sub get_outputs {
my @outputs = ();
for my $line (qx(xrandr -q)) {
next unless $line =~ /\sconnected/;
my ($w, $h, $x, $y) = ($line =~ /(\d+)x(\d+)\+(\d+)\+(\d+)/);
for my $line (qx(xrandr --listactivemonitors)) {
next if $line =~ /Monitors: /;
# output looks like:
#Monitors: 2
# 0: +*LVDS-1 1366/277x768/156+0+0 LVDS-1
# 1: +HDMI-2 1920/518x1200/324+1366+0 HDMI-2
my ($w, $h, $x, $y) = ($line =~ /(\d+)\/\d+x(\d+)\/\d+\+(\d+)\+(\d+)/);
print "found monitor with dimensions and position w=$w h=$h x=$x y=$y\n";
push @outputs, { w => $w, h => $h, x => $x, y => $y };
}
return @outputs;
......@@ -32,9 +37,11 @@ sub geometry_from_ptr {
my $ptr = { $self->{X}->QueryPointer($self->DefaultRootWindow) };
for my $output (@outputs) {
if ($output->{x} <= $ptr->{root_x} && $ptr->{root_x} < $output->{x} + $output->{w}) {
if ($output->{x} <= $ptr->{root_x} && $ptr->{root_x} < $output->{x} + $output->{w})
{
$self->{x} = $output->{x};
if ($self->{bottom}) {
# The real y-coordinate will change during execution, when the window grows
$self->{y} = $output->{y} + $output->{h};
} else {
......@@ -54,6 +61,7 @@ sub max {
}
return $max;
}
sub min {
my $min = shift;
while (my $n = shift) {
......@@ -74,6 +82,7 @@ sub geometry_from_focus {
# If the root-window is focused, we fall back to using the pointer-position
if ($focus == $self->DefaultRootWindow) {
print "Fall back to getting shellex-position from pointer\n";
return $self->geometry_from_ptr();
}
......@@ -85,7 +94,8 @@ sub geometry_from_focus {
# The (x,y) coordinates we get are relative to the parent not the
# root-window. So we just translate the coordinates of the upper-left
# corner into the coordinate-system of the root-window
my (undef, undef, $fx, $fy) = $self->{X}->TranslateCoordinates($focus, $self->DefaultRootWindow, 0, 0);
my (undef, undef, $fx, $fy) =
$self->{X}->TranslateCoordinates($focus, $self->DefaultRootWindow, 0, 0);
# Returns the area (in pixel²) of the intersection of two rectangles.
# To understand how it works, best draw a picture.
......@@ -117,6 +127,7 @@ sub geometry_from_focus {
$max_area = $area;
$self->{x} = $output->{x};
if ($self->{bottom}) {
# The real y-coordinate will change during execution, when the window grows
$self->{y} = $output->{y} + $output->{h};
} else {
......@@ -152,10 +163,10 @@ sub on_start {
# TODO: Remove compatibility code in future version
if (defined $self->x_resource("%.edge") || defined $self->x_resource("%.pos")) {
print "WARNING: URxvt.shellex.* resources are deprecated and will be removed in the future. Use shellex.*\n"
print
"WARNING: URxvt.shellex.* resources are deprecated and will be removed in the future. Use shellex.*\n";
}
if ($self->x_resource("edge") eq 'bottom' || $self->x_resource("%.edge") eq 'bottom') {
print "position should be at the bottom\n";
$self->{bottom} = 1;
......@@ -172,11 +183,14 @@ sub on_start {
$self->geometry_from_focus();
}
# This environment variable is used by the LD_PRELOAD ioctl-override to
# determine the values to send to the shell
# 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} ;
# This environment variable is used by the LD_PRELOAD ioctl-override to
# determine the values to send to the shell
# 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} ;
#
# shellex should leave part of the screen uncovered (10 lines), this assumes
# that a screen will always be larger than 10 lines.
my $sane_max_rows = int($self->{h} / $self->fheight) - 10;
$ENV{SHELLEX_MAX_ROWS} = $sane_max_rows;
......@@ -184,7 +198,7 @@ sub on_start {
open(my $fh, '>', $filename);
print $fh "$ENV{SHELLEX_MAX_ROWS}\n";
close $fh;
print "writing max rows file done\n";
print "wrote $sane_max_rows as max rows to $filename done\n";
$self->{border} = $self->x_resource('internalBorder');
......@@ -197,6 +211,7 @@ sub on_start {
my $height = $self->{row_height} + 2 * $self->{border};
my $y = $self->{y};
# Our initial position is different, if we have to be at the bottom
$y -= $height if $self->{bottom};
......@@ -219,20 +234,20 @@ sub on_line_update {
# TODO: Does this work as intended, if there is an empty line in the
# middle?
my $nrow = 0;
for my $i ($self->top_row .. $self->nrow-1) {
for my $i ($self->top_row .. $self->nrow - 1) {
if ($self->ROW_l($i) > 0) {
$nrow++;
}
}
$nrow = $nrow > 0 ? $nrow : 1;
$nrow = $nrow > $ENV{SHELLEX_MAX_ROWS} ? $ENV{SHELLEX_MAX_ROWS} : $nrow;
$nrow = $nrow > 0 ? $nrow : 1;
print "resizing to $nrow\n";
# If the window is supposed to be at the bottom, we have to move the
# window up a little bit
my $y = $self->{y};
if ($self->{bottom}) {
$y -= 2+$nrow*$self->fheight;
$y -= 2 + $nrow * $self->fheight;
}
$self->cmd_parse("\e[8;$nrow;t\e[3;$self->{x};${y}t");
();
......@@ -256,14 +271,15 @@ sub predict_term_size {
$i += $line->end - $line->beg + 1;
unless ($line->beg <= $row && $row <= $line->end) {
$n += $line->end - $line->beg + 1;
next
next;
}
my $len = ($row - $line->beg) * $self->ncol + $col;
# Because there might be control-sequences in $string, affecting the
# number of lines, we need to manually walk it
for (my $j = 0; $j < length($string); $j++) {
for (my $j = 0 ; $j < length($string) ; $j++) {
# Linebreaks mean the creating of a new line, finishing the old one
if (substr($string, $j, 1) eq "\n") {
$len = ($len == 0 ? 1 : $len);
......@@ -271,6 +287,7 @@ sub predict_term_size {
$len = 0;
next;
}
# Carriage-returns mean starting from the beginning. Though the new
# len does not really have to be 0 (because the text is not
# actually erased) it is a good enough estimate for now
......@@ -278,6 +295,7 @@ sub predict_term_size {
$len = 0;
next;
}
# We just add one per other char. This actually might not work
# correctly with wide-chars, but it is a good enough estimate for
# now
......@@ -285,6 +303,7 @@ sub predict_term_size {
}
$n += ceil(($len + 1.0) / $self->ncol);
}
print "Predicting term size: $n\n";
return $n;
}
......@@ -298,15 +317,15 @@ 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;
$nrow = $nrow > 0 ? $nrow : 1;
print "resizing to $nrow\n";
# If the window is supposed to be at the bottom, we have to move the
# window up a little bit
my $y = $self->{y};
if ($self->{bottom}) {
$y -= 2+$nrow*$self->fheight;
$y -= 2 + $nrow * $self->fheight;
}
$self->cmd_parse("\e[8;$nrow;t\e[3;$self->{x};${y}t");
();
......@@ -348,6 +367,7 @@ sub on_map_notify {
my ($self, $ev) = @_;
$self->{X}->SetInputFocus($self->parent, 2, $self->{data}{event}{time});
# We use GetInputFocus as a syncing-mechanism
$self->{X}->GetInputFocus();
......