Patchwork hgweb: code selection in file view without line numbers

login
register
mail settings
Submitter Alexander Plavin
Date April 17, 2013, 2:07 p.m.
Message ID <1933896b16c821ba1e54.1366207651@debian-alexander.dolgopa>
Download mbox | patch
Permalink /patch/1384/
State Superseded, archived
Headers show

Comments

Alexander Plavin - April 17, 2013, 2:07 p.m.
# HG changeset patch
# User Alexander Plavin <me@aplavin.ru>
# Date 1366205259 -14400
#      Wed Apr 17 17:27:39 2013 +0400
# Node ID 1933896b16c821ba1e54e397f15e3f521aaf8909
# Parent  4d32c86be3fad13cbe42ce3f51b0fdacf295f30f
hgweb: code selection in file view without line numbers

Only single file views changed, and only default templates set ('paper')
Mads Kiilerich - April 17, 2013, 2:43 p.m.
On 04/17/2013 04:07 PM, Alexander Plavin wrote:
> # HG changeset patch
> # User Alexander Plavin <me@aplavin.ru>
> # Date 1366205259 -14400
> #      Wed Apr 17 17:27:39 2013 +0400
> # Node ID 1933896b16c821ba1e54e397f15e3f521aaf8909
> # Parent  4d32c86be3fad13cbe42ce3f51b0fdacf295f30f
> hgweb: code selection in file view without line numbers
>
> Only single file views changed, and only default templates set ('paper')

Some questions that it might make sense to answer in the commit description:

What was the problem - both the user experience and the technical 
explanation?

Will the patch remove the line numbers completely or what trick will it 
use to make sure they don't get selected?

Will this for instance change how huge text files will be transmitted 
and rendered on the fly? Is using a method that is similar to what 
similar tools and sites use?

/Mads


