Second pass at adding key files
This commit is contained in:
		
							
								
								
									
										667
									
								
								site/glist/templates/help/GT/File/Diff.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										667
									
								
								site/glist/templates/help/GT/File/Diff.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,667 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
			
		||||
<html xmlns="http://www.w3.org/1999/xhtml">
 | 
			
		||||
<head>
 | 
			
		||||
<title>Algorithm::Diff - Compute `intelligent' differences between two files / lists</title>
 | 
			
		||||
<link rev="made" href="mailto:root@penguin.office.gossamer-threads.com" />
 | 
			
		||||
 | 
			
		||||
<style type="text/css">
 | 
			
		||||
/* $MVD$:fontset("Untitled Font Set 1","ARIEL","HELVETICA","HELV","SANSERIF") */
 | 
			
		||||
/* $MVD$:fontset("Arial","Arial") */
 | 
			
		||||
/* $MVD$:fontset("Arial Black","Arial Black") */
 | 
			
		||||
/* $MVD$:fontset("Algerian","Algerian") */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    background-color: white;
 | 
			
		||||
    font-family: Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size: small;
 | 
			
		||||
    color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
    background-color : white;
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    color : blue;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h3 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    color : black;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h4 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h5 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : blue;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h6 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ul {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ol {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dl {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
li {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
th {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
td {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dl {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dd {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dt {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
    font-family : Courier;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
    font-family : Courier;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mvd-H1 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : 14.0pt;
 | 
			
		||||
    background-color : transparent;
 | 
			
		||||
    background-image : none;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-H2 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : 12.0pt;
 | 
			
		||||
    color : blue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.indent {
 | 
			
		||||
    font-family : "Verdana, Arial, sans-serif";
 | 
			
		||||
    list-style-type : circle;
 | 
			
		||||
    list-style-position : inside;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-indent {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : circle;
 | 
			
		||||
    list-style-position : inside;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pre.programlisting {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    list-style-type : disc;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-PRE-programlisting {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    list-style-type : disc;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-PRE {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.note {
 | 
			
		||||
    margin-left : 28.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-note {
 | 
			
		||||
    margin-left : 28.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-H4 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : normal;
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 6.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : 10.0pt;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mvd-BODY {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.indentnobullet {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-indentnobullet {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body style="background-color: white">
 | 
			
		||||
 | 
			
		||||
<p><a name="__index__"></a></p>
 | 
			
		||||
<!-- INDEX BEGIN -->
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
 | 
			
		||||
	<li><a href="#name">NAME</a></li>
 | 
			
		||||
	<li><a href="#synopsis">SYNOPSIS</a></li>
 | 
			
		||||
	<li><a href="#introduction">INTRODUCTION</a></li>
 | 
			
		||||
	<li><a href="#usage">USAGE</a></li>
 | 
			
		||||
	<ul>
 | 
			
		||||
 | 
			
		||||
		<li><a href="#lcs"><code>LCS</code></a></li>
 | 
			
		||||
		<li><a href="#diff"><code>diff</code></a></li>
 | 
			
		||||
		<li><a href="#sdiff"><code>sdiff</code></a></li>
 | 
			
		||||
		<li><a href="#traverse_sequences"><code>traverse_sequences</code></a></li>
 | 
			
		||||
		<li><a href="#traverse_balanced"><code>traverse_balanced</code></a></li>
 | 
			
		||||
	</ul>
 | 
			
		||||
 | 
			
		||||
	<li><a href="#key_generation_functions">KEY GENERATION FUNCTIONS</a></li>
 | 
			
		||||
	<li><a href="#author">AUTHOR</a></li>
 | 
			
		||||
	<li><a href="#license">LICENSE</a></li>
 | 
			
		||||
	<li><a href="#credits">CREDITS</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
<!-- INDEX END -->
 | 
			
		||||
 | 
			
		||||
<hr />
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h1><a name="name">NAME</a></h1>
 | 
			
		||||
<p>Algorithm::Diff - Compute `intelligent' differences between two files / lists</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="synopsis">SYNOPSIS</a></h1>
 | 
			
		||||
