Hello everyone,

attached is a patch to the tabbed extension adding the following
features:

1. time dependent activity marks (the mark displayed next to the tab
   number depends on the time since last activity in given tab);

2. the "[NEW]" button can be disabled by setting new-button resource to
   false;

3. tab's title is displayed after last button (unless title resource is
   false).  This is handy if you have terminal with no window
   decorations.  Colours can be configured via title-fg and title-bg;

4. tab bar can be hidden if there is only one tab opened (Alexey
   Semenko's <asemenko at gmail.com> patch);

5. tabs are indexed in hex starting with zero -- less space occupied if
   you have 16 tabs opened; and

6. (as a minor modification) final pipe character is removed (unless
   title is displayed).

I'm submitting this patch after receiving criticism that my previous
patch did not update man page -- this one updates documentation as well.

-- 
Best regards,                                         _     _
 .o. | Liege of Serenly Enlightened Majesty of      o' \,=./ `o
 ..o | Computer Science,  Michal "mina86" Nazarewicz   (o o)
 ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
? tabbed.diff
Index: doc/rxvtperl.3.man.in
===================================================================
RCS file: /schmorpforge/rxvt-unicode/doc/rxvtperl.3.man.in,v
retrieving revision 1.66
diff -u -r1.66 rxvtperl.3.man.in
--- doc/rxvtperl.3.man.in	8 Nov 2008 16:49:46 -0000	1.66
+++ doc/rxvtperl.3.man.in	13 Dec 2009 23:30:23 -0000
@@ -384,15 +384,43 @@
 \&\fBShift-Right\fR will switch to the tab left or right of the current one,
 while \fBShift-Down\fR creates a new tab.
 .Sp
+Whenever there's an activity on a\ hidden tab a\ symbol (asterisk ny
+default) will appear next to tab's number.  This mark will change
+depending on the time since last activity (letting you see if
+compilation has finished for instance).
+.Sp
+Moreover, after all the tabs numbers current's tab's title (the thing
+usually visible in window's title bar) is displayed.
+.Sp
 The tabbar itself can be configured similarly to a normal terminal, but
-with a resource class of \f(CW\*(C`URxvt.tabbed\*(C'\fR. In addition, it supports the
-following four resources (shown with defaults):
+with a resource class of \f(CW\*(C`URxvt.tabbed\*(C'\fR.
+.Sp
+Setting the "URxvt.tabbed.new-button" resource to "false" will hide
+the \*(L"[\s-1NEW\s0]\*(R" button.  Setting the
+"URxvt.tabbat.autohide" resource to "true" will make the top bar hide
+if there is only one tab.  Setting the "URxvt.tabbed.title" resource
+to "false" will hide the terminal's title from the top bar.
+.Sp
+The activity marks can be configured as well as via
+"URxvt.tabbed.tabbar-timeouts" resource.  It's format is:
+.Sp
+.Vb 4
+\& ( <time> ":" <char> ":" )* <time> ":" <char> ":"
+.Ve
+.Sp
+where <time> is timeout in seconds and <char> is a single activity
+character.  The default is "16:.:8:::4:+".
+.Sp
+In addition, it supports the following resources (shown with defaults)
+for specifying colours of various elements:
 .Sp
 .Vb 4
 \&   URxvt.tabbed.tabbar\-fg: <colour\-index, default 3>
 \&   URxvt.tabbed.tabbar\-bg: <colour\-index, default 0>
 \&   URxvt.tabbed.tab\-fg:    <colour\-index, default 0>
 \&   URxvt.tabbed.tab\-bg:    <colour\-index, default 1>
+\&   URxvt.tabbed.title\-fg:  <colour\-index, default 2>
+\&   URxvt.tabbed.title\-bg:  <colour\-index, default 0>
 .Ve
 .Sp
 See \fI\s-1COLOR\s0 \s-1AND\s0 \s-1GRAPHICS\s0\fR in the @@RXVT_NAME@@(1) manpage for valid
Index: src/perl/tabbed
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/perl/tabbed,v
retrieving revision 1.25
diff -u -r1.25 tabbed
--- src/perl/tabbed	15 Jun 2008 14:54:44 -0000	1.25
+++ src/perl/tabbed	13 Dec 2009 23:30:23 -0000
@@ -1,40 +1,106 @@
 #! perl
 
+##
+## Tabbed plugin for rxvt-unicode
+## Modified by Michal Nazarewicz (mina86/AT/mina86.com)
+##
+## The following has been added:
+##
+## 1. Depending on time of last activity, activity character differs.
+##    By default, after 4 seconds an asterisk becomes a plus sing,
+##    after next 4 it becomes a colon, and finally, after another 8
+##    seconds it becomes a dot.  This can be configured via
+##    tabbar-timeouts resource.  It's format is:
+##
+##      ( <timeout> ":" <character> ":" )* <timeout> ":" <character> ":"
+##
+##    where <timeout> is timeout in seconds and <character> is
+##    a single activity character.
+##
+## 2. The "[NEW]" button can be disabled (who on Earth uses mouse to
+##    create new tab anyways?) by setting new-button resource to
+##    false.
+##
+## 3. tab's title is displayed after last button unless title resource
+##    is set to false.  This is handy if you have terminal with no
+##    window decorations.  Colours can be configured via title-fg and
+##    title-bg.
+##
+## 4. Incorporated Alexey Semenko <asemenko at gmail.com> patch adding
+##    autohide resource.  If it's true tab bar is hidden if there is
+##    no more then one tab opened.
+##
+## 5. Tabs are indexed in hex starting with zero. :] If you're such
+##    a geek to use urxvt it shouldn't be a problem for you and it
+##    saves few character when many tabs are opened.
+##
+## 6. As a minor modification: Final pipe character is removed (unless
+##    title is displayed).  This make tab bar look nicer.
+##
+
+
+sub tab_activity_mark ($$) {
+   my ($self, $tab) = @_;
+   return ' ' unless defined $tab->{lastActivity};
+   return ' ' if $tab == $self->{cur};
+   if (defined $self->{timeouts}) {
+      my $diff = int urxvt::NOW - $tab->{lastActivity};
+      for my $spec (@{ $self->{timeouts} }) {
+         return $spec->[1] if $diff > $spec->[0];
+      }
+   }
+   '*';
+}
+
+
 sub refresh {
    my ($self) = @_;
 
+   # autohide makes it zero
+   return unless $self->{tabheight};
+
    my $ncol = $self->ncol;
 
    my $text = " " x $ncol;
    my $rend = [($self->{rs_tabbar}) x $ncol];
 
-   my @ofs;
-
-   substr $text, 0, 7, "[NEW] |";
-   @$rend[0 .. 5] = ($self->{rs_tab}) x 6;
-   push @ofs, [0, 6, sub { $_[0]->new_tab }];
+   my ($ofs, $idx, @ofs) = (0, 0);
 
-   my $ofs = 7;
-   my $idx = 0;
+   if ($self->{new_button}) {
+      substr $text, 0, 7, "[NEW] |";
+      @$rend[0 .. 5] = ($self->{rs_tab}) x 6;
+      push @ofs, [0, 6, -1 ];
+      $ofs = 7;
+   }
 
    for my $tab (@{ $self->{tabs} }) {
-      $idx++;
-
-      my $act = $tab->{activity} && $tab != $self->{cur}
-                ? "*" : " ";
-
-      my $txt = "$act$idx$act";
+      my $act = $self->tab_activity_mark($tab);
+      my $txt = sprintf "%s%x%s", $act, $idx, $act;
       my $len = length $txt;
 
       substr $text, $ofs, $len + 1, "$txt|";
       @$rend[$ofs .. $ofs + $len - 1] = ($self->{rs_tab}) x $len
          if $tab == $self->{cur};
 
-      push @ofs, [ $ofs, $ofs + $len, sub { $_[0]->make_current ($tab) } ];
-
+      push @ofs, [ $ofs, $ofs + $len, $idx ];
+      ++$idx;
       $ofs += $len + 1;
    }
 
+   substr $text, --$ofs, 1, ' '; # remove last '|'
+
+   if ($self->{tab_title} && $ofs + 3 < $ncol) {
+      my $term = $self->{term};
+      my @str = $term->XGetWindowProperty($term->parent, $self->{tab_title});
+      if (@str && $str[2]) {
+         my $str = '| ' . $str[2];
+         my $len = length $str;
+         $len = $ncol - $ofs if $ofs + $len > $ncol;
+         substr $text, $ofs, $len, substr $str, 0, $len;
+         @$rend[$ofs + 2 .. $ofs + $len - 1] = ($self->{rs_title}) x ($len - 2);
+      }
+   }
+
    $self->{tabofs} = \...@ofs;
 
    $self->ROW_t (0, $text, 0, 0, $ncol);
@@ -48,6 +114,9 @@
 
    my $offset = $self->fheight;
 
+   $self->{tabheight} = $self->{maxtabheight}
+   unless $self->{autohide} && !(defined $self->{tabs} && @{ $self->{tabs} });
+
    # save a backlink to us, make sure tabbed is inactive
    push @urxvt::TERM_INIT, sub {
       my ($term) = @_;
@@ -68,8 +137,7 @@
    my $term = new urxvt::term
       $self->env, $urxvt::RXVTNAME,
       -embed => $self->parent,
-      @argv,
-   ;
+      @argv;
 }
 
 sub configure {
@@ -90,11 +158,6 @@
    );
 }
 
-sub on_resize_all_windows {
-   my ($self, $width, $height) = @_;
-
-   1
-}
 
 sub copy_properties {
    my ($self) = @_;
@@ -134,7 +197,7 @@
    my ($self, $tab) = @_;
 
    if (my $cur = $self->{cur}) {
-      delete $cur->{activity};
+      delete $cur->{lastActivity};
       $cur->XUnmapWindow ($cur->parent) if $cur->mapped;
       $cur->focus_out;
    }
@@ -148,7 +211,7 @@
    $tab->focus_in if $self->focus;
    
    $tab->XMapWindow ($tab->parent);
-   delete $tab->{activity};
+   delete $tab->{lastActivity};
    $self->refresh;
 
    ()
@@ -180,13 +243,7 @@
 
 sub on_key_release {
    my ($self, $event) = @_;
-
    $self->{cur}->key_release ($event->{state}, $event->{keycode}, $event->{time});
-
-   1
-}
-
-sub on_button_press {
    1
 }
 
@@ -194,18 +251,20 @@
    my ($self, $event) = @_;
 
    if ($event->{row} == 0) {
+      my $col = $event->{col};
       for my $button (@{ $self->{tabofs} }) {
-         $button->[2]->($self, $event)
-            if $event->{col} >= $button->[0]
-               && $event->{col} < $button->[1];
+         last if     $col <  $button->[0];
+         next unless $col <= $button->[1];
+         if ($button->[2] == -1) {
+            $self->new_tab;
+         } else {
+            $self->make_current($self->{tabs}[$button->[2]]);
+         }
       }
+      return 1;
    }
 
-   1
-}
-
-sub on_motion_notify {
-   1
+   ()
 }
 
 sub on_init {
@@ -223,14 +282,40 @@
    my $bg    = $self->x_resource ("tabbar-bg");
    my $tabfg = $self->x_resource ("tab-fg");
    my $tabbg = $self->x_resource ("tab-bg");
+   my $titfg = $self->x_resource ("title-fg");
+   my $titbg = $self->x_resource ("title-bg");
 
    defined $fg    or $fg    = 3;
    defined $bg    or $bg    = 0;
    defined $tabfg or $tabfg = 0;
    defined $tabbg or $tabbg = 1;
+   defined $titfg or $titfg = 2;
+   defined $titbg or $titbg = 0;
 
    $self->{rs_tabbar} = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $fg    + 2, $bg    + 2);
    $self->{rs_tab}    = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $tabfg + 2, $tabbg + 2);
+   $self->{rs_title}  = urxvt::SET_COLOR (urxvt::DEFAULT_RSTYLE, $titfg + 2, $titbg + 2);
+
+
+   my $timeouts = $self->x_resource ("tabbar-timeouts");
+   $timeouts = '16:.:8:::4:+' unless defined $timeouts;
+   if ($timeouts ne '') {
+      my @timeouts;
+      while ($timeouts =~ /^(\d+):(.)(?::(.*))?$/) {
+         push @timeouts, [ int $1, $2 ];
+         $timeouts = defined $3 ? $3 : '';
+      }
+      if (@timeouts) {
+         $self->{timeouts} = [ sort { $b->[0] <=> $a-> [0] } @timeouts ];
+      }
+   }
+
+   $self->{new_button} =
+      ($self->x_resource ('new-button') or 'true') !~ /^(?:false|0|no)/i;
+   $self->{tab_title} =
+      ($self->x_resource ('title') or 'true') !~ /^(?:false|0|no)/i;
+   $self->{autohide} =
+      ($self->x_resource ('autohide') or 'false') !~ /^(?:false|0|no)/i;
 
    ()
 }
@@ -238,7 +323,8 @@
 sub on_start {
    my ($self) = @_;
 
-   $self->{tabheight} = $self->int_bwidth + $self->fheight + $self->lineSpace;
+   $self->{maxtabheight} = $self->int_bwidth + $self->fheight + $self->lineSpace;
+   $self->{tabheight} = $self->{autohide} ? 0 : $self->{maxtabheight};
 
    $self->cmd_parse ("\033[?25l");
 
@@ -248,8 +334,20 @@
       shift @argv;
    } while @argv && $argv[0] ne "-e";
 
+   if ($self->{tab_title}) {
+      $self->{tab_title} = $self->{term}->XInternAtom("WM_NAME", 1);
+   }
+
    $self->new_tab (@argv);
 
+   if (defined $self->{timeouts}) {
+      my $interval = ($self->{timeout...@{ $self->{timeouts} } - 1]->[0]);
+      $interval = int($interval / 4);
+      $self->{timer} = urxvt::timer->new
+                                   ->interval($interval < 1 ? 1 : $interval)
+                                   ->cb ( sub { $self->refresh; } );
+   }
+
    ()
 }
 
@@ -287,6 +385,7 @@
    my ($self, $tab) = @_;
 
    $self->{tabs} = [ grep $_ != $tab, @{ $self->{tabs} } ];
+   $self->{tabheight} = 0 if $self->{autohide} && @{ $self->{tabs} } <= 1;
 
    if (@{ $self->{tabs} }) {
       if ($self->{cur} == $tab) {
@@ -308,30 +407,29 @@
 
    if ($event->{state} & urxvt::ShiftMask) {
       if ($keysym == 0xff51 || $keysym == 0xff53) {
-         my ($idx) = grep $self->{tabs}[$_] == $tab, 0 .. $#{ $self->{tabs} };
-
-         --$idx if $keysym == 0xff51;
-         ++$idx if $keysym == 0xff53;
-
-         $self->make_current ($self->{tabs}[$idx % @{ $self->{tabs}}]);
-         
+         if (@{ $self->{tabs} } > 1) {
+            my $idx = 0;
+            ++$idx while $self->{tabs}[$idx] != $tab;
+            $idx += $keysym - 0xff52;
+            $self->make_current ($self->{tabs}[$idx % @{ $self->{tabs}}]);
+         }
          return 1;
       } elsif ($keysym == 0xff54) {
          $self->new_tab;
 
          return 1;
       }
-   }
-   elsif ($event->{state} & urxvt::ControlMask) {
+   } elsif ($event->{state} & urxvt::ControlMask) {
       if ($keysym == 0xff51 || $keysym == 0xff53) {
-         my ($idx1) = grep $self->{tabs}[$_] == $tab, 0 .. $#{ $self->{tabs} };
-         my  $idx2  = ($idx1 + ($keysym == 0xff51 ? -1 : +1)) % @{ $self->{tabs} };
-
-         ($self->{tabs}[$idx1], $self->{tabs}[$idx2]) =
-            ($self->{tabs}[$idx2], $self->{tabs}[$idx1]);
-
-         $self->make_current ($self->{tabs}[$idx2]);
-
+         if (@{ $self->{tabs} } > 1) {
+            my $idx1 = 0;
+            ++$idx1 while $self->{tabs}[$idx1] != $tab;
+            my $idx2 = ($idx1 + $keysym - 0xff52) % @{ $self->{tabs} };
+
+            ($self->{tabs}[$idx1], $self->{tabs}[$idx2]) =
+                ($self->{tabs}[$idx2], $self->{tabs}[$idx1]);
+            $self->make_current ($self->{tabs}[$idx2]);
+         }
          return 1;
       }
    }
@@ -348,10 +446,13 @@
    ()
 }
 
-sub tab_activity {
+sub tab_add_lines {
    my ($self, $tab) = @_;
 
-   $self->refresh;
+   my $mark = $self->tab_activity_mark($tab);
+   $tab->{lastActivity} = int urxvt::NOW;
+   $self->refresh if $mark ne $self->tab_activity_mark($tab);
+   ()
 }
 
 package urxvt::ext::tabbed::tab;
@@ -360,7 +461,7 @@
 # simply proxies all interesting calls back to the tabbed class.
 
 {
-   for my $hook qw(start destroy key_press property_notify) {
+   for my $hook qw(start destroy key_press property_notify add_lines) {
       eval qq{
          sub on_$hook {
             my \$parent = \$_[0]{term}{parent}
@@ -371,11 +472,3 @@
       die if $@;
    }
 }
-
-sub on_add_lines {
-  $_[0]->{activity}++
-     or $_[0]{term}{parent}->tab_activity ($_[0]);
-  ()
-}
-
-
_______________________________________________
rxvt-unicode mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/rxvt-unicode

Reply via email to