>
> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/filerevision.tmpl
> --- a/mercurial/templates/paper/filerevision.tmpl	Wed Apr 10 20:45:10 2013 +0400
> +++ b/mercurial/templates/paper/filerevision.tmpl	Wed Apr 17 17:27:39 2013 +0400
> @@ -68,7 +68,8 @@
>   
>   <div class="overflow">
>   <div class="sourcefirst"> line source</div>
> -{text%fileline}
> +<pre class="sourcenumbers">{text%filelinenum}</pre>
> +<pre class="source">{text%fileline}</pre>
>   <div class="sourcelast"></div>
>   </div>
>   </div>
> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/map
> --- a/mercurial/templates/paper/map	Wed Apr 10 20:45:10 2013 +0400
> +++ b/mercurial/templates/paper/map	Wed Apr 17 17:27:39 2013 +0400
> @@ -72,7 +72,9 @@
>   filecomparison = filecomparison.tmpl
>   filelog = filelog.tmpl
>   fileline = '
> -  <div class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
> +  {line|escape|strip}'
> +filelinenum = '
> +  <a href="#{lineid}" id="{lineid}">{linenumber} </a>'
>   filelogentry = filelogentry.tmpl
>   
>   annotateline = '
> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/static/style-paper.css
> --- a/mercurial/templates/static/style-paper.css	Wed Apr 10 20:45:10 2013 +0400
> +++ b/mercurial/templates/static/style-paper.css	Wed Apr 17 17:27:39 2013 +0400
> @@ -198,7 +198,7 @@
>   .bigtable td.annotate { font-size: smaller; }
>   .bigtable td.source { font-size: inherit; }
>   
> -.source, .sourcefirst, .sourcelast {
> +.source, .sourcefirst, .sourcelast, .sourcenumbers {
>     font-family: monospace;
>     white-space: pre;
>     padding: 1px 4px;
> @@ -206,7 +206,8 @@
>   }
>   .sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
>   .sourcelast { border-top: 1px solid #999; }
> -.source a { color: #999; font-size: smaller; font-family: monospace;}
> +.sourcenumbers { float: left; }
> +.sourcenumbers a { color: #999; font-size: smaller; font-family: monospace; }
>   .bottomline { border-bottom: 1px solid #999; }
>   
>   .fileline { font-family: monospace; }
> diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-hgweb-commands.t
> --- a/tests/test-hgweb-commands.t	Wed Apr 10 20:45:10 2013 +0400
> +++ b/tests/test-hgweb-commands.t	Wed Apr 17 17:27:39 2013 +0400
> @@ -668,9 +668,10 @@
>     
>     <div class="overflow">
>     <div class="sourcefirst"> line source</div>
> -
> -  <div class="source"><a href="#l1" id="l1">     1</a> foo
> -  </div>
> +  <pre class="sourcenumbers">
> +  <a href="#l1" id="l1">     1 </a></pre>
> +  <pre class="source">
> +  foo</pre>
>     <div class="sourcelast"></div>
>     </div>
>     </div>
> diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-highlight.t
> --- a/tests/test-highlight.t	Wed Apr 10 20:45:10 2013 +0400
> +++ b/tests/test-highlight.t	Wed Apr 17 17:27:39 2013 +0400
> @@ -137,39 +137,72 @@
>     
>     <div class="overflow">
>     <div class="sourcefirst"> line source</div>
> +  <pre class="sourcenumbers">
> +  <a href="#l1" id="l1">     1 </a>
> +  <a href="#l2" id="l2">     2 </a>
> +  <a href="#l3" id="l3">     3 </a>
> +  <a href="#l4" id="l4">     4 </a>
> +  <a href="#l5" id="l5">     5 </a>
> +  <a href="#l6" id="l6">     6 </a>
> +  <a href="#l7" id="l7">     7 </a>
> +  <a href="#l8" id="l8">     8 </a>
> +  <a href="#l9" id="l9">     9 </a>
> +  <a href="#l10" id="l10">    10 </a>
> +  <a href="#l11" id="l11">    11 </a>
> +  <a href="#l12" id="l12">    12 </a>
> +  <a href="#l13" id="l13">    13 </a>
> +  <a href="#l14" id="l14">    14 </a>
> +  <a href="#l15" id="l15">    15 </a>
> +  <a href="#l16" id="l16">    16 </a>
> +  <a href="#l17" id="l17">    17 </a>
> +  <a href="#l18" id="l18">    18 </a>
> +  <a href="#l19" id="l19">    19 </a>
> +  <a href="#l20" id="l20">    20 </a>
> +  <a href="#l21" id="l21">    21 </a>
> +  <a href="#l22" id="l22">    22 </a>
> +  <a href="#l23" id="l23">    23 </a>
> +  <a href="#l24" id="l24">    24 </a>
> +  <a href="#l25" id="l25">    25 </a>
> +  <a href="#l26" id="l26">    26 </a>
> +  <a href="#l27" id="l27">    27 </a>
> +  <a href="#l28" id="l28">    28 </a>
> +  <a href="#l29" id="l29">    29 </a>
> +  <a href="#l30" id="l30">    30 </a>
> +  <a href="#l31" id="l31">    31 </a>
> +  <a href="#l32" id="l32">    32 </a></pre>
> +  <pre class="source">
> +  <span class="c">#!/usr/bin/env python</span>
>     
> -  <div class="source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></div>
> -  <div class="source"><a href="#l2" id="l2">     2</a> </div>
> -  <div class="source"><a href="#l3" id="l3">     3</a> <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></div>
> -  <div class="source"><a href="#l4" id="l4">     4</a> </div>
> -  <div class="source"><a href="#l5" id="l5">     5</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></div>
> -  <div class="source"><a href="#l6" id="l6">     6</a> <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></div>
> -  <div class="source"><a href="#l7" id="l7">     7</a> <span class="sd">&quot;&quot;&quot;</span></div>
> -  <div class="source"><a href="#l8" id="l8">     8</a> </div>
> -  <div class="source"><a href="#l9" id="l9">     9</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></div>
> -  <div class="source"><a href="#l10" id="l10">    10</a> </div>
> -  <div class="source"><a href="#l11" id="l11">    11</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></div>
> -  <div class="source"><a href="#l12" id="l12">    12</a>     <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></div>
> -  <div class="source"><a href="#l13" id="l13">    13</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></div>
> -  <div class="source"><a href="#l14" id="l14">    14</a>         <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div>
> -  <div class="source"><a href="#l15" id="l15">    15</a>         <span class="c"># It is important to yield *here* in order to stop the</span></div>
> -  <div class="source"><a href="#l16" id="l16">    16</a>         <span class="c"># infinite recursion.</span></div>
> -  <div class="source"><a href="#l17" id="l17">    17</a>         <span class="kn">yield</span> <span class="n">p</span></div>
> -  <div class="source"><a href="#l18" id="l18">    18</a>         <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></div>
> -  <div class="source"><a href="#l19" id="l19">    19</a>         <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></div>
> -  <div class="source"><a href="#l20" id="l20">    20</a>             <span class="kn">yield</span> <span class="n">n</span></div>
> -  <div class="source"><a href="#l21" id="l21">    21</a> </div>
> -  <div class="source"><a href="#l22" id="l22">    22</a>     <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></div>
> -  <div class="source"><a href="#l23" id="l23">    23</a>     <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></div>
> -  <div class="source"><a href="#l24" id="l24">    24</a> </div>
> -  <div class="source"><a href="#l25" id="l25">    25</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></div>
> -  <div class="source"><a href="#l26" id="l26">    26</a>     <span class="kn">import</span> <span class="nn">sys</span></div>
> -  <div class="source"><a href="#l27" id="l27">    27</a>     <span class="kn">try</span><span class="p">:</span></div>
> -  <div class="source"><a href="#l28" id="l28">    28</a>         <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></div>
> -  <div class="source"><a href="#l29" id="l29">    29</a>     <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></div>
> -  <div class="source"><a href="#l30" id="l30">    30</a>         <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></div>
> -  <div class="source"><a href="#l31" id="l31">    31</a>     <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></div>
> -  <div class="source"><a href="#l32" id="l32">    32</a>     <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></div>
> +  <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span>
> +
> +  <span class="sd">primes = 2 : sieve [3, 5..]</span>
> +  <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span>
> +  <span class="sd">&quot;&quot;&quot;</span>
> +
> +  <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span>
> +
> +  <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span>
> +  <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span>
> +  <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span>
> +  <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
> +  <span class="c"># It is important to yield *here* in order to stop the</span>
> +  <span class="c"># infinite recursion.</span>
> +  <span class="kn">yield</span> <span class="n">p</span>
> +  <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span>
> +  <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span>
> +  <span class="kn">yield</span> <span class="n">n</span>
> +
> +  <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span>
> +  <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span>
> +
> +  <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
> +  <span class="kn">import</span> <span class="nn">sys</span>
> +  <span class="kn">try</span><span class="p">:</span>
> +  <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
> +  <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span>
> +  <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span>
> +  <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span>
> +  <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></pre>
>     <div class="sourcelast"></div>
>     </div>
>     </div>
> @@ -586,24 +619,27 @@
>     >
>     >     echo % hgweb filerevision, html
>     >     "$TESTDIR/get-with-headers.py" localhost:$HGPORT "file/tip/$2" \
> -  >         | grep '<div class="source">'
> +  >         | grep -A 1 '<pre class="source">'
>     >     echo % errors encountered
>     >     cat errors.log
>     > }
>     $ hgserveget euc-jp eucjp.txt
>     % HGENCODING=euc-jp hg serve
>     % hgweb filerevision, html
> -  <div class="source"><a href="#l1" id="l1">     1</a> \xb5\xfe</div> (esc)
> +  <pre class="source">
> +  \xb5\xfe</pre> (esc)
>     % errors encountered
>     $ hgserveget utf-8 eucjp.txt
>     % HGENCODING=utf-8 hg serve
>     % hgweb filerevision, html
> -  <div class="source"><a href="#l1" id="l1">     1</a> \xef\xbf\xbd\xef\xbf\xbd</div> (esc)
> +  <pre class="source">
> +  \xef\xbf\xbd\xef\xbf\xbd</pre> (esc)
>     % errors encountered
>     $ hgserveget us-ascii eucjp.txt
>     % HGENCODING=us-ascii hg serve
>     % hgweb filerevision, html
> -  <div class="source"><a href="#l1" id="l1">     1</a> ??</div>
> +  <pre class="source">
> +  ??</pre>
>     % errors encountered
>   
>     $ cd ..
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
Alexander Plavin - April 17, 2013, 2:48 p.m.
You can look for an example at
http://aplavin.ru:8000/file/1933896b16c8/README (and other files there, of
course - it's a running 'hg serve'). The problem was that you could not
select the file code correctly, only with line numbers. The patch keeps
line numbers, but they are not selected: the column with them is separated
from the column with the code itself.
Will add it to commit description.


2013/4/17 Mads Kiilerich <mads@kiilerich.com>

> On 04/17/2013 04:07 PM, Alexander Plavin wrote:
>
>> # HG changeset patch
>> # User Alexander Plavin <me@aplavin.ru>
>> # Date 1366205259 -14400
>> #      Wed Apr 17 17:27:39 2013 +0400
>> # Node ID 1933896b16c821ba1e54e397f15e3f**521aaf8909
>> # Parent  4d32c86be3fad13cbe42ce3f51b0fd**acf295f30f
>> hgweb: code selection in file view without line numbers
>>
>> Only single file views changed, and only default templates set ('paper')
>>
>
> Some questions that it might make sense to answer in the commit
> description:
>
> What was the problem - both the user experience and the technical
> explanation?
>
> Will the patch remove the line numbers completely or what trick will it
> use to make sure they don't get selected?
>
> Will this for instance change how huge text files will be transmitted and
> rendered on the fly? Is using a method that is similar to what similar
> tools and sites use?
>
> /Mads
>
>
>
>> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/**
>> filerevision.tmpl
>> --- a/mercurial/templates/paper/**filerevision.tmpl       Wed Apr 10
>> 20:45:10 2013 +0400
>> +++ b/mercurial/templates/paper/**filerevision.tmpl       Wed Apr 17
>> 17:27:39 2013 +0400
>> @@ -68,7 +68,8 @@
>>     <div class="overflow">
>>   <div class="sourcefirst"> line source</div>
>> -{text%fileline}
>> +<pre class="sourcenumbers">{text%**filelinenum}</pre>
>> +<pre class="source">{text%fileline}**</pre>
>>   <div class="sourcelast"></div>
>>   </div>
>>   </div>
>> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/map
>> --- a/mercurial/templates/paper/**map     Wed Apr 10 20:45:10 2013 +0400
>> +++ b/mercurial/templates/paper/**map     Wed Apr 17 17:27:39 2013 +0400
>> @@ -72,7 +72,9 @@
>>   filecomparison = filecomparison.tmpl
>>   filelog = filelog.tmpl
>>   fileline = '
>> -  <div class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a>
>> {line|escape}</div>'
>> +  {line|escape|strip}'
>> +filelinenum = '
>> +  <a href="#{lineid}" id="{lineid}">{linenumber} </a>'
>>   filelogentry = filelogentry.tmpl
>>     annotateline = '
>> diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/static/**
>> style-paper.css
>> --- a/mercurial/templates/static/**style-paper.css        Wed Apr 10
>> 20:45:10 2013 +0400
>> +++ b/mercurial/templates/static/**style-paper.css        Wed Apr 17
>> 17:27:39 2013 +0400
>> @@ -198,7 +198,7 @@
>>   .bigtable td.annotate { font-size: smaller; }
>>   .bigtable td.source { font-size: inherit; }
>>   -.source, .sourcefirst, .sourcelast {
>> +.source, .sourcefirst, .sourcelast, .sourcenumbers {
>>     font-family: monospace;
>>     white-space: pre;
>>     padding: 1px 4px;
>> @@ -206,7 +206,8 @@
>>   }
>>   .sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
>>   .sourcelast { border-top: 1px solid #999; }
>> -.source a { color: #999; font-size: smaller; font-family: monospace;}
>> +.sourcenumbers { float: left; }
>> +.sourcenumbers a { color: #999; font-size: smaller; font-family:
>> monospace; }
>>   .bottomline { border-bottom: 1px solid #999; }
>>     .fileline { font-family: monospace; }
>> diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-hgweb-commands.t
>> --- a/tests/test-hgweb-commands.t       Wed Apr 10 20:45:10 2013 +0400
>> +++ b/tests/test-hgweb-commands.t       Wed Apr 17 17:27:39 2013 +0400
>> @@ -668,9 +668,10 @@
>>         <div class="overflow">
>>     <div class="sourcefirst"> line source</div>
>> -
>> -  <div class="source"><a href="#l1" id="l1">     1</a> foo
>> -  </div>
>> +  <pre class="sourcenumbers">
>> +  <a href="#l1" id="l1">     1 </a></pre>
>> +  <pre class="source">
>> +  foo</pre>
>>     <div class="sourcelast"></div>
>>     </div>
>>     </div>
>> diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-highlight.t
>> --- a/tests/test-highlight.t    Wed Apr 10 20:45:10 2013 +0400
>> +++ b/tests/test-highlight.t    Wed Apr 17 17:27:39 2013 +0400
>> @@ -137,39 +137,72 @@
>>         <div class="overflow">
>>     <div class="sourcefirst"> line source</div>
>> +  <pre class="sourcenumbers">
>> +  <a href="#l1" id="l1">     1 </a>
>> +  <a href="#l2" id="l2">     2 </a>
>> +  <a href="#l3" id="l3">     3 </a>
>> +  <a href="#l4" id="l4">     4 </a>
>> +  <a href="#l5" id="l5">     5 </a>
>> +  <a href="#l6" id="l6">     6 </a>
>> +  <a href="#l7" id="l7">     7 </a>
>> +  <a href="#l8" id="l8">     8 </a>
>> +  <a href="#l9" id="l9">     9 </a>
>> +  <a href="#l10" id="l10">    10 </a>
>> +  <a href="#l11" id="l11">    11 </a>
>> +  <a href="#l12" id="l12">    12 </a>
>> +  <a href="#l13" id="l13">    13 </a>
>> +  <a href="#l14" id="l14">    14 </a>
>> +  <a href="#l15" id="l15">    15 </a>
>> +  <a href="#l16" id="l16">    16 </a>
>> +  <a href="#l17" id="l17">    17 </a>
>> +  <a href="#l18" id="l18">    18 </a>
>> +  <a href="#l19" id="l19">    19 </a>
>> +  <a href="#l20" id="l20">    20 </a>
>> +  <a href="#l21" id="l21">    21 </a>
>> +  <a href="#l22" id="l22">    22 </a>
>> +  <a href="#l23" id="l23">    23 </a>
>> +  <a href="#l24" id="l24">    24 </a>
>> +  <a href="#l25" id="l25">    25 </a>
>> +  <a href="#l26" id="l26">    26 </a>
>> +  <a href="#l27" id="l27">    27 </a>
>> +  <a href="#l28" id="l28">    28 </a>
>> +  <a href="#l29" id="l29">    29 </a>
>> +  <a href="#l30" id="l30">    30 </a>
>> +  <a href="#l31" id="l31">    31 </a>
>> +  <a href="#l32" id="l32">    32 </a></pre>
>> +  <pre class="source">
>> +  <span class="c">#!/usr/bin/env python</span>
>>     -  <div class="source"><a href="#l1" id="l1">     1</a> <span
>> class="c">#!/usr/bin/env python</span></div>
>> -  <div class="source"><a href="#l2" id="l2">     2</a> </div>
>> -  <div class="source"><a href="#l3" id="l3">     3</a> <span
>> class="sd">&quot;&quot;&quot;**Fun with generators. Corresponding
>> Haskell implementation:</span></div>
>> -  <div class="source"><a href="#l4" id="l4">     4</a> </div>
>> -  <div class="source"><a href="#l5" id="l5">     5</a> <span
>> class="sd">primes = 2 : sieve [3, 5..]</span></div>
>> -  <div class="source"><a href="#l6" id="l6">     6</a> <span class="sd">
>>    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /=
>> 0]</span></div>
>> -  <div class="source"><a href="#l7" id="l7">     7</a> <span
>> class="sd">&quot;&quot;&quot;<**/span></div>
>> -  <div class="source"><a href="#l8" id="l8">     8</a> </div>
>> -  <div class="source"><a href="#l9" id="l9">     9</a> <span
>> class="kn">from</span> <span class="nn">itertools</span> <span
>> class="kn">import</span> <span class="n">dropwhile</span><**span
>> class="p">,</span> <span class="n">ifilter</span><span class="p">,</span>
>> <span class="n">islice</span><span class="p">,</span> <span
>> class="n">count</span><span class="p">,</span> <span
>> class="n">chain</span></div>
>> -  <div class="source"><a href="#l10" id="l10">    10</a> </div>
>> -  <div class="source"><a href="#l11" id="l11">    11</a> <span
>> class="kn">def</span> <span class="nf">primes</span><span
>> class="p">():</span></div>
>> -  <div class="source"><a href="#l12" id="l12">    12</a>     <span
>> class="sd">&quot;&quot;&quot;**Generate all primes.&quot;&quot;&quot;</**
>> span></div>
>> -  <div class="source"><a href="#l13" id="l13">    13</a>     <span
>> class="kn">def</span> <span class="nf">sieve</span><span
>> class="p">(</span><span class="n">ns</span><span class="p">):</span></div>
>> -  <div class="source"><a href="#l14" id="l14">    14</a>         <span
>> class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span
>> class="o">.</span><span class="n">next</span><span class="p">()</span></div>
>> -  <div class="source"><a href="#l15" id="l15">    15</a>         <span
>> class="c"># It is important to yield *here* in order to stop
>> the</span></div>
>> -  <div class="source"><a href="#l16" id="l16">    16</a>         <span
>> class="c"># infinite recursion.</span></div>
>> -  <div class="source"><a href="#l17" id="l17">    17</a>         <span
>> class="kn">yield</span> <span class="n">p</span></div>
>> -  <div class="source"><a href="#l18" id="l18">    18</a>         <span
>> class="n">ns</span> <span class="o">=</span> <span
>> class="n">ifilter</span><span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">n</span><span class="p">:</span>
>> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span>
>> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span>
>> <span class="n">ns</span><span class="p">)</span></div>
>> -  <div class="source"><a href="#l19" id="l19">    19</a>         <span
>> class="kn">for</span> <span class="n">n</span> <span class="ow">in</span>
>> <span class="n">sieve</span><span class="p">(</span><span
>> class="n">ns</span><span class="p">):</span></div>
>> -  <div class="source"><a href="#l20" id="l20">    20</a>
>> <span class="kn">yield</span> <span class="n">n</span></div>
>> -  <div class="source"><a href="#l21" id="l21">    21</a> </div>
>> -  <div class="source"><a href="#l22" id="l22">    22</a>     <span
>> class="n">odds</span> <span class="o">=</span> <span
>> class="n">ifilter</span><span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">i</span><span class="p">:</span>
>> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span>
>> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span>
>> <span class="n">count</span><span class="p">())</span></div>
>> -  <div class="source"><a href="#l23" id="l23">    23</a>     <span
>> class="kn">return</span> <span class="n">chain</span><span
>> class="p">([</span><span class="mi">2</span><span class="p">],</span> <span
>> class="n">sieve</span><span class="p">(</span><span
>> class="n">dropwhile</span><**span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">n</span><span class="p">:</span>
>> <span class="n">n</span> <span class="o">&lt;</span> <span
>> class="mi">3</span><span class="p">,</span> <span
>> class="n">odds</span><span class="p">)))</span></div>
>> -  <div class="source"><a href="#l24" id="l24">    24</a> </div>
>> -  <div class="source"><a href="#l25" id="l25">    25</a> <span
>> class="kn">if</span> <span class="n">__name__</span> <span
>> class="o">==</span> <span class="s">&quot;__main__&quot;**</span><span
>> class="p">:</span></div>
>> -  <div class="source"><a href="#l26" id="l26">    26</a>     <span
>> class="kn">import</span> <span class="nn">sys</span></div>
>> -  <div class="source"><a href="#l27" id="l27">    27</a>     <span
>> class="kn">try</span><span class="p">:</span></div>
>> -  <div class="source"><a href="#l28" id="l28">    28</a>         <span
>> class="n">n</span> <span class="o">=</span> <span
>> class="nb">int</span><span class="p">(</span><span
>> class="n">sys</span><span class="o">.</span><span
>> class="n">argv</span><span class="p">[</span><span class="mi">1</span><span
>> class="p">])</span></div>
>> -  <div class="source"><a href="#l29" id="l29">    29</a>     <span
>> class="kn">except</span> <span class="p">(</span><span
>> class="ne">ValueError</span><**span class="p">,</span> <span
>> class="ne">IndexError</span><**span class="p">):</span></div>
>> -  <div class="source"><a href="#l30" id="l30">    30</a>         <span
>> class="n">n</span> <span class="o">=</span> <span class="mi">10</span></div>
>> -  <div class="source"><a href="#l31" id="l31">    31</a>     <span
>> class="n">p</span> <span class="o">=</span> <span
>> class="n">primes</span><span class="p">()</span></div>
>> -  <div class="source"><a href="#l32" id="l32">    32</a>     <span
>> class="kn">print</span> <span class="s">&quot;The first </span><span
>> class="si">%d</span><span class="s"> primes: </span><span
>> class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
>> <span class="p">(</span><span class="n">n</span><span class="p">,</span>
>> <span class="nb">list</span><span class="p">(</span><span
>> class="n">islice</span><span class="p">(</span><span
>> class="n">p</span><span class="p">,</span> <span class="n">n</span><span
>> class="p">)))</span></div>
>> +  <span class="sd">&quot;&quot;&quot;**Fun with generators.
>> Corresponding Haskell implementation:</span>
>> +
>> +  <span class="sd">primes = 2 : sieve [3, 5..]</span>
>> +  <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns,
>> mod n p /= 0]</span>
>> +  <span class="sd">&quot;&quot;&quot;<**/span>
>> +
>> +  <span class="kn">from</span> <span class="nn">itertools</span> <span
>> class="kn">import</span> <span class="n">dropwhile</span><**span
>> class="p">,</span> <span class="n">ifilter</span><span class="p">,</span>
>> <span class="n">islice</span><span class="p">,</span> <span
>> class="n">count</span><span class="p">,</span> <span class="n">chain</span>
>> +
>> +  <span class="kn">def</span> <span class="nf">primes</span><span
>> class="p">():</span>
>> +  <span class="sd">&quot;&quot;&quot;**Generate all
>> primes.&quot;&quot;&quot;</**span>
>> +  <span class="kn">def</span> <span class="nf">sieve</span><span
>> class="p">(</span><span class="n">ns</span><span class="p">):</span>
>> +  <span class="n">p</span> <span class="o">=</span> <span
>> class="n">ns</span><span class="o">.</span><span class="n">next</span><span
>> class="p">()</span>
>> +  <span class="c"># It is important to yield *here* in order to stop
>> the</span>
>> +  <span class="c"># infinite recursion.</span>
>> +  <span class="kn">yield</span> <span class="n">p</span>
>> +  <span class="n">ns</span> <span class="o">=</span> <span
>> class="n">ifilter</span><span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">n</span><span class="p">:</span>
>> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span>
>> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span>
>> <span class="n">ns</span><span class="p">)</span>
>> +  <span class="kn">for</span> <span class="n">n</span> <span
>> class="ow">in</span> <span class="n">sieve</span><span
>> class="p">(</span><span class="n">ns</span><span class="p">):</span>
>> +  <span class="kn">yield</span> <span class="n">n</span>
>> +
>> +  <span class="n">odds</span> <span class="o">=</span> <span
>> class="n">ifilter</span><span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">i</span><span class="p">:</span>
>> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span>
>> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span>
>> <span class="n">count</span><span class="p">())</span>
>> +  <span class="kn">return</span> <span class="n">chain</span><span
>> class="p">([</span><span class="mi">2</span><span class="p">],</span> <span
>> class="n">sieve</span><span class="p">(</span><span
>> class="n">dropwhile</span><**span class="p">(</span><span
>> class="kn">lambda</span> <span class="n">n</span><span class="p">:</span>
>> <span class="n">n</span> <span class="o">&lt;</span> <span
>> class="mi">3</span><span class="p">,</span> <span
>> class="n">odds</span><span class="p">)))</span>
>> +
>> +  <span class="kn">if</span> <span class="n">__name__</span> <span
>> class="o">==</span> <span class="s">&quot;__main__&quot;**</span><span
>> class="p">:</span>
>> +  <span class="kn">import</span> <span class="nn">sys</span>
>> +  <span class="kn">try</span><span class="p">:</span>
>> +  <span class="n">n</span> <span class="o">=</span> <span
>> class="nb">int</span><span class="p">(</span><span
>> class="n">sys</span><span class="o">.</span><span
>> class="n">argv</span><span class="p">[</span><span class="mi">1</span><span
>> class="p">])</span>
>> +  <span class="kn">except</span> <span class="p">(</span><span
>> class="ne">ValueError</span><**span class="p">,</span> <span
>> class="ne">IndexError</span><**span class="p">):</span>
>> +  <span class="n">n</span> <span class="o">=</span> <span
>> class="mi">10</span>
>> +  <span class="n">p</span> <span class="o">=</span> <span
>> class="n">primes</span><span class="p">()</span>
>> +  <span class="kn">print</span> <span class="s">&quot;The first
>> </span><span class="si">%d</span><span class="s"> primes: </span><span
>> class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
>> <span class="p">(</span><span class="n">n</span><span class="p">,</span>
>> <span class="nb">list</span><span class="p">(</span><span
>> class="n">islice</span><span class="p">(</span><span
>> class="n">p</span><span class="p">,</span> <span class="n">n</span><span
>> class="p">)))</span></pre>
>>     <div class="sourcelast"></div>
>>     </div>
>>     </div>
>> @@ -586,24 +619,27 @@
>>     >
>>     >     echo % hgweb filerevision, html
>>     >     "$TESTDIR/get-with-headers.py" localhost:$HGPORT "file/tip/$2" \
>> -  >         | grep '<div class="source">'
>> +  >         | grep -A 1 '<pre class="source">'
>>     >     echo % errors encountered
>>     >     cat errors.log
>>     > }
>>     $ hgserveget euc-jp eucjp.txt
>>     % HGENCODING=euc-jp hg serve
>>     % hgweb filerevision, html
>> -  <div class="source"><a href="#l1" id="l1">     1</a> \xb5\xfe</div>
>> (esc)
>> +  <pre class="source">
>> +  \xb5\xfe</pre> (esc)
>>     % errors encountered
>>     $ hgserveget utf-8 eucjp.txt
>>     % HGENCODING=utf-8 hg serve
>>     % hgweb filerevision, html
>> -  <div class="source"><a href="#l1" id="l1">     1</a>
>> \xef\xbf\xbd\xef\xbf\xbd</div> (esc)
>> +  <pre class="source">
>> +  \xef\xbf\xbd\xef\xbf\xbd</pre> (esc)
>>     % errors encountered
>>     $ hgserveget us-ascii eucjp.txt
>>     % HGENCODING=us-ascii hg serve
>>     % hgweb filerevision, html
>> -  <div class="source"><a href="#l1" id="l1">     1</a> ??</div>
>> +  <pre class="source">
>> +  ??</pre>
>>     % errors encountered
>>       $ cd ..
>> ______________________________**_________________
>> Mercurial-devel mailing list
>> Mercurial-devel@selenic.com
>> http://selenic.com/mailman/**listinfo/mercurial-devel<http://selenic.com/mailman/listinfo/mercurial-devel>
>>
>
>

Patch

diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/filerevision.tmpl
--- a/mercurial/templates/paper/filerevision.tmpl	Wed Apr 10 20:45:10 2013 +0400
+++ b/mercurial/templates/paper/filerevision.tmpl	Wed Apr 17 17:27:39 2013 +0400
@@ -68,7 +68,8 @@ 
 
 <div class="overflow">
 <div class="sourcefirst"> line source</div>
-{text%fileline}
+<pre class="sourcenumbers">{text%filelinenum}</pre>
+<pre class="source">{text%fileline}</pre>
 <div class="sourcelast"></div>
 </div>
 </div>
diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/paper/map
--- a/mercurial/templates/paper/map	Wed Apr 10 20:45:10 2013 +0400
+++ b/mercurial/templates/paper/map	Wed Apr 17 17:27:39 2013 +0400
@@ -72,7 +72,9 @@ 
 filecomparison = filecomparison.tmpl
 filelog = filelog.tmpl
 fileline = '
-  <div class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
+  {line|escape|strip}'
+filelinenum = '
+  <a href="#{lineid}" id="{lineid}">{linenumber} </a>'
 filelogentry = filelogentry.tmpl
 
 annotateline = '
diff -r 4d32c86be3fa -r 1933896b16c8 mercurial/templates/static/style-paper.css
--- a/mercurial/templates/static/style-paper.css	Wed Apr 10 20:45:10 2013 +0400
+++ b/mercurial/templates/static/style-paper.css	Wed Apr 17 17:27:39 2013 +0400
@@ -198,7 +198,7 @@ 
 .bigtable td.annotate { font-size: smaller; }
 .bigtable td.source { font-size: inherit; }
 
-.source, .sourcefirst, .sourcelast {
+.source, .sourcefirst, .sourcelast, .sourcenumbers {
   font-family: monospace;
   white-space: pre;
   padding: 1px 4px;
@@ -206,7 +206,8 @@ 
 }
 .sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
 .sourcelast { border-top: 1px solid #999; }
-.source a { color: #999; font-size: smaller; font-family: monospace;}
+.sourcenumbers { float: left; }
+.sourcenumbers a { color: #999; font-size: smaller; font-family: monospace; }
 .bottomline { border-bottom: 1px solid #999; }
 
 .fileline { font-family: monospace; }
diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t	Wed Apr 10 20:45:10 2013 +0400
+++ b/tests/test-hgweb-commands.t	Wed Apr 17 17:27:39 2013 +0400
@@ -668,9 +668,10 @@ 
   
   <div class="overflow">
   <div class="sourcefirst"> line source</div>
-  
-  <div class="source"><a href="#l1" id="l1">     1</a> foo
-  </div>
+  <pre class="sourcenumbers">
+  <a href="#l1" id="l1">     1 </a></pre>
+  <pre class="source">
+  foo</pre>
   <div class="sourcelast"></div>
   </div>
   </div>
diff -r 4d32c86be3fa -r 1933896b16c8 tests/test-highlight.t
--- a/tests/test-highlight.t	Wed Apr 10 20:45:10 2013 +0400
+++ b/tests/test-highlight.t	Wed Apr 17 17:27:39 2013 +0400
@@ -137,39 +137,72 @@ 
   
   <div class="overflow">
   <div class="sourcefirst"> line source</div>
+  <pre class="sourcenumbers">
+  <a href="#l1" id="l1">     1 </a>
+  <a href="#l2" id="l2">     2 </a>
+  <a href="#l3" id="l3">     3 </a>
+  <a href="#l4" id="l4">     4 </a>
+  <a href="#l5" id="l5">     5 </a>
+  <a href="#l6" id="l6">     6 </a>
+  <a href="#l7" id="l7">     7 </a>
+  <a href="#l8" id="l8">     8 </a>
+  <a href="#l9" id="l9">     9 </a>
+  <a href="#l10" id="l10">    10 </a>
+  <a href="#l11" id="l11">    11 </a>
+  <a href="#l12" id="l12">    12 </a>
+  <a href="#l13" id="l13">    13 </a>
+  <a href="#l14" id="l14">    14 </a>
+  <a href="#l15" id="l15">    15 </a>
+  <a href="#l16" id="l16">    16 </a>
+  <a href="#l17" id="l17">    17 </a>
+  <a href="#l18" id="l18">    18 </a>
+  <a href="#l19" id="l19">    19 </a>
+  <a href="#l20" id="l20">    20 </a>
+  <a href="#l21" id="l21">    21 </a>
+  <a href="#l22" id="l22">    22 </a>
+  <a href="#l23" id="l23">    23 </a>
+  <a href="#l24" id="l24">    24 </a>
+  <a href="#l25" id="l25">    25 </a>
+  <a href="#l26" id="l26">    26 </a>
+  <a href="#l27" id="l27">    27 </a>
+  <a href="#l28" id="l28">    28 </a>
+  <a href="#l29" id="l29">    29 </a>
+  <a href="#l30" id="l30">    30 </a>
+  <a href="#l31" id="l31">    31 </a>
+  <a href="#l32" id="l32">    32 </a></pre>
+  <pre class="source">
+  <span class="c">#!/usr/bin/env python</span>
   
-  <div class="source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></div>
-  <div class="source"><a href="#l2" id="l2">     2</a> </div>
-  <div class="source"><a href="#l3" id="l3">     3</a> <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></div>
-  <div class="source"><a href="#l4" id="l4">     4</a> </div>
-  <div class="source"><a href="#l5" id="l5">     5</a> <span class="sd">primes = 2 : sieve [3, 5..]</span></div>
-  <div class="source"><a href="#l6" id="l6">     6</a> <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span></div>
-  <div class="source"><a href="#l7" id="l7">     7</a> <span class="sd">&quot;&quot;&quot;</span></div>
-  <div class="source"><a href="#l8" id="l8">     8</a> </div>
-  <div class="source"><a href="#l9" id="l9">     9</a> <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span></div>
-  <div class="source"><a href="#l10" id="l10">    10</a> </div>
-  <div class="source"><a href="#l11" id="l11">    11</a> <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span></div>
-  <div class="source"><a href="#l12" id="l12">    12</a>     <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span></div>
-  <div class="source"><a href="#l13" id="l13">    13</a>     <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></div>
-  <div class="source"><a href="#l14" id="l14">    14</a>         <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div>
-  <div class="source"><a href="#l15" id="l15">    15</a>         <span class="c"># It is important to yield *here* in order to stop the</span></div>
-  <div class="source"><a href="#l16" id="l16">    16</a>         <span class="c"># infinite recursion.</span></div>
-  <div class="source"><a href="#l17" id="l17">    17</a>         <span class="kn">yield</span> <span class="n">p</span></div>
-  <div class="source"><a href="#l18" id="l18">    18</a>         <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span></div>
-  <div class="source"><a href="#l19" id="l19">    19</a>         <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span></div>
-  <div class="source"><a href="#l20" id="l20">    20</a>             <span class="kn">yield</span> <span class="n">n</span></div>
-  <div class="source"><a href="#l21" id="l21">    21</a> </div>
-  <div class="source"><a href="#l22" id="l22">    22</a>     <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span></div>
-  <div class="source"><a href="#l23" id="l23">    23</a>     <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span></div>
-  <div class="source"><a href="#l24" id="l24">    24</a> </div>
-  <div class="source"><a href="#l25" id="l25">    25</a> <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span></div>
-  <div class="source"><a href="#l26" id="l26">    26</a>     <span class="kn">import</span> <span class="nn">sys</span></div>
-  <div class="source"><a href="#l27" id="l27">    27</a>     <span class="kn">try</span><span class="p">:</span></div>
-  <div class="source"><a href="#l28" id="l28">    28</a>         <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></div>
-  <div class="source"><a href="#l29" id="l29">    29</a>     <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span></div>
-  <div class="source"><a href="#l30" id="l30">    30</a>         <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></div>
-  <div class="source"><a href="#l31" id="l31">    31</a>     <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></div>
-  <div class="source"><a href="#l32" id="l32">    32</a>     <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></div>
+  <span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span>
+  
+  <span class="sd">primes = 2 : sieve [3, 5..]</span>
+  <span class="sd">    where sieve (p:ns) = p : sieve [n | n &lt;- ns, mod n p /= 0]</span>
+  <span class="sd">&quot;&quot;&quot;</span>
+  
+  <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">dropwhile</span><span class="p">,</span> <span class="n">ifilter</span><span class="p">,</span> <span class="n">islice</span><span class="p">,</span> <span class="n">count</span><span class="p">,</span> <span class="n">chain</span>
+  
+  <span class="kn">def</span> <span class="nf">primes</span><span class="p">():</span>
+  <span class="sd">&quot;&quot;&quot;Generate all primes.&quot;&quot;&quot;</span>
+  <span class="kn">def</span> <span class="nf">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span>
+  <span class="n">p</span> <span class="o">=</span> <span class="n">ns</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
+  <span class="c"># It is important to yield *here* in order to stop the</span>
+  <span class="c"># infinite recursion.</span>
+  <span class="kn">yield</span> <span class="n">p</span>
+  <span class="n">ns</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">%</span> <span class="n">p</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">ns</span><span class="p">)</span>
+  <span class="kn">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">sieve</span><span class="p">(</span><span class="n">ns</span><span class="p">):</span>
+  <span class="kn">yield</span> <span class="n">n</span>
+  
+  <span class="n">odds</span> <span class="o">=</span> <span class="n">ifilter</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">i</span><span class="p">:</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="n">count</span><span class="p">())</span>
+  <span class="kn">return</span> <span class="n">chain</span><span class="p">([</span><span class="mi">2</span><span class="p">],</span> <span class="n">sieve</span><span class="p">(</span><span class="n">dropwhile</span><span class="p">(</span><span class="kn">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">3</span><span class="p">,</span> <span class="n">odds</span><span class="p">)))</span>
+  
+  <span class="kn">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&quot;__main__&quot;</span><span class="p">:</span>
+  <span class="kn">import</span> <span class="nn">sys</span>
+  <span class="kn">try</span><span class="p">:</span>
+  <span class="n">n</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
+  <span class="kn">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span>
+  <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span>
+  <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span>
+  <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></pre>
   <div class="sourcelast"></div>
   </div>
   </div>
@@ -586,24 +619,27 @@ 
   > 
   >     echo % hgweb filerevision, html
   >     "$TESTDIR/get-with-headers.py" localhost:$HGPORT "file/tip/$2" \
-  >         | grep '<div class="source">'
+  >         | grep -A 1 '<pre class="source">'
   >     echo % errors encountered
   >     cat errors.log
   > }
   $ hgserveget euc-jp eucjp.txt
   % HGENCODING=euc-jp hg serve
   % hgweb filerevision, html
-  <div class="source"><a href="#l1" id="l1">     1</a> \xb5\xfe</div> (esc)
+  <pre class="source">
+  \xb5\xfe</pre> (esc)
   % errors encountered
   $ hgserveget utf-8 eucjp.txt
   % HGENCODING=utf-8 hg serve
   % hgweb filerevision, html
-  <div class="source"><a href="#l1" id="l1">     1</a> \xef\xbf\xbd\xef\xbf\xbd</div> (esc)
+  <pre class="source">
+  \xef\xbf\xbd\xef\xbf\xbd</pre> (esc)
   % errors encountered
   $ hgserveget us-ascii eucjp.txt
   % HGENCODING=us-ascii hg serve
   % hgweb filerevision, html
-  <div class="source"><a href="#l1" id="l1">     1</a> ??</div>
+  <pre class="source">
+  ??</pre>
   % errors encountered
 
   $ cd ..