output.pm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #
  2. # Copyright 1999, 2000, 2001 Patrik Stridvall
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Lesser General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2.1 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. # Lesser General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Lesser General Public
  15. # License along with this library; if not, write to the Free Software
  16. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  17. #
  18. package output;
  19. use strict;
  20. use warnings 'all';
  21. use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  22. require Exporter;
  23. @ISA = qw(Exporter);
  24. @EXPORT = qw();
  25. @EXPORT_OK = qw($output);
  26. use vars qw($output);
  27. $output = '_output'->new;
  28. package _output;
  29. use strict;
  30. use warnings 'all';
  31. my $stdout_isatty = -t STDOUT;
  32. my $stderr_isatty = -t STDERR;
  33. sub new($) {
  34. my $proto = shift;
  35. my $class = ref($proto) || $proto;
  36. my $self = {};
  37. bless ($self, $class);
  38. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  39. my $progress = \${$self->{PROGRESS}};
  40. my $last_progress = \${$self->{LAST_PROGRESS}};
  41. my $last_time = \${$self->{LAST_TIME}};
  42. my $progress_count = \${$self->{PROGRESS_COUNT}};
  43. my $prefix = \${$self->{PREFIX}};
  44. my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
  45. $$progress_enabled = 1;
  46. $$progress = "";
  47. $$last_progress = "";
  48. $$last_time = 0;
  49. $$progress_count = 0;
  50. $$prefix = undef;
  51. $$prefix_callback = undef;
  52. return $self;
  53. }
  54. sub DESTROY {
  55. my $self = shift;
  56. $self->hide_progress;
  57. }
  58. sub enable_progress($) {
  59. my $self = shift;
  60. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  61. $$progress_enabled = 1;
  62. }
  63. sub disable_progress($) {
  64. my $self = shift;
  65. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  66. $$progress_enabled = 0;
  67. }
  68. sub show_progress($) {
  69. my $self = shift;
  70. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  71. my $progress = ${$self->{PROGRESS}};
  72. my $last_progress = \${$self->{LAST_PROGRESS}};
  73. my $progress_count = \${$self->{PROGRESS_COUNT}};
  74. $$progress_count++;
  75. if($$progress_enabled) {
  76. if($$progress_count > 0 && $$progress && $stderr_isatty) {
  77. # If progress has more than $columns characters the xterm will
  78. # scroll to the next line and our ^H characters will fail to
  79. # erase it.
  80. my $columns=$ENV{COLUMNS} || 80;
  81. $progress = substr $progress,0,($columns-1);
  82. print STDERR $progress;
  83. $$last_progress = $progress;
  84. }
  85. }
  86. }
  87. sub hide_progress($) {
  88. my $self = shift;
  89. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  90. my $progress = \${$self->{PROGRESS}};
  91. my $last_progress = \${$self->{LAST_PROGRESS}};
  92. my $progress_count = \${$self->{PROGRESS_COUNT}};
  93. $$progress_count--;
  94. if($$progress_enabled) {
  95. if($$last_progress && $stderr_isatty) {
  96. my $message=" " x length($$last_progress);
  97. print STDERR $message;
  98. undef $$last_progress;
  99. }
  100. }
  101. }
  102. sub update_progress($) {
  103. my $self = shift;
  104. my $progress_enabled = \${$self->{PROGRESS_ENABLED}};
  105. my $progress = ${$self->{PROGRESS}};
  106. my $last_progress = \${$self->{LAST_PROGRESS}};
  107. if($$progress_enabled) {
  108. # If progress has more than $columns characters the xterm will
  109. # scroll to the next line and our ^H characters will fail to
  110. # erase it.
  111. my $columns=$ENV{COLUMNS} || 80;
  112. $progress = substr $progress,0,($columns-1);
  113. my $prefix = "";
  114. my $suffix = "";
  115. if($$last_progress) {
  116. $prefix = "" x length($$last_progress);
  117. my $diff = length($$last_progress)-length($progress);
  118. if($diff > 0) {
  119. $suffix = (" " x $diff) . ("" x $diff);
  120. }
  121. }
  122. print STDERR $prefix, $progress, $suffix;
  123. $$last_progress = $progress;
  124. }
  125. }
  126. sub progress($$) {
  127. my $self = shift;
  128. my $progress = \${$self->{PROGRESS}};
  129. my $last_time = \${$self->{LAST_TIME}};
  130. my $new_progress = shift;
  131. if(defined($new_progress)) {
  132. if(!defined($$progress) || $new_progress ne $$progress) {
  133. $$progress = $new_progress;
  134. $self->update_progress;
  135. $$last_time = 0;
  136. }
  137. } else {
  138. return $$progress;
  139. }
  140. }
  141. sub lazy_progress($$) {
  142. my $self = shift;
  143. my $progress = \${$self->{PROGRESS}};
  144. my $last_time = \${$self->{LAST_TIME}};
  145. $$progress = shift;
  146. my $time = time();
  147. if($time - $$last_time > 0) {
  148. $self->update_progress;
  149. $$last_time = $time;
  150. }
  151. }
  152. sub prefix($$) {
  153. my $self = shift;
  154. my $prefix = \${$self->{PREFIX}};
  155. my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
  156. my $new_prefix = shift;
  157. if(defined($new_prefix)) {
  158. if(!defined($$prefix) || $new_prefix ne $$prefix) {
  159. $$prefix = $new_prefix;
  160. $$prefix_callback = undef;
  161. }
  162. } else {
  163. return $$prefix;
  164. }
  165. }
  166. sub prefix_callback($) {
  167. my $self = shift;
  168. my $prefix = \${$self->{PREFIX}};
  169. my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
  170. $$prefix = undef;
  171. $$prefix_callback = shift;
  172. }
  173. sub write($$) {
  174. my $self = shift;
  175. my $message = shift;
  176. my $prefix = \${$self->{PREFIX}};
  177. my $prefix_callback = \${$self->{PREFIX_CALLBACK}};
  178. $self->hide_progress if $stdout_isatty;
  179. if(defined($$prefix)) {
  180. print $$prefix . $message;
  181. } elsif(defined($$prefix_callback)) {
  182. print &{$$prefix_callback}() . $message;
  183. } else {
  184. print $message;
  185. }
  186. $self->show_progress if $stdout_isatty;
  187. }
  188. 1;