1
0
mirror of https://github.com/gryf/tabbedalt.git synced 2026-03-27 22:03:34 +01:00

Compare commits

...

4 Commits

Author SHA1 Message Date
8da342b9b0 Fix an issue with confirmation to close terminal.
Sometimes, it happens that closing terminal with mouse/keyboard
confirmation dialog appears (no matter if it was graphical or the one
build on top of urxvt overlay).

The culprit was with lines origin from `ps` command, which wasn't
correctly split, but, what is more important, wasn't properly trimmed.
This commit fixing the issue by removing whitespace from both ends of
the string and splitting using space character rather, than regexp, and
second, be sure to chop off all the whitespace characters before
splitting line and after splitting process name and its arguments.
2024-12-10 19:02:41 +01:00
a9eb5cee5d Added ability to disable tab activity indicator. 2024-06-10 10:42:27 +02:00
7e76d39402 Fix overlay placement depending on the line length 2023-10-28 17:18:32 +02:00
697a698add Added urxvt overlay based dialog for closing window 2023-10-28 17:08:32 +02:00
2 changed files with 89 additions and 33 deletions

View File

@@ -121,6 +121,10 @@ You can change those values but bear in mind, that first group should have
timeout in seconds set higher, than middle one. You can also change symbols for timeout in seconds set higher, than middle one. You can also change symbols for
those groups. those groups.
Tab activity can be disabled by setting::
URxvt.tabbedalt.disable-activity: true
Flickering Flickering
~~~~~~~~~~ ~~~~~~~~~~
@@ -255,14 +259,24 @@ Confirm closing window
When working with tabs, sometimes user accidentally could close the window, and When working with tabs, sometimes user accidentally could close the window, and
loose all the applications run on the tabs. There might be multiple tabs open, loose all the applications run on the tabs. There might be multiple tabs open,
or just one with running process on it (i.e. some editor), where closing window or just one with running process on it (i.e. some editor), where closing window
by accident could result in data loss. To prevent this, there are couple of by accident could result in data loss. To prevent this, there are two
resources to be set. First one, disabled by default is:: additional resources that can be set. First one, disabled by default is::
URxvt.tabbedalt.confirm-quit: false URxvt.tabbedalt.confirm-quit: false
When set to ``true`` it will execute a message program defined in When set to ``true`` it will either execute a message program or will display
``confirm-program`` resource. It might be whatever X program, which can accept an urxvt overlay with the dialog directly on current tab. Note that overlay
text as an argument, and can provide dialog which: dialog will expect the user to either press:
- ``y`` or ``enter`` key to close the window
- ``n`` or ``escape`` key to deny closing it
Second one is to provide X dialog program::
URxvt.tabbedalt.confirm-program:
It might be whatever X program, which can accept text as an argument, and can
provide dialog which:
- have two buttons (i.e. yes/no, ok/cancel) where first will exit dialog with 0 - have two buttons (i.e. yes/no, ok/cancel) where first will exit dialog with 0
exit code and the latter will exit with whatever other number, exit code and the latter will exit with whatever other number,
@@ -282,10 +296,6 @@ or `kdialog`_::
or… any other dialog programs which fulfill the above criteria. or… any other dialog programs which fulfill the above criteria.
Note, that ``confirm-program`` resource have no default value and you'll need
to configure it alongside with the ``confirm-quit``, otherwise ``confirm-quit``
will have no effect.
Creating specific commands/shells Creating specific commands/shells
--------------------------------- ---------------------------------

View File