<pre>
 | 
			
		||||
  use GT::File::Diff qw(diff sdiff LCS traverse_sequences
 | 
			
		||||
                         traverse_balanced);</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @lcs    = LCS( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @lcs    = LCS( \@seq1, \@seq2, $key_generation_function );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  $lcsref = LCS( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  $lcsref = LCS( \@seq1, \@seq2, $key_generation_function );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @diffs = diff( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @diffs = diff( \@seq1, \@seq2, $key_generation_function );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @sdiffs = sdiff( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  @sdiffs = sdiff( \@seq1, \@seq2, $key_generation_function );
 | 
			
		||||
  
 | 
			
		||||
  traverse_sequences( \@seq1, \@seq2,
 | 
			
		||||
                     { MATCH => $callback,
 | 
			
		||||
                       DISCARD_A => $callback,
 | 
			
		||||
                       DISCARD_B => $callback,
 | 
			
		||||
                     } );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  traverse_sequences( \@seq1, \@seq2,
 | 
			
		||||
                     { MATCH => $callback,
 | 
			
		||||
                       DISCARD_A => $callback,
 | 
			
		||||
                       DISCARD_B => $callback,
 | 
			
		||||
                     },
 | 
			
		||||
                     $key_generation_function );</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  traverse_balanced( \@seq1, \@seq2,
 | 
			
		||||
                     { MATCH => $callback,
 | 
			
		||||
                       DISCARD_A => $callback,
 | 
			
		||||
                       DISCARD_B => $callback,
 | 
			
		||||
                       CHANGE    => $callback,
 | 
			
		||||
                     } );</pre>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="introduction">INTRODUCTION</a></h1>
 | 
			
		||||
<p>(by Mark-Jason Dominus)</p>
 | 
			
		||||
<p>I once read an article written by the authors of <code>diff</code>; they said
 | 
			
		||||
that they hard worked very hard on the algorithm until they found the
 | 
			
		||||
right one.</p>
 | 
			
		||||
<p>I think what they ended up using (and I hope someone will correct me,
 | 
			
		||||
because I am not very confident about this) was the `longest common
 | 
			
		||||
subsequence' method.  in the LCS problem, you have two sequences of
 | 
			
		||||
items:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
        a b c d f g h j q z</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
        a b c d e f g i j k r x y z</pre>
 | 
			
		||||
<p>and you want to find the longest sequence of items that is present in
 | 
			
		||||
both original sequences in the same order.  That is, you want to find
 | 
			
		||||
a new sequence <em>S</em> which can be obtained from the first sequence by
 | 
			
		||||
deleting some items, and from the secend sequence by deleting other
 | 
			
		||||
items.  You also want <em>S</em> to be as long as possible.  In this case
 | 
			
		||||
<em>S</em> is</p>
 | 
			
		||||
<pre>
 | 
			
		||||
        a b c d f g j z</pre>
 | 
			
		||||
<p>From there it's only a small step to get diff-like output:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
        e   h i   k   q r x y 
 | 
			
		||||
        +   - +   +   - + + +</pre>
 | 
			
		||||
<p>This module solves the LCS problem.  It also includes a canned
 | 
			
		||||
function to generate <code>diff</code>-like output.</p>
 | 
			
		||||
<p>It might seem from the example above that the LCS of two sequences is
 | 
			
		||||
always pretty obvious, but that's not always the case, especially when
 | 
			
		||||
the two sequences have many repeated elements.  For example, consider</p>
 | 
			
		||||
<pre>
 | 
			
		||||
        a x b y c z p d q
 | 
			
		||||
        a b c a x b y c z</pre>
 | 
			
		||||
<p>A naive approach might start by matching up the <code>a</code> and <code>b</code> that
 | 
			
		||||
appear at the beginning of each sequence, like this:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
        a x b y c         z p d q
 | 
			
		||||
        a   b   c a b y c z</pre>
 | 
			
		||||
<p>This finds the common subsequence <code>a b c z</code>.  But actually, the LCS
 | 
			
		||||
is <code>a x b y c z</code>:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
              a x b y c z p d q
 | 
			
		||||
        a b c a x b y c z</pre>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="usage">USAGE</a></h1>
 | 
			
		||||
<p>This module provides three exportable functions, which we'll deal with in
 | 
			
		||||
ascending order of difficulty: <code>LCS</code>, 
 | 
			
		||||
<code>diff</code>, <code>sdiff</code>, <code>traverse_sequences</code>, and <code>traverse_balanced</code>.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="lcs"><code>LCS</code></a></h2>
 | 
			
		||||
<p>Given references to two lists of items, LCS returns an array containing their
 | 
			
		||||
longest common subsequence.  In scalar context, it returns a reference to
 | 
			
		||||
such a list.</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  @lcs    = LCS( \@seq1, \@seq2 );
 | 
			
		||||
  $lcsref = LCS( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<p><code>LCS</code> may be passed an optional third parameter; this is a CODE
 | 
			
		||||
reference to a key generation function.  See <a href="#key_generation_functions">KEY GENERATION FUNCTIONS</a>.</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  @lcs    = LCS( \@seq1, \@seq2, $keyGen );
 | 
			
		||||
  $lcsref = LCS( \@seq1, \@seq2, $keyGen );</pre>
 | 
			
		||||
<p>Additional parameters, if any, will be passed to the key generation
 | 
			
		||||
routine.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="diff"><code>diff</code></a></h2>
 | 
			
		||||
<pre>
 | 
			
		||||
  @diffs     = diff( \@seq1, \@seq2 );
 | 
			
		||||
  $diffs_ref = diff( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<p><code>diff</code> computes the smallest set of additions and deletions necessary
 | 
			
		||||
to turn the first sequence into the second, and returns a description
 | 
			
		||||
of these changes.  The description is a list of <em>hunks</em>; each hunk
 | 
			
		||||
represents a contiguous section of items which should be added,
 | 
			
		||||
deleted, or replaced.  The return value of <code>diff</code> is a list of
 | 
			
		||||
hunks, or, in scalar context, a reference to such a list.</p>
 | 
			
		||||
<p>Here is an example:  The diff of the following two sequences:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  a b c e h j l m n p
 | 
			
		||||
  b c d e f j k l m r s t</pre>
 | 
			
		||||
<p>Result:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
 [ 
 | 
			
		||||
   [ [ '-', 0, 'a' ] ],</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
   [ [ '+', 2, 'd' ] ],</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
   [ [ '-', 4, 'h' ] , 
 | 
			
		||||
     [ '+', 4, 'f' ] ],</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
   [ [ '+', 6, 'k' ] ],</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
   [ [ '-', 8, 'n' ], 
 | 
			
		||||
     [ '-', 9, 'p' ], 
 | 
			
		||||
     [ '+', 9, 'r' ], 
 | 
			
		||||
     [ '+', 10, 's' ], 
 | 
			
		||||
     [ '+', 11, 't' ],
 | 
			
		||||
   ]
 | 
			
		||||
 ]</pre>
 | 
			
		||||
<p>There are five hunks here.  The first hunk says that the <code>a</code> at
 | 
			
		||||
position 0 of the first sequence should be deleted (<code>-</code>).  The second
 | 
			
		||||
hunk says that the <code>d</code> at position 2 of the second sequence should
 | 
			
		||||
be inserted (<code>+</code>).  The third hunk says that the <code>h</code> at position 4
 | 
			
		||||
of the first sequence should be removed and replaced with the <code>f</code>
 | 
			
		||||
from position 4 of the second sequence.  The other two hunks similarly.</p>
 | 
			
		||||
<p><code>diff</code> may be passed an optional third parameter; this is a CODE
 | 
			
		||||
reference to a key generation function.  See <a href="#key_generation_functions">KEY GENERATION FUNCTIONS</a>.</p>
 | 
			
		||||
<p>Additional parameters, if any, will be passed to the key generation
 | 
			
		||||
routine.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="sdiff"><code>sdiff</code></a></h2>
 | 
			
		||||
<pre>
 | 
			
		||||
  @sdiffs     = sdiff( \@seq1, \@seq2 );
 | 
			
		||||
  $sdiffs_ref = sdiff( \@seq1, \@seq2 );</pre>
 | 
			
		||||
<p><code>sdiff</code> computes all necessary components to show two sequences
 | 
			
		||||
and their minimized differences side by side, just like the 
 | 
			
		||||
Unix-utility <em>sdiff</em> does:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    same             same
 | 
			
		||||
    before     |     after
 | 
			
		||||
    old        <     -
 | 
			
		||||
    -          >     new</pre>
 | 
			
		||||
<p>It returns a list of array refs, each pointing to an array of 
 | 
			
		||||
display instructions. In scalar context it returns a reference
 | 
			
		||||
to such a list.</p>
 | 
			
		||||
<p>Display instructions consist of three elements: A modifier indicator
 | 
			
		||||
(<code>+</code>: Element added, <code>-</code>: Element removed, <code>u</code>: Element unmodified, 
 | 
			
		||||
<code>c</code>: Element changed) and the value of the old and new elements, to
 | 
			
		||||
be displayed side by side.</p>
 | 
			
		||||
<p>An <code>sdiff</code> of the following two sequences:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  a b c e h j l m n p
 | 
			
		||||
  b c d e f j k l m r s t</pre>
 | 
			
		||||
<p>results in</p>
 | 
			
		||||
<p>[ [ '-', 'a', ''  ],
 | 
			
		||||
  [ 'u', 'b', 'b' ],
 | 
			
		||||
  [ 'u', 'c', 'c' ],
 | 
			
		||||
  [ '+', '',  'd' ],
 | 
			
		||||
  [ 'u', 'e', 'e' ],
 | 
			
		||||
  [ 'c', 'h', 'f' ],
 | 
			
		||||
  [ 'u', 'j', 'j' ],
 | 
			
		||||
  [ '+', '',  'k' ],
 | 
			
		||||
  [ 'u', 'l', 'l' ],
 | 
			
		||||
  [ 'u', 'm', 'm' ],
 | 
			
		||||
  [ 'c', 'n', 'r' ],
 | 
			
		||||
  [ 'c', 'p', 's' ],
 | 
			
		||||
  [ '+', '', 't' ] ]</p>
 | 
			
		||||
<p><code>sdiff</code> may be passed an optional third parameter; this is a CODE
 | 
			
		||||
reference to a key generation function.  See <a href="#key_generation_functions">KEY GENERATION FUNCTIONS</a>.</p>
 | 
			
		||||
<p>Additional parameters, if any, will be passed to the key generation
 | 
			
		||||
routine.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="traverse_sequences"><code>traverse_sequences</code></a></h2>
 | 
			
		||||
<p><code>traverse_sequences</code> is the most general facility provided by this
 | 
			
		||||
module; <code>diff</code> and <code>LCS</code> are implemented as calls to it.</p>
 | 
			
		||||
<p>Imagine that there are two arrows.  Arrow A points to an element of sequence A,
 | 
			
		||||
and arrow B points to an element of the sequence B.  Initially, the arrows
 | 
			
		||||
point to the first elements of the respective sequences.  <code>traverse_sequences</code>
 | 
			
		||||
will advance the arrows through the sequences one element at a time, calling an
 | 
			
		||||
appropriate user-specified callback function before each advance.  It
 | 
			
		||||
willadvance the arrows in such a way that if there are equal elements <code>$A[$i]</code>
 | 
			
		||||
and <code>$B[$j]</code> which are equal and which are part of the LCS, there will be
 | 
			
		||||
some moment during the execution of <code>traverse_sequences</code> when arrow A is
 | 
			
		||||
pointing to <code>$A[$i]</code> and arrow B is pointing to <code>$B[$j]</code>.  When this happens,
 | 
			
		||||
<code>traverse_sequences</code> will call the <code>MATCH</code> callback function and then it will
 | 
			
		||||
advance both arrows.</p>
 | 
			
		||||
<p>Otherwise, one of the arrows is pointing to an element of its sequence that is
 | 
			
		||||
not part of the LCS.  <code>traverse_sequences</code> will advance that arrow and will
 | 
			
		||||
call the <code>DISCARD_A</code> or the <code>DISCARD_B</code> callback, depending on which arrow it
 | 
			
		||||
advanced.  If both arrows point to elements that are not part of the LCS, then
 | 
			
		||||
<code>traverse_sequences</code> will advance one of them and call the appropriate
 | 
			
		||||
callback, but it is not specified which it will call.</p>
 | 
			
		||||
<p>The arguments to <code>traverse_sequences</code> are the two sequences to traverse, and a
 | 
			
		||||
hash which specifies the callback functions, like this:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  traverse_sequences( \@seq1, \@seq2,
 | 
			
		||||
                     { MATCH => $callback_1,
 | 
			
		||||
                       DISCARD_A => $callback_2,
 | 
			
		||||
                       DISCARD_B => $callback_3,
 | 
			
		||||
                     } );</pre>
 | 
			
		||||
<p>Callbacks for MATCH, DISCARD_A, and DISCARD_B are invoked with at least the
 | 
			
		||||
indices of the two arrows as their arguments.  They are not expected to return
 | 
			
		||||
any values.  If a callback is omitted from the table, it is not called.</p>
 | 
			
		||||
<p>Callbacks for A_FINISHED and B_FINISHED are invoked with at least the
 | 
			
		||||
corresponding index in A or B.</p>
 | 
			
		||||
<p>If arrow A reaches the end of its sequence, before arrow B does,
 | 
			
		||||
<code>traverse_sequences</code> will call the <code>A_FINISHED</code> callback when it advances
 | 
			
		||||
arrow B, if there is such a function; if not it will call <code>DISCARD_B</code> instead.
 | 
			
		||||
Similarly if arrow B finishes first.  <code>traverse_sequences</code> returns when both
 | 
			
		||||
arrows are at the ends of their respective sequences.  It returns true on
 | 
			
		||||
success and false on failure.  At present there is no way to fail.</p>
 | 
			
		||||
<p><code>traverse_sequences</code> may be passed an optional fourth parameter; this is a
 | 
			
		||||
CODE reference to a key generation function.  See <a href="#key_generation_functions">KEY GENERATION FUNCTIONS</a>.</p>
 | 
			
		||||
<p>Additional parameters, if any, will be passed to the key generation function.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="traverse_balanced"><code>traverse_balanced</code></a></h2>
 | 
			
		||||
<p><code>traverse_balanced</code> is an alternative to <code>traverse_sequences</code>. It
 | 
			
		||||
uses a different algorithm to iterate through the entries in the
 | 
			
		||||
computed LCS. Instead of sticking to one side and showing element changes
 | 
			
		||||
as insertions and deletions only, it will jump back and forth between
 | 
			
		||||
the two sequences and report <em>changes</em> occurring as deletions on one
 | 
			
		||||
side followed immediatly by an insertion on the other side.</p>
 | 
			
		||||
<p>In addition to the 
 | 
			
		||||
<code>DISCARD_A</code>,
 | 
			
		||||
<code>DISCARD_B</code>, and
 | 
			
		||||
<code>MATCH</code>
 | 
			
		||||
callbacks supported by <code>traverse_sequences</code>, <code>traverse_balanced</code> supports
 | 
			
		||||
a <code>CHANGE</code> callback indicating that one element got <code>replaced</code> by another:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  traverse_sequences( \@seq1, \@seq2,
 | 
			
		||||
                     { MATCH => $callback_1,
 | 
			
		||||
                       DISCARD_A => $callback_2,
 | 
			
		||||
                       DISCARD_B => $callback_3,
 | 
			
		||||
                       CHANGE    => $callback_4,
 | 
			
		||||
                     } );</pre>
 | 
			
		||||
<p>If no <code>CHANGE</code> callback is specified, <code>traverse_balanced</code>
 | 
			
		||||
will map <code>CHANGE</code> events to <code>DISCARD_A</code> and <code>DISCARD_B</code> actions,
 | 
			
		||||
therefore resulting in a similar behaviour as <code>traverse_sequences</code>
 | 
			
		||||
with different order of events.</p>
 | 
			
		||||
<p><code>traverse_balanced</code> might be a bit slower than <code>traverse_sequences</code>,
 | 
			
		||||
noticable only while processing huge amounts of data.</p>
 | 
			
		||||
<p>The <code>sdiff</code> function of this module 
 | 
			
		||||
is implemented as call to <code>traverse_balanced</code>.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="key_generation_functions">KEY GENERATION FUNCTIONS</a></h1>
 | 
			
		||||
<p><code>diff</code>, <code>LCS</code>, and <code>traverse_sequences</code> accept an optional last parameter.
 | 
			
		||||
This is a CODE reference to a key generating (hashing) function that should
 | 
			
		||||
return a string that uniquely identifies a given element.  It should be the
 | 
			
		||||
case that if two elements are to be considered equal, their keys should be the
 | 
			
		||||
same (and the other way around).  If no key generation function is provided,
 | 
			
		||||
the key will be the element as a string.</p>
 | 
			
		||||
<p>By default, comparisons will use ``eq'' and elements will be turned into keys
 | 
			
		||||
using the default stringizing operator '``'''.</p>
 | 
			
		||||
<p>Where this is important is when you're comparing something other than strings.
 | 
			
		||||
If it is the case that you have multiple different objects that should be
 | 
			
		||||
considered to be equal, you should supply a key generation function. Otherwise,
 | 
			
		||||
you have to make sure that your arrays contain unique references.</p>
 | 
			
		||||
<p>For instance, consider this example:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  package Person;</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  sub new
 | 
			
		||||
  {
 | 
			
		||||
    my $package = shift;
 | 
			
		||||
    return bless { name => '', ssn => '', @_ }, $package;
 | 
			
		||||
  }</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  sub clone
 | 
			
		||||
  {
 | 
			
		||||
    my $old = shift;
 | 
			
		||||
    my $new = bless { %$old }, ref($old);
 | 
			
		||||
  }</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  sub hash
 | 
			
		||||
  {
 | 
			
		||||
    return shift()->{'ssn'};
 | 
			
		||||
  }</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
  my $person1 = Person->new( name => 'Joe', ssn => '123-45-6789' );
 | 
			
		||||
  my $person2 = Person->new( name => 'Mary', ssn => '123-47-0000' );
 | 
			
		||||
  my $person3 = Person->new( name => 'Pete', ssn => '999-45-2222' );
 | 
			
		||||
  my $person4 = Person->new( name => 'Peggy', ssn => '123-45-9999' );
 | 
			
		||||
  my $person5 = Person->new( name => 'Frank', ssn => '000-45-9999' );</pre>
 | 
			
		||||
<p>If you did this:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  my $array1 = [ $person1, $person2, $person4 ];
 | 
			
		||||
  my $array2 = [ $person1, $person3, $person4, $person5 ];
 | 
			
		||||
  GT::File::Diff::diff( $array1, $array2 );</pre>
 | 
			
		||||
<p>everything would work out OK (each of the objects would be converted
 | 
			
		||||
into a string like ``Person=HASH(0x82425b0)'' for comparison).</p>
 | 
			
		||||
<p>But if you did this:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  my $array1 = [ $person1, $person2, $person4 ];
 | 
			
		||||
  my $array2 = [ $person1, $person3, $person4->clone(), $person5 ];
 | 
			
		||||
  GT::File::Diff::diff( $array1, $array2 );</pre>
 | 
			
		||||
<p>$person4 and $person4-><code>clone()</code> (which have the same name and SSN)
 | 
			
		||||
would be seen as different objects. If you wanted them to be considered
 | 
			
		||||
equivalent, you would have to pass in a key generation function:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
  my $array1 = [ $person1, $person2, $person4 ];
 | 
			
		||||
  my $array2 = [ $person1, $person3, $person4->clone(), $person5 ];
 | 
			
		||||
  GT::File::Diff::diff( $array1, $array2, \&Person::hash );</pre>
 | 
			
		||||
<p>This would use the 'ssn' field in each Person as a comparison key, and
 | 
			
		||||
so would consider $person4 and $person4-><code>clone()</code> as equal.</p>
 | 
			
		||||
<p>You may also pass additional parameters to the key generation function
 | 
			
		||||
if you wish.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="author">AUTHOR</a></h1>
 | 
			
		||||
<p>This version by Ned Konz, <a href="mailto:perl@bike-nomad.com">perl@bike-nomad.com</a></p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="license">LICENSE</a></h1>
 | 
			
		||||
<p>Copyright (c) 2000-2002 Ned Konz.  All rights reserved.
 | 
			
		||||
This program is free software;
 | 
			
		||||
you can redistribute it and/or modify it under the same terms
 | 
			
		||||
as Perl itself.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="credits">CREDITS</a></h1>
 | 
			
		||||
<p>Versions through 0.59 (and much of this documentation) were written by:</p>
 | 
			
		||||
<p>Mark-Jason Dominus, <a href="mailto:mjd-perl-diff@plover.com">mjd-perl-diff@plover.com</a></p>
 | 
			
		||||
<p>This version borrows the documentation and names of the routines
 | 
			
		||||
from Mark-Jason's, but has all new code in Diff.pm.</p>
 | 
			
		||||
<p>This code was adapted from the Smalltalk code of
 | 
			
		||||
Mario Wolczko <<a href="mailto:mario@wolczko.com">mario@wolczko.com</a>>, which is available at
 | 
			
		||||
<a href="ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st">ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st</a></p>
 | 
			
		||||
<p><code>sdiff</code> and <code>traverse_balanced</code> were written by Mike Schilli
 | 
			
		||||
<<a href="mailto:m@perlmeister.com">m@perlmeister.com</a>>.</p>
 | 
			
		||||
<p>The algorithm is that described in 
 | 
			
		||||
<em>A Fast Algorithm for Computing Longest Common Subsequences</em>,
 | 
			
		||||
CACM, vol.20, no.5, pp.350-353, May 1977, with a few
 | 
			
		||||
minor improvements to improve the speed.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										580
									
								
								site/glist/templates/help/GT/File/Tools.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										580
									
								
								site/glist/templates/help/GT/File/Tools.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,580 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 | 
			
		||||
<html xmlns="http://www.w3.org/1999/xhtml">
 | 
			
		||||
<head>
 | 
			
		||||
<title>GT::File::Tools - Export tools for dealing with files</title>
 | 
			
		||||
<link rev="made" href="mailto:root@penguin.office.gossamer-threads.com" />
 | 
			
		||||
 | 
			
		||||
<style type="text/css">
 | 
			
		||||
/* $MVD$:fontset("Untitled Font Set 1","ARIEL","HELVETICA","HELV","SANSERIF") */
 | 
			
		||||
/* $MVD$:fontset("Arial","Arial") */
 | 
			
		||||
/* $MVD$:fontset("Arial Black","Arial Black") */
 | 
			
		||||
/* $MVD$:fontset("Algerian","Algerian") */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    background-color: white;
 | 
			
		||||
    font-family: Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size: small;
 | 
			
		||||
    color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p {
 | 
			
		||||
    background-color : white;
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h2 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    color : blue;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h3 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : medium;
 | 
			
		||||
    color : black;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h4 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h5 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : blue;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
h6 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ul {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ol {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dl {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
li {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
th {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
td {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dl {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dd {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dt {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
    font-family : Courier;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
    font-family : Courier;
 | 
			
		||||
    font-size : small;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mvd-H1 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : bold;
 | 
			
		||||
    font-size : 14.0pt;
 | 
			
		||||
    background-color : transparent;
 | 
			
		||||
    background-image : none;
 | 
			
		||||
    color : maroon;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-H2 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : 12.0pt;
 | 
			
		||||
    color : blue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.indent {
 | 
			
		||||
    font-family : "Verdana, Arial, sans-serif";
 | 
			
		||||
    list-style-type : circle;
 | 
			
		||||
    list-style-position : inside;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-indent {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : circle;
 | 
			
		||||
    list-style-position : inside;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pre.programlisting {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    list-style-type : disc;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-PRE-programlisting {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    list-style-type : disc;
 | 
			
		||||
    margin-left : 16.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-PRE {
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.note {
 | 
			
		||||
    margin-left : 28.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-note {
 | 
			
		||||
    margin-left : 28.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-H4 {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-weight : normal;
 | 
			
		||||
    font-size : 9.0pt;
 | 
			
		||||
    color : black;
 | 
			
		||||
    margin-left : 6.0pt;
 | 
			
		||||
    margin-top : -14.0pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    font-size : 10.0pt;
 | 
			
		||||
    color : black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mvd-BODY {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    background-color : white;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
p.indentnobullet {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.mvd-P-indentnobullet {
 | 
			
		||||
    font-family : Verdana, Arial, sans-serif;
 | 
			
		||||
    list-style-type : none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body style="background-color: white">
 | 
			
		||||
 | 
			
		||||
<p><a name="__index__"></a></p>
 | 
			
		||||
<!-- INDEX BEGIN -->
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
 | 
			
		||||
	<li><a href="#name">NAME</a></li>
 | 
			
		||||
	<li><a href="#synopsis">SYNOPSIS</a></li>
 | 
			
		||||
	<li><a href="#description">DESCRIPTION</a></li>
 | 
			
		||||
	<li><a href="#functions">FUNCTIONS</a></li>
 | 
			
		||||
	<ul>
 | 
			
		||||
 | 
			
		||||
		<li><a href="#find">find</a></li>
 | 
			
		||||
		<li><a href="#move">move</a></li>
 | 
			
		||||
		<li><a href="#del">del</a></li>
 | 
			
		||||
		<li><a href="#deldir">deldir</a></li>
 | 
			
		||||
		<li><a href="#copy">copy</a></li>
 | 
			
		||||
		<li><a href="#mkpath">mkpath</a></li>
 | 
			
		||||
		<li><a href="#parsefile">parsefile</a></li>
 | 
			
		||||
		<li><a href="#dirname">dirname</a></li>
 | 
			
		||||
		<li><a href="#basename">basename</a></li>
 | 
			
		||||
		<li><a href="#expand">expand</a></li>
 | 
			
		||||
	</ul>
 | 
			
		||||
 | 
			
		||||
	<li><a href="#see_also">SEE ALSO</a></li>
 | 
			
		||||
	<li><a href="#maintainer">MAINTAINER</a></li>
 | 
			
		||||
	<li><a href="#copyright">COPYRIGHT</a></li>
 | 
			
		||||
	<li><a href="#version">VERSION</a></li>
 | 
			
		||||
</ul>
 | 
			
		||||
<!-- INDEX END -->
 | 
			
		||||
 | 
			
		||||
<hr />
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h1><a name="name">NAME</a></h1>
 | 
			
		||||
<p>GT::File::Tools - Export tools for dealing with files</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="synopsis">SYNOPSIS</a></h1>
 | 
			
		||||
<pre>
 | 
			
		||||
    use GT::File::Tools qw/:all/;
 | 
			
		||||
    
 | 
			
		||||
    # Find all files in a users home directory.
 | 
			
		||||
    find "/home/user", sub { print shift };
 | 
			
		||||
    
 | 
			
		||||
    # Rename a file1 to file2.
 | 
			
		||||
    move "file1", "file2";</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Remove a list of files.
 | 
			
		||||
    del @files;</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Remove a users home directory
 | 
			
		||||
    deldir "/home/foo";</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Copy a file
 | 
			
		||||
    copy "file1", "file2";</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Recursively copy a directory.
 | 
			
		||||
    copy "/home/user", "/home/user.bak";</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Recursively make a directory.
 | 
			
		||||
    mkpath "/home/user/www/cgi-bin", 0755;</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Parse a filename into directory, file and is_relative components
 | 
			
		||||
    my ($dir, $file, $is_rel) = parsefile("/home/foo/file.txt");</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Get the file portion of a filename
 | 
			
		||||
    my $file = basename("/home/foo/file.txt");</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Get the directory portion of a filename.
 | 
			
		||||
    my $dir = dirname("/home/foo/file.txt");</pre>
 | 
			
		||||
<pre>
 | 
			
		||||
    # Use shell like expansion to get a list of absolute files.
 | 
			
		||||
    my @src = expand("*.c", "*.h");</pre>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="description">DESCRIPTION</a></h1>
 | 
			
		||||
<p>GT::File::Tools is designed to export requested functions into your namespace.
 | 
			
		||||
These function perform various file operations.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="functions">FUNCTIONS</a></h1>
 | 
			
		||||
<p>GT::File::Tools exports functions to your namespace. Here is a list of the
 | 
			
		||||
functions you can request to be exported.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="find">find</a></h2>
 | 
			
		||||
<p><code>find</code> takes three parameters: directory to search in, callback to run for
 | 
			
		||||
each file and/or directory found, and a hash ref of options. <strong>Note</strong>: this is
 | 
			
		||||
the opposite order of File::Find's <code>find()</code> function! The following options
 | 
			
		||||
can be passed set:</p>
 | 
			
		||||
<dl>
 | 
			
		||||
<dt><strong><a name="item_globbing">globbing</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
Expand filenames in the same way as the unix shell:
 | 
			
		||||
</dd>
 | 
			
		||||
<dd>
 | 
			
		||||
<pre>
 | 
			
		||||
    find("/home/a*", sub { print shift; }, { globbing => 1 });</pre>
 | 
			
		||||
</dd>
 | 
			
		||||
<dd>
 | 
			
		||||
<p>would fine all home directories starting with the letter a. This option is 
 | 
			
		||||
off by default.</p>
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_error_handler">error_handler</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
A code ref that is run whenever find encounters an error. If the callback 
 | 
			
		||||
returns 0, find will stop immediately, otherwise find will continue 
 | 
			
		||||
searching (default).
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_no_chdir">no_chdir</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
By default, find will chdir into the directories it is searching as
 | 
			
		||||
this results in a dramatic performance improvement. Upon completion, find
 | 
			
		||||
will chdir back to the original directory. This behavior is on by default.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_dirs_first">dirs_first</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option controls the order find traverses. It defaults on, and means 
 | 
			
		||||
find will go down directories first before looking at files. This is 
 | 
			
		||||
essential for recursively deleting a directory.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_files_only">files_only</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option tells find to run the callback only for each file found
 | 
			
		||||
and not for each directory. Off by default.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_dirs_only">dirs_only</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option tells find to run the callback only for each directory found
 | 
			
		||||
and not for each file. Off by default.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_max_depth">max_depth</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
Defaults to 1000, this option controls how deep a directory structure find
 | 
			
		||||
will traverse. Meant mainly as a safety, and should not need to be adjusted.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p></dl>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="move">move</a></h2>
 | 
			
		||||
<p><code>move</code> has the same syntax as the system mv command:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    move 'file', 'file2';
 | 
			
		||||
    move 'file1', 'file2', 'dir';
 | 
			
		||||
    move 'file1', 'file2', 'dir3', 'dir';
 | 
			
		||||
    move '*.c', 'dir', { globbing => 1 };</pre>
 | 
			
		||||
<p>The only difference is the last argument can be a hash ref of options. The 
 | 
			
		||||
following options are allowed:</p>
 | 
			
		||||
<dl>
 | 
			
		||||
<dt><strong>globbing</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>error_handler</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>max_depth</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
</dl>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="del">del</a></h2>
 | 
			
		||||
<p><code>del</code> has the same syntax as the rm system command, but it can not remove
 | 
			
		||||
directories. Use <code>deldir</code> below to recursively remove files.</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    del 'file1';
 | 
			
		||||
    del '*.c', { globbing => 1 };
 | 
			
		||||
    del 'a', 'b', 'c';</pre>
 | 
			
		||||
<p>It takes a list of files or directories to delete, and an optional hash ref 
 | 
			
		||||
of options. The following options are allowed:</p>
 | 
			
		||||
<dl>
 | 
			
		||||
<dt><strong>error_handler</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>globbing</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
</dl>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="deldir">deldir</a></h2>
 | 
			
		||||
<p><code>deldir</code> is similiar to <code>del</code>, but allows recursive deletes of directories:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    deldir 'file1';
 | 
			
		||||
    deldir 'dir11', 'dir2', 'dir3';
 | 
			
		||||
    deldir '/home/a*', { globbing => 1 };</pre>
 | 
			
		||||
<p>It takes a list of files and/or directories to remove, and an optional hash ref
 | 
			
		||||
of options. The following options are allowed:</p>
 | 
			
		||||
<dl>
 | 
			
		||||
<dt><strong>error_handler</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>globbing</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>max_depth</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
</dl>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="copy">copy</a></h2>
 | 
			
		||||
<p><code>copy</code> is similiar to the system cp command:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    copy 'file1', 'file2';
 | 
			
		||||
    copy 'file1', 'file2', 'file3', 'dir1';
 | 
			
		||||
    copy '*.c', '/usr/local/src', { globbing => 1 };
 | 
			
		||||
    copy</pre>
 | 
			
		||||
<p>It copies a source file to a destination file or directory. You can also 
 | 
			
		||||
specify multiple source files, and copy them into a single directory. The 
 | 
			
		||||
last argument should be a hash ref of options:</p>
 | 
			
		||||
<dl>
 | 
			
		||||
<dt><strong><a name="item_set_perms">set_perms</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option will preserve permissions. i.e.: if the original file is set 755,
 | 
			
		||||
the copy will also be set 755. It defaults on.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_set_owner">set_owner</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option will preserver file ownership. Note: you must be root to be able
 | 
			
		||||
to change ownerhsip of a file. This defaults off.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_set_time">set_time</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option will preserve file modification time.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong><a name="item_preserve_all">preserve_all</a></strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dd>
 | 
			
		||||
This option sets set_perms, set_owner and set_time on.
 | 
			
		||||
</dd>
 | 
			
		||||
<p></p>
 | 
			
		||||
<dt><strong>error_handler</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>globbing</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
<dt><strong>max_depth</strong><br />
 | 
			
		||||
</dt>
 | 
			
		||||
</dl>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="mkpath">mkpath</a></h2>
 | 
			
		||||
<p><code>mkpath</code> recursively makes a directory. It takes the same arguments as 
 | 
			
		||||
perl's mkdir():</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    mkpath("/home/alex/create/these/dirs", 0755) or die "Can't mkpath: $!";</pre>
 | 
			
		||||
<p>For compatibility with older module versions, <code>rmkdir()</code> is an alias for
 | 
			
		||||
mkpath().</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="parsefile">parsefile</a></h2>
 | 
			
		||||
<p>This function takes any type of filename (relative, fullpath, etc) and 
 | 
			
		||||
returns the inputs directory, file, and whether it is a relative path or
 | 
			
		||||
not. For example:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    my ($directory, $file, $is_relative) = parsefile("../foo/bar.txt");</pre>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="dirname">dirname</a></h2>
 | 
			
		||||
<p>Returns the directory portion of a filename.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="basename">basename</a></h2>
 | 
			
		||||
<p>Returns the last portion of a filename (typically, the filename itself without
 | 
			
		||||
any leading directory).  A deprecated <code>filename()</code> alias for <code>basename()</code> also
 | 
			
		||||
exists.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<h2><a name="expand">expand</a></h2>
 | 
			
		||||
<p>Uses shell like expansion to expand a list of filenames to full paths. For 
 | 
			
		||||
example:</p>
 | 
			
		||||
<pre>
 | 
			
		||||
    my @source   = expand("*.c", "*.h");
 | 
			
		||||
    my @homedirs = expand("/home/*");</pre>
 | 
			
		||||
<p>If you pass in relative paths, expand always returns absolute paths of 
 | 
			
		||||
expanded files. <strong>Note</strong>: this does not actually go to the shell.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="see_also">SEE ALSO</a></h1>
 | 
			
		||||
<p>This module depends on perl's Cwd module for getting the current working
 | 
			
		||||
directory. It also uses GT::AutoLoader to load on demand functions.</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="maintainer">MAINTAINER</a></h1>
 | 
			
		||||
<p>Scott Beck</p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="copyright">COPYRIGHT</a></h1>
 | 
			
		||||
<p>Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
 | 
			
		||||
<a href="http://www.gossamer-threads.com/">http://www.gossamer-threads.com/</a></p>
 | 
			
		||||
<p>
 | 
			
		||||
</p>
 | 
			
		||||
<hr />
 | 
			
		||||
<h1><a name="version">VERSION</a></h1>
 | 
			
		||||
<p>Revision: $Id: Tools.pm,v 1.61 2005/05/13 01:48:23 jagerman Exp $</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user