@@ -152,6 +152,16 @@
# 2023-10-24 21:14:56 # 2023-10-24 21:14:56
# - Added confirmation when closing window when there is more than one tab or # - Added confirmation when closing window when there is more than one tab or
# there is a process still running. # there is a process still running.
#
# 2023-10-28 16:30:32
# - Added overlay based dialog to confirm closing urxvt window
#
# 2024-06-10 10:34:47
# - Added option for disabling activity marks and colors
#
# 2024-12-10 18:30:22
# - Fix an issue with requesting closing terminal, which appear to be a
# single instance
use Scalar::Util; use Scalar::Util;
@@ -225,6 +235,7 @@ package urxvt::ext::tabbedalt::main;
sub tab_activity_mark ($$) { sub tab_activity_mark ($$) {
my ($self, $tab) = @_; my ($self, $tab) = @_;
return ' ' unless defined $tab->{lastActivity}; return ' ' unless defined $tab->{lastActivity};
return ' ' if $self->{disable_activity};
return ' ' if $tab == $self->{cur}; return ' ' if $tab == $self->{cur};
if (defined $self->{timeouts}) { if (defined $self->{timeouts}) {
my $diff = int urxvt::NOW - $tab->{lastActivity}; my $diff = int urxvt::NOW - $tab->{lastActivity};
@@ -303,12 +314,14 @@ sub refresh {
if ($tab == $self->{cur}) { if ($tab == $self->{cur}) {
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab}) x $len; @$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab}) x $len;
} else { } else {
if ($act eq "*") { if (!$self->{disable_activity}) {
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_act}) x $len; if ($act eq "*") {
} elsif ($act eq $self->{timeouts}[0][1]) { @$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_act}) x $len;
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_acd}) x $len; } elsif ($act eq $self->{timeouts}[0][1]) {
} elsif ($act ne " ") { @$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_acd}) x $len;
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_acs}) x $len; } elsif ($act ne " ") {
@$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab_acs}) x $len;
}
} }
} }
@@ -563,6 +576,7 @@ sub init {
$self->{stop_flickering} = $self->x_resource_boolean('stop-flickering'); $self->{stop_flickering} = $self->x_resource_boolean('stop-flickering');
$self->{confirm_quit} = $self->x_resource_boolean('confirm-quit'); $self->{confirm_quit} = $self->x_resource_boolean('confirm-quit');
$self->{confirm_program} = $self->x_resource('confirm-program'); $self->{confirm_program} = $self->x_resource('confirm-program');
$self->{disable_activity} = $self->x_resource_boolean('disable-activity');
my $timeouts = $self->x_resource ("tabbar-timeouts"); my $timeouts = $self->x_resource ("tabbar-timeouts");
$timeouts = '16:.:8:::4:+' unless defined $timeouts; $timeouts = '16:.:8:::4:+' unless defined $timeouts;
@@ -588,6 +602,23 @@ sub init {
} }
sub dialog_key_press {
# react only on certain keys:
# n and ESC - this case will delete the overlay
# y and Enter - in this case, all tabs will be destroyed
my ($tab, $event, $keysym, $str) = @_;
if ($keysym == 0xff0d || $keysym == 0xff8d || $keysym == 0x79) { # enter/y
$tab->disable('key_press');
$_->destroy for @{ $tab->{main}->{tabs} };
} elsif ($keysym == 0xff1b || $keysym == 0x6e) { # escape/n
delete $tab->{overlay};
$tab->disable('key_press');
$tab->{main}->refresh;
}
return 1;
}
_on start => sub { _on start => sub {
my ($self) = @_; my ($self) = @_;
@@ -626,18 +657,19 @@ _on configure_notify => sub {
_on wm_delete_window => sub { _on wm_delete_window => sub {
my ($self) = @_; my ($self) = @_;
if ($self->{confirm_quit} and $self->{confirm_program}) { if ($self->{confirm_quit}) {
my $tab_count = @{ $self->{tabs} }; my $tab_count = @{ $self->{tabs} };
my $subp_count = 0; my $subp_count = 0;
my @subprocesses = split(/\n/, `ps --ppid $$ -o pid=,cmd=`); my @subprocesses = split(/\n/, `ps --ppid $$ -o pid=,cmd=`);
my %process_to_skip = ( "bash"=>1, "zsh"=>1, "ps"=>1, "fish"=>1, "sh"=>1 ); my %process_to_skip = ( "bash"=>1, "zsh"=>1, "ps"=>1, "fish"=>1, "sh"=>1 );
foreach my $line (@subprocesses) { foreach my $line (@subprocesses) {
chomp $line; $line =~ s/^\s+|\s+$//g;
my @split_line = split(/ /, $line); my @split_line = split(" ", $line);
my $pid = @split_line[0]; my $pid = @split_line[0];
my $proc_name = @split_line[1]; my @line = split(" ", @split_line[1]);
chomp $proc_name; my $proc_name = @line[0];
$proc_name =~ s/^\s+|\s+$//g;
if (!exists $process_to_skip{$proc_name}) { if (!exists $process_to_skip{$proc_name}) {
$subp_count = $subp_count + 1; $subp_count = $subp_count + 1;
} else { } else {
@@ -647,27 +679,42 @@ _on wm_delete_window => sub {
if ($tab_count > 1 or $subp_count > 0) { if ($tab_count > 1 or $subp_count > 0) {
my $msg = ""; my $msg = "";
my $qst = "Are you sure you want to close urxvt?";
$msg = "There are $tab_count tabs opened" if ($tab_count > 1); $msg = "There are $tab_count tabs opened" if ($tab_count > 1);
if ($subp_count > 0) { if ($subp_count > 0) {
if (! $msg) { if (! $msg) {
$msg = "There is $subp_count active processes running."; $msg = "There is $subp_count active processes running.";
$msg = "$msg Are you sure you want to close urxvt?";
} else { } else {
$msg = "$msg and there is $subp_count active processes running."; $msg = "$msg and there is $subp_count active processes running.";
$msg = "$msg Are you sure you want to close urxvt?";
} }
}else{
$msg = "$msg. Are you sure you want to close urxvt?";
} }
`$self->{confirm_program} '$msg'`; if ($self->{confirm_program}) {
`$self->{confirm_program} '$msg $qst'`;
if ($? == 0) { if ($? == 0) {
$self->{is_being_destroyed} = 1; $self->{is_being_destroyed} = 1;
# stop the timers, as we changed focus # stop the timers, as we changed focus
$self->{timer}->stop(); $self->{timer}->stop();
$_->destroy for @{ $self->{tabs} }; $_->destroy for @{ $self->{tabs} };
}
} else {
my $marginc = 0;
$qst = "$qst (y/n)";
if ((length $msg) > (length $qst)) {
$marginc = int(($self->ncol - length $msg)/2);
} elsif ((length $msg) <= (length $qst)) {
$marginc = int(($self->ncol - length $qst)/2);
}
my $marginr = int(($self->nrow - 4)/2);
my $tab = $self->{cur};
$tab->{overlay} = $tab->overlay_simple($marginc, $marginr,
"$msg\n$qst");
# action for removing all tabs will be decided in following
# method.
$tab->enable(key_press => \&dialog_key_press);
} }
} else { } else {
$_->destroy for @{ $self->{tabs} }; $_->destroy for @{ $self->{tabs} };
@@ -881,7 +928,6 @@ sub start_rename_tab {
1 1
} }
sub _rename_tab_key_press { sub _rename_tab_key_press {
my ($tab, $event, $keysym, $str) = @_; my ($tab, $event, $keysym, $str) = @_;