Fossil Forum

line numbers, and copying
Login

line numbers, and copying

line numbers, and copying

(1) By Alfred M. Szmidt (ams) on 2020-08-13 18:52:52 [source]

What is the easy way of showing a file with line numbers and getting a URL to that line, ore region?

It would be really really nice if one could just click on something in the UI somehow, or mark the region and get back a link.

(2) By Stephan Beal (stephan) on 2020-08-13 19:05:36 in reply to 1 [link] [source]

What is the easy way of showing a file with line numbers and getting a URL to that line, ore region?

"Easy" is probably a stretch, but...

  • Visit the file via the /dir page, or equivalent...
  • Tap the "line numbers" checkbox (which reloads the page)...
  • Scroll until you find the line(s) you want, and note their number(s)...
  • Replace "ln=on" in the URL bar with "ln=100-110"...
  • Ctrl-A, Ctrl-C to copy that to the clipboard.

It "would be cool" to be able to tap on a line to get a link to it, similar to github, but hyperlinking each line that way would cause the output size to approximately double. Perhaps we can come up with a click handler which can do ranges, similarly to the way selecting 2 nodes in the timeline works, without having to actually tie an event handler to every line of the file. i'll add that to the to-try-out list. By using HTML5 history we could also update the URL bar, so the above could be reduced to:

  • Visit the file via the /dir page, or equivalent...
  • Tap the "line numbers" checkbox (which reloads the page)...
  • Scroll until you find the line(s) you want...
  • Tap on 1 of them to update the URL bar with a reference to that line.
  • Optionally tap again to update the URL bar with a reference to that range.
  • Tap in the URL bar and Ctrl-A, Ctrl-C to copy that to the clipboard.

That doesn't look much shorter, in terms of process, but selecting the numbers with a tap, rather than having to manually edit the URL bar, would be an improvement.

(3) By Stephan Beal (stephan) on 2020-08-13 19:21:54 in reply to 2 [link] [source]

i'll add that to the to-try-out list.

Nevermind: the structure of the line numbering does not make this really feasible to do. The text of the file is dumped out in a PRE with the line numbers embedded at the start of each line. That's the most efficient way to do it, but it makes it next to impossible (maybe genuinely impossible) to figure out which line was clicked on via JS. My incorrect assumption was that each line was a pair of elements: the line number in one and the line content in another. That would allow JS selection but would also bloat the output considerably.

(4) By Warren Young (wyetr) on 2020-08-13 21:00:53 in reply to 3 [link] [source]

The selection markup you get on clicking "Line Numbers" has to target the individual lines somehow.

Maybe instead of two different ways to emit HTML for the preview, take the line-numbered version and make the line number elements hidden in the "Line Numbers" = false case.

Bonus: then you could enable the line numbers without an HTTP round-trip.

(5) By Stephan Beal (stephan) on 2020-08-13 21:36:10 in reply to 4 [link] [source]

The selection markup you get on clicking "Line Numbers" has to target the individual lines somehow.

Right. That's the bit which won't work with the current line numbering approach.

Maybe instead of two different ways to emit HTML for the preview, take the line-numbered version and make the line number elements hidden in the "Line Numbers" = false case.

It would be simple enough to emit the line numbers separately, but starting hidden, but it would be horribly inefficient and slow for large files.

sqlite3.c, easily our biggest with 230k lines, would need some 460,000 DOM elements to render that way, as opposed to a single PRE tag containing a single TEXT element using the current approach. shell.c, with nearly 21k lines, would need almost 42000 DOM elements. That's painful in terms of both rendering speed and memory cost.

By comparison, the current timeline on fossil-scm.org, with the "verbose" view, has only 3k elements:

document.querySelectorAll('*').length
3126

(6) By Warren Young (wyetr) on 2020-08-13 23:25:18 in reply to 5 [link] [source]

Are you sure you want to be making decisions based on a 234-sigma outlier?

Yes, really, 234. Method: Convert wc -l src/*.c output to CSV, drop shell.c and sqlite3.c from data set as amalgams, calculate standard deviation = 984.

(Median is 662, by the way. You might also find the line count histogram interesting.)

The point is, normal files you'd want to do line number markup on do not cause a serious problem if you mark up each line separately.

Simply loading sqlite3.c in a /file URL without the ln parameter set takes several seconds here. That's how abnormal this case is! Clicking Line Numbers on the resulting page timed out several times in testing here, presumably due to some sort of anti-DoS protection in Fossil.

I eventually got it to load, and now I see that the line numbers are hard-coded into the single <pre> element, which as you say, means there is nothing to hang a JS onclick event handler onto.

I'll answer my own question: I don't see why we should design around this wildly uncommon case.

(7) By Warren Young (wyetr) on 2020-08-13 23:40:26 in reply to 6 [link] [source]

Yes, really, 234.

It may be considered dodgy statistics to calculate SD without the outliers but then calculate values on those same outliers based on the resulting SD.

If you include the two amalgamation files, SD is 18344 (!), but the mean shifts only slightly to 671, leaving sqlite3.c 12.5 sigma out from the mean.

On the other hand, if you take this method, it tells you that shell.c is only 1.1 sigma out from the mean, which is clearly ridiculous.

The distribution is in no way Gaussian, so it's no wonder statistics based on such distributions give strange results. A better statistician than I could probably come up with a method that gives a better sense of how out-there these two outliers really are.

(8) By Stephan Beal (stephan) on 2020-08-13 23:50:12 in reply to 6 [link] [source]

Obviously sqlite3.c is a pathological case, but we do have to account for 3rd party repos having arbitrarily large files:

https://fossil.wanderinghorse.net/r/cwal/file?udc=1&ln=on&ci=tip&name=cwal.c

14017 lovingly hand-coded lines = 28k DOM elements.

Another very real consideration is syntax highlighters installed via the skin. If we wrap that output in separate DOM elements, syntax highlighters cannot work, which would make me quite sad:

https://fossil.wanderinghorse.net/r/cwal/file?name=test.c&ci=tip

Highlighters inject tons of DOM elements, as well - certainly more than 2 per line on average. My tablet's Firefox is currently choking on trying to highlight that 2nd file in line number mode. Hmmm... should probably not trigger highlighting when "ln" is in the URL params.

(9) By Warren Young (wyetr) on 2020-08-14 00:28:09 in reply to 8 [link] [source]

Highlighters inject tons of DOM elements, as well

Yes, because there's no other reasonable way to do it.

The same goes for interactive line number selection. It's a necessary cost to get the desired feature. You should be able to just check the Line Numbers box, have the line numbers appear client-side without hitting the server, click the first line, and shift click the last line to get a URL you can share.

I don't expect that feature to have zero cost in browser resources.

We don't have to write this code to get benchmark results. At semi-random, I picked SQLite's src/util.c from the GitHub file viewer, and for this 1694 line file, there are about 5x that number of DOM elements, which render in about 600 ms here on my 8-year-old iMac, from first-paint to "largest contentful paint", according to Chrome. If you measure FP to the document onload event, that's closer to 700 ms.

I find this quite palatable.

(10) By Warren Young (wyetr) on 2020-08-14 00:34:53 in reply to 9 [link] [source]

Another useful comparison is /timeline, which produces about 3k DOM elements for the default 200-entry limit on fossil-scm.org/fossil.

(11) By Stephan Beal (stephan) on 2020-08-14 00:36:57 in reply to 9 [link] [source]

To the best of my knowledge, though i can't verify this from my tablet in bed, github's highlighting happens server-side, so the client has only the rendering cost, not the parse-and-DOMize cost.

1700 lines is also pretty small. Lemon is nearly 6k lines:

https://github.com/sqlite/sqlite/blob/master/tool/lemon.c

(12) By Stephan Beal (stephan) on 2020-08-14 00:43:48 in reply to 11 [link] [source]

In any case, the loss of syntax highlighting for the sake of simplifying linking to lines would be a catastrophe for me. You can't mix server-side linkable line numbers and client-side syntax highlighting. They're fundamentally incompatible because syntax highlighters require access to the raw content as a single string.

We can have one or the other, and syntax highlighting is easily my favorite of the two.

(13) By Stephan Beal (stephan) on 2020-08-14 00:51:56 in reply to 12 [link] [source]

You can't mix server-side linkable line numbers and client-side syntax highlighting.

Maybe if we put the line numbers in one table column (a single cell) and content in a single neighboring cell, we could get them to line up. That's assuming that the highlighter doesn't change the font sizes. If we set a large line-height value, say 1.5em, we might even have some leeway there for small changes in font sizes. Hmmm. Seems worth trying out, anyway.

(14) By Warren Young (wyetr) on 2020-08-14 01:08:56 in reply to 11 [link] [source]

github's highlighting happens server-side

We were only discussing syntax highlighting as a way to talk about large DOMs, but it's kind of a side issue here.

GitHub generates a big <table> for its file viewer, line numbers in the first column, line content in the second. That's the relevant thing to compare against here.

1700 lines is also pretty small.

It's 0.34 sigma out from the median of SQLite's src/*.c, excluding test*.

I checked two other large C++ source bases here, and 1700 LOC is on the high end for both.

I tried looking for global-scale statistics on source code file sizes, but I couldn't find anything with a web search. There must be such things in the CS and project management literature, but I don't have a ready way to find such things here.

I suspect that if someone comes up with such stats, we'll find that lemon.c is another outlier.

(15) By Stephan Beal (stephan) on 2020-08-14 01:16:31 in reply to 12 [link] [source]

i hate it when code won't let me sleep :/.

Here's some proof of concept which takes a (conceptually) server-side generated table in this form:

<table><tbody><tr><td>LINE NUMBERS</td><td>FILE CONTENT</td></tr></tbody></table>

This demo dynamically populates those fields using the source code for the demo script itself. It does not hyperlink the lines, but that would be the next logical step (and that could be done server-side)...

<!doctype html>
<html>
<head></head>
<body>
  <table class='numbered-lines'>
    <tbody>
      <tr>
        <td></td>
        <td><pre><code class='language-js'></code></pre></td>
      </tr>
    </tbody>
  </table>
  <style>
    table.numbered-lines td {
        font-family: monospace;
        line-height: 1.5em;
        white-space: pre;
        margin: 0;
        padding: 0;
    }
    table.numbered-lines td:nth-of-type(1) {
    }
    table.numbered-lines td:nth-of-type(2) > pre,
    table.numbered-lines td:nth-of-type(2) > pre > code {
        margin: 0; padding: 0;
    }
  </style>
  <script id='the-script'>(function(){
    const e = document.querySelector('#the-script'),
          tbl = document.querySelector('table.numbered-lines'),
          tdLn = tbl.querySelector('td'),
          eFile = tbl.querySelector('td:nth-of-type(2) > pre > code')
    ;
    const lineCount = e.innerText.split(/\r?\n/).length,
          lineNumbers = [],
          digits = (''+lineCount).length,
          pad = (n)=>('0000'+n).substr(-digits)
    ;
    var i = 0;
    for( ; i < lineCount; ++i ){
        lineNumbers.push(pad(i));
    }
    tdLn.innerText = lineNumbers.join('\n');
    eFile.innerText = e.innerText;
})()</script>
</body>
</html>

Dump that into an HTML file and open it.

Interesting properties:

  • Would not interfere with syntax highlighting.
  • Code is still mouse-selectable without the line numbers.

Down-side compared to the current line highlighting technique: it cannot, in a way compatible with client-side syntax highlighters, mark the code block like ln=X-Y currently does. Instead it would have to mark the line numbers (without changing their font size, or that would screw up alignment with the neighboring code).

(16) By Warren Young (wyetr) on 2020-08-14 01:20:06 in reply to 14 [link] [source]

[syntax highlighting is] kind of a side issue here.

I just remembered something: the client-side JS syntax highlighter I use requires that you point it at a single <pre> or <code> element; it won't work on a <table>. I suspect this is typical of those available, since most languages you want to be highlit are context-dependent, so that the highlighter must consider multiple lines to give sensible results.

This fits with your wish to skip highlighting in line-numbering mode, since it means we do need two entirely different HTML renderings: one-big-pre, and a table. The HTTP round-trip is therefore unavoidable short of near-total DOM reconstruction on the client side to switch modes.

As for your idea to make it a 2-element table, I think you won't get it to line up without CSS tricks like clipping overflow and disabling wrapping, and then having done that, you still won't have the DOM elements you need for attaching onclick handlers.

I don't see how you avoid 2⨉ LOC DOM elements plus overhead: one for the line number, one for the line content.

(17) By Stephan Beal (stephan) on 2020-08-14 01:20:12 in reply to 14 [link] [source]

GitHub generates a big

for its file viewer, line numbers in the first column, line content in the second.

Well, good. My demo did it the same way, so at least there's a solid precedent for that approach.

It's 0.34 sigma

That's all Greek to me (no pun intended).

IMO the two-column table approach is not overly-expensive and it would not (insofar as i can see, anyway) interfere with client-side syntax highlighters.

i'll experiment with that the next time i have the energy for it, but it's pushing 03:30 here so it's time to slip away for a while.

(18) By Stephan Beal (stephan) on 2020-08-14 01:33:54 in reply to 16 [link] [source]

As for your idea to make it a 2-element table, I think you won't get it to line up without CSS tricks like clipping overflow and disabling wrapping, and then having done that, you still won't have the DOM elements you need for attaching onclick handlers.

i didn't even think about wrapping - that would be a complete breaker. The onclick handlers could happen in the line numbers, which would be wrapped in 0-margin/0-padding SPAN elements. We would then only need a single click handler on the left TD, and check its target element in handler to find the appropriate line element.

Aside from wrapping, which needs to be disabled, i think this can work reasonably well. Experimentation may prove me wrong, but then we'll know for sure. If it does work we have our cake (simpler line linking) and eat it too (syntax highlighter compatibility). That said: as soon as a syntax highlighter messes with font sizes or (especially) line-height, all bets are off as far as line/code alignment.

I don't see how you avoid 2⨉ LOC DOM elements plus overhead: one for the line number, one for the line content.

The table + 1xLOC (line numbers) + (1xPRE + 1xCODE) (file content). To reach that code we would have to sacrifice the ability to mark (purple highlight) the code lines when using ln=X and ln=X-Y, and instead just mark the line number elements. The code lines themselves would have to remain unaddressable for the sake of allowing a highlighter to mutilate them.

(19) By Warren Young (wyetr) on 2020-08-14 02:06:59 in reply to 18 [link] [source]

It's not just wrapping: you also can't count on line height to be constant. (Point 4)

Proof:

plain ASCIIHello, world!
half as single char½
using solidus¹/₂
using fraction slash¹⁄₂
emoji😀
enclosed alphanumerics🅆, ❶
Asian scripts壱, 搋

With my current browser + OS + font combo, I get 3 different row heights. I wouldn't be surprised if someone found a combo that gives a different value on each row.

It may be possible to force this with CSS's line-height property, but I feel you're treading out onto thin ice here, where it works in one browser with one OS's font rendering engine but fails elsewhere.

If you find then that you need to force both sides to make it work, now you lack the addressable DOM elements on the right hand side.

I think it's best if you just modify the current method: deliver a single DOM element for the file content by default, and deliver a row-per-line <table> in numbered line mode, giving up on the option to do client-side syntax highlighting.

(20) By Stephan Beal (stephan) on 2020-08-14 02:21:39 in reply to 12 [link] [source]

The line-dissecting code in info.c is too intricate for my tired mind to dissect at the moment but here's version 2 of the JS proof of concept:

  • Disable wrapping.
  • Total DOM element count of TABLE + 1xLOC + PRE + CODE.
  • Selecting of line numbers and ranges via a single event handler (not one per line number). Watch the URL bar change as the selection does and/or watch the console for console.debug() messages (noting that Chromium apparently defaults to not showing that level of message by default).
<head></head>
<body>
  <table class='numbered-lines'>
    <tbody>
      <tr>
        <td></td>
        <td><pre><code class='language-js'></code></pre></td>
      </tr>
    </tbody>
  </table>
  <style>
    table {
        border: 1px dotted black;
    }
    table.numbered-lines td {
        font-family: monospace;
        line-height: 1.5em;
        white-space: pre;
        margin: 0;
        padding: 0;
        white-space: nowrap;
        vertical-align: top;
    }
    table.numbered-lines td:nth-of-type(1) > span {
        display: block;
        margin: 0;
        padding: 0;
        line-height: inherit;
        font-size: inherit;
        font-family: inherit;
        cursor: pointer;
    }
    table.numbered-lines td:nth-of-type(1) > span:hover {
        background-color: lightgreen;
    }
    table.numbered-lines td:nth-of-type(2) {
        padding-left: 1em;
    }
    table.numbered-lines td:nth-of-type(2) > pre,
    table.numbered-lines td:nth-of-type(2) > pre > code {
        max-width: 20em /* simulate long lines */;
        margin: 0;
        padding: 0;
        white-space: pre;
        overflow-x: auto;
        line-height: inherit;
        font-size: inherit;
        font-family: inherit;
    }
  </style>
  <script id='the-script'>(function(){
    const e = document.querySelector('#the-script'),
          tbl = document.querySelector('table.numbered-lines'),
          tdLn = tbl.querySelector('td'),
          eFile = tbl.querySelector('td:nth-of-type(2) > pre > code')
    ;
    const lineCount = e.innerText.split(/\r?\n/).length,
          digits = (''+lineCount).length,
          pad = (n)=>('0000'+n).substr(-digits)
    ;
    var i = 0, span;
    for( ; i < lineCount; ++i ){
        span = document.createElement('span');
        span.innerText = pad(i);
        tdLn.appendChild(span);
    }
    eFile.innerText = e.innerText;
    tdLn.addEventListener('click', function f(ev){
        console.debug("ev =",ev);
        if(!f.selectedRange){
            f.selectedRange = [0,0];
            f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
        }
        const rng = f.selectedRange;
        if('SPAN'===ev.target.tagName){
            const ln = +ev.target.innerText;
            if(2===f.mode){/*reset selection*/
                f.mode = 0;
                //rng[0] = rng[1] = 0;
            }
            if(0===f.mode){
                rng[1] = 0;
                rng[0] = ln;
                console.debug("Selected line #"+ln);
                history.pushState(undefined,'Line #'+ln, "?ln="+ln);
                f.mode = 1;
            }else if(1===f.mode){
                if(ln === rng[0]){/*unselect line*/
                    console.debug("Unselected line #"+ln);
                    history.pushState(undefined,'No selection', '?ln=on');
                    rng[0] = 0;
                    f.mode = 0;
                }else{
                    rng[1] = ln;
                    console.debug("Selected range: ",rng);
                    history.pushState(undefined,'Range '+rng.join('..'), "?ln="+rng.join('-'));
                    f.mode = 2;
                }
            }                
        }
    }, false);
})()</script>
</body>
</html>

So... most of that just needs to be moved to the server side and it needs to honor the multi-block selection mode ostensibly supported by ln=X-Y/A-B/C-D..., but which isn't working for me:

https://fossil-scm.org/fossil/info/605528a1f70b33df?ln=2022-2023x2029-2033

(21) By Stephan Beal (stephan) on 2020-08-14 02:34:40 in reply to 19 [link] [source]

It may be possible to force this with CSS's line-height property, but I feel you're treading out onto thin ice here, where it works in one browser with one OS's font rendering engine but fails elsewhere.

i've had good experience with the line-height property in that regard in creating custom cards for board games using HTML/CSS. i think it will work just fine. The only way to know for certain is to try it out, though, which is now on my TODO list. That basically just means reimplementing:

https://fossil-scm.org/fossil/info/605528a1f70b33df?ln=2025-2096

And adding a small bit of CSS and JS to go with it.

I think it's best if you just modify the current method: deliver a single DOM element for the file content by default, and deliver a row-per-line

in numbered line mode, giving up on the option to do client-side syntax highlighting.

It also loses the ability to copy more than one line of the code with a mouse, except by also selecting the line numbers :/. The current impl also has that limitation, though, so that wouldn't be a new misfeature.

If the one-row/two-column approach doesn't work we "could" fall back to one row per LOC, but that would be horribly expensive: 3xLOC DOM elements (1xTR + 2xTD per line), or 4xLOC if the lines are individually hyperlinked (not strictly necessary, but a JS-side event handler would either have to be applied to every single line number cell or a bubble-catching event handler on the table would have to take care in order to avoid accidentally reacting to highligher-injected elements). Personally i consider that cost too high client-side, but i admittedly project much of my C-level memory-frugality mentality into the browser environment.

(22) By Warren Young (wyetr) on 2020-08-14 02:52:27 in reply to 21 [link] [source]

i've had good experience with the line-height property

Set to what, in this case, and in what units?

It can't be pixels, since that varies across devices.

"em" is measuring in the wrong direction.

"ex" is in the right direction, but the x-height of fonts varies considerably, so you can't correctly guess at a multiplier like "1.4ex".

Does "100%" do the right thing?

Do we need to use something experimental or not widely supported like "1.0rlh"?

i think it will work just fine.

With a restricted character set, sure. As soon as someone drops some uncommon Unicode into the file, I think you'll have to be very clever or lucky to keep it from breaking.

I've tested the prior table in 4 different browsers on 3 different platforms now that the post is published, and I get a different set of unique row heights on each combo:

  • macOS Chrome: 21, 25, 26
  • macOS Firefox: 20, 21, 24
  • Chrome OS: 22, 26
  • old MS Edge: 21, 22, 24, 25
  • new Edge (Chrome-based): 21, 22, 24

Here's the one-liner I used to produce these values, suitable for pasting into a JS console:

h = {}; for (i = 0; i < 6; ++i) { h[document.querySelector("#test" + i).clientHeight] = true } ; Object.keys(h)

(23) By Stephan Beal (stephan) on 2020-08-14 03:12:09 in reply to 22 [link] [source]

With a restricted character set, sure. As soon as someone drops some uncommon Unicode into the file, I think you'll have to be very clever or lucky to keep it from breaking.

That's certainly true, but also probably as uncommon (in fossil repos) as a code file with 200k+ lines. My thought was to simply set it to a relatively high value (em, ex, whichever), monospace font, and hope for the best (which will probably work for 99.5%+ of source/embedded doc files).

i'm really not keen on the DOM cost of one row per line, but agree that it's the safest in terms of layout predictability. It's also slow in widespread browsers, though:

https://techcommunity.microsoft.com/t5/discussions/rendering-large-tables-is-very-slow/m-p/1460579 (the ticket linked to there coincidentally fits sqlite3's size, but even only a few thousand rows can take 15s to render)

MSIE10 can take literally several minutes to render a few thousand table lines (that was a major problem on my last commercial project), but that browser is probably not a significant concern anymore.

(24) By Alfred M. Szmidt (ams) on 2020-08-14 08:15:22 in reply to 6 [link] [source]

And to be fair, even github refuses to load sqlite3.c ... so having a limit on the size of "line numbers" might make sense, do people really view something like sqlite3.c in the web GUI?


View raw

(Sorry about that, but we can’t show files that are this big right now.)

(25) By Stephan Beal (stephan) on 2020-08-14 10:20:26 in reply to 22 [link] [source]

Now that i've slept some, i can respond to this better:

With a restricted character set, sure. As soon as someone drops some uncommon Unicode into the file, I think you'll have to be very clever or lucky to keep it from breaking.

The good news is, that's not quite the case with a fixed line-height. Once line-height is set, any characters which are too large for it will simply overlap with adjacent lines, rather than shifting the line layout. This can be seen by setting the line-height in the demo HMTML to, say, 1.6ex. Setting it to 2.8ex gives a fairly comfortable spacing. Even using non-fixed-width fonts works fine, in that the line numbers and code lines stay aligned, so long as they both explicitly have (A) the same font-family, (B) the same font-size, and (C) the same line-height. i've not yet been able to break their alignment so long as those prerequisites are met.

Here's a rundown of the github impl:

  • They use the one TR/two TD per row approach but...

  • They don't actually output line numbers. Instead the left TD has a data-line-number=123 attribute and a CSS ::before selector uses the CSS attr() method (which is new to me) to apply that node's line number. This allows the text in the right column to be mouse-selected without selecting the line numbers because content applied via ::before and ::after CSS selectors cannot (for whatever reason) be mouse-selected.

  • There's a whopping 144 bytes of HTML-related overhead applied to every line, plus the markup related to highlighting the code line (a minimum of 2 SPAN elements, at 52 bytes of HTML, for a 2-character line of C code). That, in turn, gets translated to 3 DOM elements plus the highlighting elements, for a minimum of 5 DOM elements per line. Since we don't do server-side syntax highlighting, that cost doesn't really apply to us.

  • i've been unable to find concrete numbers for the C-/C++-side memory cost of DOM nodes, but vaguely guesstimate it, based solely on the sizes of similar structures in my own code, to be a bare minimum of 48 bytes per node. Assuming that is anywhere close to reality, the HTML- and DOM-related overhead works out to about 436kb per 1000 lines of output (196 bytes TR/TD/highlighting + 5 DOM nodes at 48 bytes each). That's not terribly much in terms of RAM, but the raw HTML (not DOM) is also a network transport cost (empty lines have an overhead of about 196 bytes (github) or 144 bytes (fossil), so 144kb overhead per 1000 LOC). Not huge but not inconsiderable.

Alfred has shown that github simply refuses to output "too big," so there's a solid precedent for us doing the same, though we would need to decided whether too big means byte count or line count (which we'd first have to calculate to know whether it's too big).

So... next step: today i'll take a stab at the 1 TR/2 TD (total, not per line) approach using line-height to keep everything lined (as it were) up and throw it through all sorts of fonts and line heights to try to get it mis-aligned. So far (in admittedly pre-coffee-intake tests) alignment has held up perfectly.

For completeness's sake, here my current test CSS (the HTML/JS code is the same as above):

    table {
        border: 1px dotted black;
    }
    table.numbered-lines td {
        font-family: monospace;
        line-height: 2.8ex;
        white-space: pre;
        margin: 0;
        white-space: nowrap;
        vertical-align: top;
        padding: 1em 0 0 0 /*prevents slight overlap at top */;
    }
    table.numbered-lines td:nth-of-type(1) > span {
        display: block;
        margin: 0;
        padding: 0;
        line-height: inherit;
        font-size: inherit;
        font-family: inherit;
        cursor: pointer;
    }
    table.numbered-lines td:nth-of-type(1) > span:hover {
        background-color: lightgreen;
    }
    table.numbered-lines td:nth-of-type(2) {
        padding-left: 1em;
    }
    table.numbered-lines td:nth-of-type(2) > pre {
        margin: 0;
        padding: 0;
        max-width: 20em /* simulate long lines */;
        overflow-x: auto;
        overflow-y: hidden /* apparently not needed, but eases my mind */;
        padding: 0 0 1em 0 /*prevents a 1-2px underlap at bottom from triggering a scrollar */;
    }
    table.numbered-lines td:nth-of-type(2) > pre > code {
        margin: 0;
        padding: 0;
        white-space: pre;
        line-height: inherit;
        font-size: inherit;
        font-family: inherit;
    }

(26.3) By Stephan Beal (stephan) on 2020-08-14 15:21:39 edited from 26.2 in reply to 1 [link] [source]

Well that wasn't so bad. Here's a working version of line selection via click:

https://fossil-scm.org/fossil/timeline?r=line-number-selection

However, we need to decide whether this is merge-worthy, especially given how the selection works...

Advantages of this over the current impl.:

  • We can mouse-select code lines without selecting the line numbers.
  • We can interactively select a line number/range to highlight (without actually highlighting it - that must be done server-side unless we use a separate DOM element for every line of code).
  • It's compatible with client-installed syntax highlighters:

https://fossil.wanderinghorse.net/screenshots/fossil-line-select-highlight.png

(Edit: the ability to add syntax highlighters has been more frequently requested than a simpler way to select code ranges to link to (insofar as i recall, this thread is the first such request). Thus the former should arguably take priority in any conflict.)

Here's how line selection works:

When clicking on a line number, the URL bar in the browser is updated to reflect the selected line or range of lines. That means you can simply copy the URL bar to get the link to the selected range.

However...

It also means that each time you tap a line number, that gets added to the browser's history, such that tapping the back button will leave you on that page but will update the URL bar to reflect the previous selection. Feature or bug? Undoubtedly yes. It's slightly annoying only if you want to use the back button, otherwise it's not even noticeable.

Option #2 might be, instead of updating the history (which updates the URL bar), to copy the URL to the clipboard. The advantage would be that the back button works as expected. The disadvantage, other than needing access to the clipboard (which might not be a given), would be that the URL would be hidden from the user, so they couldn't see/confirm their selected range until they pasted the URL somewhere. Implicitly messing with the clipboard is evil, IMO, as it can overwrite something the user wanted to have in there. (Lotus Notes is forever on my poo-list for that reason.)

Option #3 might be, instead of updating the history multiple times, we instead do:

window.href.location = ...?ln=THE-SELECTION

which would re-request the page with the given range selected. That sounds like severe overkill, tough.

Opinions, suggestions, patches are, of course, welcomed.

Edit: here's a repo to try it out on:

https://fossil.wanderinghorse.net/r/cwal/dir?ci=tip

Just be aware that the file cwal.c is 10k (edit:) 14k lines and the site uses a JS-side syntax highlighter, which is really slow on files that big. (My hoster's also not blazingly fast, but it gets the job done.)

(27) By graham on 2020-08-14 14:20:20 in reply to 26.1 [link] [source]

Possibly too late (I've seen the thread evolve but haven't had a chance to play with anything until now), but have you considered using simple text-selection with the mouse to indicate the area to be selected?

There's a rough proof-of-concept on JS Fiddle... at present, it just shows you the line numbers when you click the Select Range button. (Note: the text shown in the <pre>-block may not be the latest version of the code).

Pros:

  • As I understand the original "everything in a <pre>-block" format, it should work with or without line numbers – shouldn't have any problems of "not lining up", or of local syntax highlighters not working.

  • Doesn't involve lots of DOM elements.

  • Mouse-selecting is (to me) a "natural" way of selecting text of interest.

Cons:

  • Highlighting a large are (where scrolling is needed to get from start to end) could get tricky (although most uses of Fossil's highlighting I've seen tend to be (relatively) small ranges).

  • You cannot (as far as I know) select multiple ranges using the mouse (although the window.getSelection() appears to be able to handle this if there is).

Unknown:

  • The method of counting lines doesn't seem to be affected if the <pre> block is set to wrap, but I don't know if different files' line-endings can affect things.

Possible Enhancements:

  • Instead of clicking on a button after selecting some text, I suspect you could react to an "on selection made" event (although, the number of times I tend to highlight text when I'm musing about this, I don't think you'd want this active all the time).

  • For selecting large blocks of text, you could potentially select a few characters in the first line and click Start Highlight, then navigate to the last line, select a few characters and click End Highlight.

  • For multiple selections, there could be an Add to Highlight button.

  • Instead of adding the range to the URL (and "polluting" the history), you could possibly copy the augmented URL to the clipboard, or have a pop-up similar to StackOverflow's "Share" link (this could be done whatever method of range-selection is used).

Just some thoughts: use or ignore as you see fit!

(28) By Warren Young (wyoung) on 2020-08-14 14:21:28 in reply to 26.1 [link] [source]

without actually highlighting it - that must be done server-side unless we use a separate DOM element for every line of code

Yes, which is part of my judgement above about "only sensible way to do it." If clicking the line doesn't set the highlight, users will be confused about what it is they're doing. Answering, "Just reload the page after making your selection" won't be seen as terribly helpful.

To do otherwise throws the principle of least surprise out the window.

the former should arguably take priority in any conflict

I don't see why you'd want 3rd-party syntax highlighting plus Fossil line highlighting. The colors are likely to clash and make the result hard to read.

I think what we want here is a choice between highlighters: 3rd-party syntax highlighting or Fossil line highlighting.

Some JS syntax highlighters have the ability to add line numbers as part of their action, so it's not like you must give up syntax highlighting just to get line numbers. (e.g. Prism.) Used in that mode, the Fossil "Line Numbers" feature can reasonably strip the highlighting, since it's a prelude to applying a different sort of highlighting.

each time you tap a line number, that gets added to the browser's history

Easily solved.

Option #2...copy the URL to the clipboard.

Given that I'm likely to be copying the URL manually shortly after doing this — what's the point in highlighting lines if you aren't going to share the URL? — I think Fossil should do this as well.

It's customary to flash a notification saying something like "URL Copied!" so the user doesn't waste time doing it manually afterward.

(29) By abhijit (abhijitnandy) on 2020-08-14 14:22:53 in reply to 26.2 [link] [source]

I've been following this thread from the beginning. Initially, I thought this thread isn't going to go anywhere. But now, Stephen, I'm seriously amazed! I hope this becomes part of fossil. Awesome!

(30.1) By Warren Young (wyoung) on 2020-08-14 14:38:19 edited from 30.0 in reply to 25 [link] [source]

Setting it to 2.8ex gives a fairly comfortable spacing.

...with the fonts you're currently using to test with. The x-height varies considerably among fonts.

It's common with CSS for such elements to list half a dozen monospace fonts plus "fixed-width", since you can't count on the same fonts to be everywhere.

So, 2.8× which x-height?

i've been unable to find concrete numbers for the C-/C++-side memory cost of DOM nodes

Make the browser tell you: decent browser developer toolsets have a Memory tab that reports how heavy the page is, in RAM.

Firefox on macOS reports that the current sqlite3.c page initially takes 109 MiB without the table and 436 MiB with it. We may guess at a doubling for adding a table row per line, so roughly a gigabyte.

Yes, that's a lot of RAM, but it's no more than a quarter of it in any machine I'm likely to ever open sqlite3.c into a Fossil file browser and then select Line Numbers mode. It's even doable on the larger Raspberry Pi boards!

Virtually every file viewed this way will take a tiny fraction of that wild outlier's memory footprint.

github simply refuses to output "too big," so there's a solid precedent for us

Given my test results above, I'd guess that the limit should be bigger than sqlite3.c. I'd say the heuristic should be a threshold likely to cause more than 2 GiB of RAM usage on the client side, being about half the size of a current "small" GUI-based development system.

EDIT: ...Unless we find a client platform that does something drastic like killing the page load if you exceed some lower limit. I can see mobile browsers doing something like this. In that case, we should adjust our threshold downward to cope.

And let's not get confused: I do realize that not everyone puts 4 GiB or more into every Fossil-based system. (My own public Fossil repos are on a 512 MiB VPS, for example.) However, I question how often those smaller systems run with a GUI, and of those that do, how many are using Fossil's file browser, and of those how many are likely to view files this big. Statistically speaking, tiny times minuscule times insignificant equals teensy-weensy.

Well-known mathematical fact, that.

(31) By Stephan Beal (stephan) on 2020-08-14 14:58:14 in reply to 27 [link] [source]

Possibly too late (I've seen the thread evolve but haven't had a chance to play with anything until now),

This isn't slated for 2.12, so there's no hurry.

but have you considered using simple text-selection with the mouse to indicate the area to be selected?

That's an interesting idea but i'm not certain that i could do that reliably. Unless we wrap each and every code line in its own DOM element, we don't know which code line we're selecting unless we break down the whole file and count the lines ourselves every time a selection is made (possible but painfully inefficient). If we wrap each code line in its own DOM element then syntax highlighters cannot work, and that feature is more important (based solely on mailing list/forum requests and my own personal preference) than line selection.

As I understand the original "everything in a <pre>-block" format, it should work with or without line numbers – shouldn't have any problems of "not lining up", or of local syntax highlighters not working.

The alignment is, so far, a hypothetical problem. In testing i've not been able to get the line numbers and code out of alignment if those two elements are configured with the same font-family, font-size, and line-height.

Mouse-selecting is (to me) a "natural" way of selecting text of interest.

Selection is sometimes tricky on touchscreens, though - one has to tap just right in order to initiate the process, and then has to drag tiny handles around to get the whole area selected. It works but it's often fidgety.

You cannot (as far as I know) select multiple ranges using the mouse (although the window.getSelection() appears to be able to handle this if there is).

AFAIK that's a platform-specific feature.

The method of counting lines doesn't seem to be affected if the

 block is set to wrap, but I don't know if different files' line-endings can affect things.

That's easy enough, but it requires traversing the whole file (arbitrarily long) for each selection. Counting lines is literally just a matter of counting literal \n characters. In its simplest form it's just theTextArea.value.split('\n').length, but that's also inefficient in that it creates a second, line-by-line copy of the whole text just so we can count the number of lines.

For selecting large blocks of text, you could potentially select a few characters in the first line and click Start Highlight, then navigate to the last line, select a few characters and click End Highlight.

But where do those UI controls go when we're scrolled 1234 lines down into the dock? We don't want to have to scroll back to the top or bottom to find the buttons for that. (Nevermind - a popup like the one mentioned below could host those.)

For multiple selections, there could be an Add to Highlight button.

Hypothetically fossil's ln=xxx feature supports multiple ranges, but i was not able to get it working for me. A cursory search suggests that it's not generally possible to do multi-select in HTML textarea elements, though.

Instead of adding the range to the URL (and "polluting" the history), you could possibly copy the augmented URL to the clipboard, or have a pop-up similar to StackOverflow's "Share" link (this could be done whatever method of range-selection is used).

An implicit transfer to the clipboard would be a last resort for me because i consider that evil unless the user explicitly asks for it (it risks wiping out something they put in the clipboard). A popup with a copy-to-clipboard option... oh, we have something like that on the timeline already (go hover over a timeline node). That could be used to show the current line(s) selected and copy the URL to the clipboard. i'll see if i can adapted that, and pop it up next to the clicked line. (i'm still not convinced about mouse-selection, primarily because of mobile.)

Just some thoughts: use or ignore as you see fit!

Thank you for taking the time!

(32) By Stephan Beal (stephan) on 2020-08-14 15:12:58 in reply to 28 [link] [source]

To do otherwise throws the principle of least surprise out the window.

See my reply to graham about that - i think that's a better way to go than adjusting the URL. The line highlighting isn't really intended for immediate use by the person selecting the lines, but for whomever they're going to send that link to.

I don't see why you'd want 3rd-party syntax highlighting plus Fossil line highlighting. The colors are likely to clash and make the result hard to read.

There's a bit of clash, depending on the highlighting theme, but so far it's still usable. To disable highlighting of the doc simply because one line is marked by fossil seems extreme. (Also, there's no practical way to tell the syntax highlighter not to run except, e.g., to inspect the URL params for "ln=", which is a fragile solution.)

Here's a slightly clashy, but still usable, example:

https://fossil.wanderinghorse.net/r/cwal/file?udc=1&ci=tip&name=cwal_format.c&ln=168-190

each time you tap a line number, that gets added to the browser's history

Easily solved.

Excellent - replace() is new to me but looks like an ideal solution, even for use in conjunction with the pending popup.

Given that I'm likely to be copying the URL manually shortly after doing this — what's the point in highlighting lines if you aren't going to share the URL? — I think Fossil should do this as well.

i agree, but if we implicitly do it then the user might not know they're overwriting their clipboard content. i've had fights with apps because they've replaced or cleared my clipboard content without me explicitly having told it to. (fossil diff -tk empties the clipboard when it closes if a selection was copied while it was opened, which is thoroughly infuriating.)

It's customary to flash a notification saying something like "URL Copied!" so the user doesn't waste time doing it manually afterward.

Where do we flash that, though, unless we add a "toast" API? There's no UI element to put that in which is guaranteed to be on the screen when they select something.

In any case, i think the popup from the timeline will suffice here perfectly, and it can be popped up to follow the line selection, so it's always in easy reach and tap-friendly.

(33) By Stephan Beal (stephan) on 2020-08-14 15:20:30 in reply to 32 [link] [source]

Excellent - replace() is new to me but looks like an ideal solution, even for use in conjunction with the pending popup.

Nevermind: replace() causes a reload of the page, which breaks what we're doing. We have to allow for a selection of a single line or a range of lines. If we replace() when the first line is selected we lose our state and can't select the second line to go with that. Well, we "could" but that would mean 2 round trips to select the range, which is horrible.

The popup is a nicer/more usable solution, anyway, so i'll go with that.

(34) By Stephan Beal (stephan) on 2020-08-14 15:24:45 in reply to 29 [link] [source]

Initially, I thought this thread isn't going to go anywhere.

FWIW, me too, but then the problem kept me from sleeping so it had to be tinkered with. #TheAddictionIsReal #FirstWorldProblems

I hope this becomes part of fossil.

i'm not pushing this for 2.12, as Richard has already posted what might become that release in the next few days, but if it's useful and not tooooo expensive then there's little reason it can't be in 2.13.

(35) By Warren Young (wyoung) on 2020-08-14 15:41:17 in reply to 32 [link] [source]

there's no practical way to tell the syntax highlighter not to run

There are two.

First, the highligher might not run at all, even if you tell it to. With Prism, it won't find a <pre><code> pair if the code is in a <table>, so it won't find an element to target, so the object constructor is a null action.

Second, if your highlighter will run on a <table>, then you can easily make the init call conditional:

if (!document.location.match('[&?]ln') {
   // init the highlighter
}

There's no UI element to put that in which is guaranteed to be on the screen when they select something.

The same way in-page confirm() replacements and such work: by requiring an empty <div> or whatever that they fill with dynamic HTML, place, and then display. In this case, it then fades back out after a second or so.

(36) By Warren Young (wyoung) on 2020-08-14 15:41:42 in reply to 33 [link] [source]

(37) By Stephan Beal (stephan) on 2020-08-14 15:54:30 in reply to 35 [link] [source]

Second, if your highlighter will run on a

, then you can easily make the init call conditional:

In my case i search for all pre-code blocks which have a language-XYZ class and pass them each individually to the highlighter. Highlighter docs usually tell users just to run it's init routine and let it figure it out by itself, but highlightjs likes to brute-force attempt anything pre/code blocks which have no language-XY class, and then complains loudly about it on the dev console, so i'm a stickler for specifically telling it what to process.

if (!document.location.match('[&?]ln') {
   // init the highlighter
}

That's what i meant by fragile. It's a leaky abstraction which has to be copied to all impacted repos and it and breaks the first time any new page with highlightable content gets a ln argument.

The same way in-page confirm() replacements and such work: by requiring an empty <div> or whatever that they fill with dynamic HTML, place, and then display. In this case, it then fades back out after a second or so.

That's basically a "toast", but it requires infrastructure we don't currently have and i'm not currently qualified to write (namely the animation). i'm not at all ruling it out as a near-future option, just saying we don't currently have any JS for that and probably won't have it this weekend.

(38) By Stephan Beal (stephan) on 2020-08-14 16:00:40 in reply to 36 [link] [source]

Plan B.

Eeek:

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

First, innerHTML is to be avoided at all costs whenever possible because it's subject to script injection attacks. Also, it's a string-based serialization process, so that round trip loses any and all event handlers.

history.pushState() does exactly what i want, but it also adds entries to the history, leading to potential confusion when trying to "back", causing users to cry out, "Ow, my back!"

The timeline popup is currently my preferred choice. It's there, is usable, and already does exactly what i want, it just need to be integrated.

(39) By Stephan Beal (stephan) on 2020-08-14 18:27:36 in reply to 30.1 [link] [source]

...with the fonts you're currently using to test with. The x-height varies considerably among fonts.

It's common with CSS for such elements to list half a dozen monospace fonts plus "fixed-width", since you can't count on the same fonts to be everywhere.

So, 2.8× which x-height?

Whatever the current ex is. Ex units are dynamically calculated by the browser based on whatever the current font is, so the layout adapts itself dynamically. i tried every font built in to Chromium and Firefox on my system and had zero problems in this regard - everything lines up to within a pixel or two, even for long files, with no small errors accumulating into larger ones the further down the file we go.

The alignment of the numbers and file content is hypothetically a problem but does not seem, based on every test i've made so far, to be a genuine problem. Even if there are fonts out there, used in this context, with glyphs larger than the line-height, they will simply overlap with the lines above/below them, rather than mess up the alignment.

Yes, that's a lot of RAM, but it's no more than a quarter of it in any machine I'm likely to ever open sqlite3.c into a Fossil file browser and then select Line Numbers mode.

It's not just about the RAM anymore, though. When this thread started i had not yet considered the fallout to syntax highlighters. That's a feature i actively use, and a feature others request from time to time, so i'm not personally willing to change the line numbering in a way which would break that (and will whine and moan incessantly if someone else does).

In any case, 1GB of RAM for any single static web page is downright criminal - that would keep me awake at night. Even gmail takes "only"... 230MB in Firefox.

It's even doable on the larger Raspberry Pi boards!

Sidebar: only the newest Pi 4B has an 8GB model, released not quite 3 months ago. i've been using one as my primary workstation since about a week, and am utterly thrilled with its overall performance running from an external USB3 drive.

Well-known mathematical fact, that.

Can't argue with math!

(40) By Warren Young (wyoung) on 2020-08-14 18:40:17 in reply to 39 [link] [source]

Whatever the current ex is.

That was a rhetorical question which was meant to lead you to the realization that "2.8 times big x-height" gives a very different result from "2.8 times small x-height."

everything lines up to within a pixel or two

My concern regarding x-height isn't about whether this breaks alignment, it's about whether it puts either too much or too little space between lines because you're on a system without the same fonts as the skin designer.

A large x-height is rather common with the better coding fonts, since a large x-height aids readability.

...yet we can't count on the user to have a large-x-height font installed, so if we design around that, now we get skins that put the lines too close together because you don't have a "good" font installed.

Do you see the problem now?

If you're going to force the line height, it should be in units other than x-height. It needs to be something based on the entire line height of "normal" text, like the "rlh" experimental value I linked to above.

1GB of RAM for any single static web page is downright criminal

We can argue about the threshold, but let's not get distracted by wild outlier cases. sqlite3.c is useful as a top-end test case, but it's not something to design around as "normal."

(41) By Stephan Beal (stephan) on 2020-08-14 19:28:36 in reply to 40 [link] [source]

Do you see the problem now?

i see a hypothetical problem which seems unlikely to materialize because it depends on corner-case conditions and weird fonts.

The "rlh" unit is far too new to be able to expect it to work in most browsers. It would be understood as an invalid value, probably leading them to use whatever their default is.

Nonetheless...

Mozilla recommends something which is new to me:

<number> (unitless)
    The used value is this unitless <number> multiplied by the element's own font size. The computed value is the same as the specified <number>. In most cases, this is the preferred way to set line-height and avoid unexpected results due to inheritance

A value of 1.35 works reasonably well for this purpose. 1.3 or 1.4 aren't bad, either. That's now checked in to the branch.

(42) By John Rouillard (rouilj) on 2020-08-14 21:00:03 in reply to 32 [link] [source]

I don't see why you'd want 3rd-party syntax highlighting plus Fossil line highlighting. The colors are likely to clash and make the result hard to read.

There's a bit of clash, depending on the highlighting theme, but so far it's still usable. To disable highlighting of the doc simply because one line is marked by fossil seems extreme. (Also, there's no practical way to tell the syntax highlighter not to run except, e.g., to inspect the URL params for "ln=", which is a fragile solution.)

Another possibility is to not highlight the code lines in fossil, but change the border for the selected lines. Since fossil only allows line and not character in line selection, we don't need to highlight characters, just mark the beginning of the affected line.

This splits the line indication markup from the syntax highlighting.

Now is this possible with the structure of the data? I am not sure. Maybe the row column could have a div around the highlighted lines and color the background of the number div for the selected lines? Since the markup is in the row number column only, it won't affect the syntax highlighting of the code column.

That would also provide additional visual weight to he marker compared to a border accent.

(43) By Stephan Beal (stephan) on 2020-08-15 02:06:58 in reply to 42 [link] [source]

Another possibility is to not highlight the code lines in fossil, but change the border for the selected lines. Since fossil only allows line and not character in line selection, we don't need to highlight characters, just mark the beginning of the affected line.

That was indeed my initial intention, but the existing code for the output output didn't lend itself well to that as-is and a complete refactoring of it was not on my agenda :/. Whereas it used to output the line numbers and file lines in the same step, right where the "is this line selected?" logic and state are available, my reimplementation has to first output all of the line numbers before it can output the file lines. Re-shaping it to highlight the line numbers instead of the lines is on my todo list.

(44) By Stephan Beal (stephan) on 2020-08-15 03:51:45 in reply to 43 [link] [source]

Another possibility is to not highlight the code lines in fossil, but change the border for the selected lines.

Re-shaping it to highlight the line numbers instead of the lines is on my todo list.

Here we go:

http://fossil.wanderinghorse.net/screenshots/fossil-line-select-highlight-3.png

And it only had CSS fallout in 2 skins, both of which have been patched for the new CSS classes.

Now it's just missing the URL-copy popup bit.

(45) By Alfred M. Szmidt (ams) on 2020-08-15 06:40:24 in reply to 44 [link] [source]

You people never cease to amaze me! When I raised the question about line numbering I really did not expect something to happen in such a short time! This is one of the many reasons why I enjoy fossil so much!

Thank you, this feature looks really nice so far!

(46) By Stephan Beal (stephan) on 2020-08-15 08:10:33 in reply to 45 [link] [source]

Now it's just missing the URL-copy popup bit.

That's now checked in, as well as the ability to select a single line or a contiguous group of lines by tapping on the line number(s) (that might be slow on large files because of the work it must do when selecting different groups). Dynamic selection of multiple groups of lines is left as an exercise for someone else.

Unfortunately, i can't build the x86/64 fossil binary for my hoster from this machine (an ARM Raspberry Pi), so the one on my site won't be updated until i can get it built from another machine.

You people never cease to amaze me!

That's just because you haven't gotten to know us yet ;). Give it another week or so.

When I raised the question about line numbering I really did not expect something to happen in such a short time!

i didn't expect anything to happen at all, but it's turning out to be a nice little improvement aaaand we now have a halfway decent tooltip widget which i can hopefully eventually use to replace the title-attribute tooltips in wikiedit/fileedit aaaaaaaand we have a halfway generic copy-to-clipboard button feature which can be plugged in just about anywhere.

(47.1) By Stephan Beal (stephan) on 2020-08-15 09:18:17 edited from 47.0 in reply to 28 [link] [source]

I don't see why you'd want 3rd-party syntax highlighting plus Fossil line highlighting. The colors are likely to clash and make the result hard to read.

That particular problem is resolved now, by selecting the lines instead of the code, buuuuut...

highlightjs is changing the font size when highlighting, which of course gets the code and lines out of sync, leading to silliness like:

https://fossil.wanderinghorse.net/r/cwal/file?udc=1&ci=tip&name=s2%2Fmod%2Fsqlite3%2Fmod_sqlite3.c&ln=2050-2061

(That range was selected with the mouse using the current tip, btw.)

Aaarrrggg.

If i can't find a way to stop it from mangling font sizes then i'm going to have no choice but to disable the syntax highlighter for these. Bummer.

Edit: got it :-D. Just had to add "inherits" on a few CSS classes to make sure the font size and line height get full propagated. The link above might be fixed by the time you read this.

(48.1) By John Rouillard (rouilj) on 2020-08-15 17:19:54 edited from 48.0 in reply to 47.1 [link] [source]

Nice.

It also highlights well without javascript. But it doesn't jump to the right location.

I wonder if there is some way to jump to the first highlighted range without javascript. I know I don't view random websites with javascript enabled.

I could see adding a name="startLineRange" to the first highlighted area, but how to change the url to include #startLineRange...

(49) By Warren Young (wyoung) on 2020-08-15 19:13:55 in reply to 48.1 [link] [source]

it doesn't jump to the right location.

This patch may solve the problem. If not, then something like it.

I wonder if there is some way to jump to the first highlighted range without javascript.

Sure: with fragment IDs and/or named anchors. (e.g. .../file/abcd1234#selection)

There are a bunch of details to work out around that, though. Generating the fragment IDs, dealing with browser history modification...

(50) By John Rouillard (rouilj) on 2020-08-15 21:14:49 in reply to 49 [link] [source]

Hi Warren:

I realize I wasn't clear. If javascript is enabled, the jump occurs fine. IIRC the top line of the highlighted code is displayed in the middle of the page which is probably desired. But your fix IIUC would put it at the top of the viewport. That works as well.

It's when javascript is disabled that you have to manually scroll down (potentially many, many, many) screenfulls of the page.

I don't see a way around it without a redirect. The server can't see or change the fragment on the client without javascript. So the only way this could work is for the browser to load a url with the fragment in place.

(51) By Stephan Beal (stephan) on 2020-08-15 22:29:44 in reply to 48.1 [link] [source]

It also highlights well without javascript. But it doesn't jump to the right location.

That's actually the legacy behaviour: it jumps about 15 lines back (give or take a bit - it's not a fixed value.

I wonder if there is some way to jump to the first highlighted range without javascript.

i'm not aware of a way to do that without including a hashtag in the link to the page: e.g thesite.com/page#jump-target.

I know I don't view random websites with javascript enabled.

Forewarning: Fossil is getting more JS in the near future.

I could see adding a name="startLineRange" to the first highlighted area

If an element has an ID then it automatically behaves like a #hash-target.

, but how to change the url to include #startLineRange...

That's the crux of the problem. We "could" add it to the generated links, but then it would only work on such links.

(52) By John Rouillard (rouilj) on 2020-08-16 00:30:01 in reply to 51 [link] [source]

That's actually the legacy behaviour: it jumps about 15 lines back (give or take a bit - it's not a fixed value.

I assume this is with javascript enabled. Without it enabled you are left at the top of the page.

I agree showing some lines before the highlighted lines is useful for context.

Forewarning: Fossil is getting more JS in the near future.

Yup I know. I won't be able to post to forum or edit wiki remotely soon since support for non-js text mode browsers will go away.

Hopefully I will be able to continue to view at least.

(53) By Stephan Beal (stephan) on 2020-08-16 01:13:04 in reply to 52 [link] [source]

I assume this is with javascript enabled. Without it enabled you are left at the top of the page.

Correct.

Yup I know. I won't be able to post to forum or edit wiki remotely soon since support for non-js text mode browsers will go away.

Hopefully I will be able to continue to view at least.

i've personally got no plans to replace any view-only features with JS equivalents. It's only being used to bring the more interactive components into the 21st century (insofar as my own contributions go, anyway - can't speak for anyone else).

The code line highlighting will still work in non-JS environments, as the initial highlighting is performed by the server, it just won't have clickable line selection in the client.

Text-only browsers have never been a serious concern for us during development (as can be seen by our heavy reliance on CSS for layout). They have their niche uses, but explicitly targeting them would hold us back considerably or require duplicate page implementations and the ability to reliably detect such browsers for purposes of selecting the output mode.

(54.2) By Stephan Beal (stephan) on 2020-08-16 03:45:57 edited from 54.1 in reply to 1 [link] [source]

It would be really really nice if one could just click on something in the UI somehow, or mark the region and get back a link.

Now we can. i invite everyone to try out this still-in-a-branch feature over at:

https://fossil.wanderinghorse.net/r/cwal/file?udc=1&ci=tip&name=cwal_json.c&ln=8-13+20-23+30

This feature arrived too late for the 2.12 release, but can be found in the line-number-selection branch until it is merged in after 2.12 goes out the door.

Some of the highlights:

  • Line selection now marks the line numbers instead of the code so that...
  • Client-side syntax highlighters can work without clashing with fossil's highlighting. (The site at the above link uses such a highlighter.)
  • It is now possible to select an individual line or range of lines by tapping on the line numbers, which causes a small popup to appear with one the line range link can be copied to the clipboard. (Selection of multiple ranges is not implemented via tapping - those have to be manually composed into the URL bar until someone who really wants to do it with the mouse patches this code to do so.)
  • Edit: code can be selected/copied without also copying the line numbers. (Conversely, the code cannot be selected/copied with the line numbers.)

With the caveat that the copy-to-clipboard feature requires that the browser's environment support that, which is not a given but "should" work on most desktop and Android environments.

The line selection heuristics "should be" relatively intuitive, but here's how they work:

  • Selecting a single line when there is no selection will mark that line and pop up the clipboard widget.
    • Selecting a line while a range is selected unselects that range first.
    • Selecting a single line when it is already selected unselects it and hides the clipboard popup.
  • Selecting a single line while a different line is selected will mark the inclusive range between those lines and pop up the clipboard widget.
  • Minor caveat: lines marked by the server for initial rendering of the page are not considered for purposes of the "is a line marked?" decision making. Any clicking of lines while server-marked lines are shown will unmark those lines and then react to the click as if those lines had not been marked.

The clipboard popup widget always pops up/is moved directly next to the most recently clicked line number, so it's always within easy reach.

In the context of this change, a few infrastructure-level additions were created which will be helpful in other contexts:

  • The copy-to-clipboard widget, previously only available in the timeline, has been genericized for use in various contexts, including the ability to add multiple such buttons per page.
  • A basic popup widget was built to support the creation of widgets like the line selector's copy popup and...
  • A basic "toast" message mechanism was added (use the line selector's copy button to see it in action - watch along the top/left of the page after tapping the copy button).

As always: feedback, suggestions, patches, etc...

(55) By John Rouillard (rouilj) on 2020-08-16 02:36:38 in reply to 53 [link] [source]

HTML markup does a good job. Making it accessible to text mode browsers, screen readers, feature phones.... To screw up the web requires javascript 8-).

You have to log in so login as anonymous works.

Wiki view works (and edit for now).

Forum view works, but the url's from threads don't use a fragment, so you need to switch to chronologigcal view. Links between messages also fail because of lack of fragment.

Timeline is missing the graph, the other issue is none of the form settings (lines, type of entries ...) can be changes because there is no submit button. Adding a submit button and hiding it with:

   body.hasjs #f01 submit { visibility: hidden }
and running javascript that adds the hasjs class to the body tag would handle that.

Viewing checkins works including changing diff style.

so I would say 85% of what should work works.

(56) By Stephan Beal (stephan) on 2020-08-16 03:01:28 in reply to 55 [link] [source]

Adding a submit button and hiding it with ... and running javascript that adds the hasjs class to the body tag would handle that.

That's an interesting idea. i'll take a look at that.

Wiki view works (and edit for now).

so I would say 85% of what should work works.

With the release of 2.12, that number's about to shrink, and will almost certainly shrink further in 2.13: the plan is to integrate the wikiedit/fileedit tabbed edit/preview mode into the forum, at which pointing posting will not be possible without JS (and we'll sell that as an anit-bot measure ;)). That's the approach many reasonably modern well-visited sites use nowadays (e.g. github and BoardGameGeek, though both of those use client-side JS-based rendering of the preview), and implementing more than the most basic of tabbed interfaces requires client-side scripting.

Similarly, the checkin editor might also get ajaxified.

Even so, it's only the interactive/editing-related components which are being scriptified. There's no need/plan to replace static data-oriented pages (which means most pages).

(57) By Stephan Beal (stephan) on 2020-08-16 03:36:49 in reply to 56 [link] [source]

Adding a submit button and hiding it with ... and running javascript that adds the hasjs class to the body tag would handle that.

That's an interesting idea. i'll take a look at that.

It's conceptually easy to do but requires far more work than simply emitting one line each of HTML, CSS, and JS.

The UI at the top of the timeline is constructed in multiple phases across two C files and is built up solely via an internal API used for creating submenus. i.e. we can't simply emit HTML for that button - it has to go through the object-oriented submenu API. That API does not currently support button elements because those have never been used in a submenu. So adding a submit button requires hammering on that API to add the appropriate bits for buttons, just to support that one button (which very users would ever see).

Once that were done, it would allow non-JS-capable bots to toy with the form.

In short: the overhead required to support that one button, and the potential for side effects, make me leery of adding it.

(58) By sean (jungleboogie) on 2020-08-16 03:41:30 in reply to 54.1 [link] [source]

Line selection now marks the line numbers instead of the code so that...

That's a nice idea! Hats off to whomever thought of that solution. Another nice feature is not copying the code and line numbers.

Thanks to all who have participated in this conversation! It's been well discussed and I look forward to the final implementation in time.

There's one side effect of the helper text "Copied to clipboard."

  1. Highlight one or more lines anywhere in the file
  2. Immediately go to the end of the page
  3. Notice the helper text is present in the lower left of the page

Scrolling up and down the page doesn't make it disappear and persists there until the next page load.

This might be a design you implemented - I haven't read all the posts in this conversation yet.

(59.1) By Stephan Beal (stephan) on 2020-08-16 03:55:03 edited from 59.0 in reply to 58 [link] [source]

Notice the helper text is present in the lower left of the page

Ooops - it's supposed to be hidden. (The reason it shows up there is because it's a child of the BODY element.) i'll get that fix in a few moments.

This might be a design you implemente

Nope - bug.

Edit: fixed via CSS improvement. Demo site will be updated in about 5 minutes.

(60) By Alfred M. Szmidt (ams) on 2020-08-16 12:37:53 in reply to 54.2 [link] [source]

I am thinking that the behavior of selection to be slightly confusing, in that when you continue selecting text, it resets the selected region. I.e., if you start selecting line 10 to 30, and then press 40 the selected region is reset. But while I do find it slightly confusing, I think it also makes sense so I'm on the fence. I think e.g., Github (which should not say that this is a good example) continues extending the selection.

Other than that minor quibble, I find this feature REALLY nice. Thank you!

(61) By Stephan Beal (stephan) on 2020-08-16 14:12:22 in reply to 60 [link] [source]

I think e.g., Github (which should not say that this is a good example) continues extending the selection.

What i tried to do was to have it extend the selection if:

  • The shift key was pressed.
  • A line before the first selected line or after the last selected line was clicked.

But:

  • The browser has built-in shift-click handling which extends is own text selection, causing a horrible-looking mishmash of our highlighting and the browser's. i tried several supposed tricks to suppress that but none worked for me.
  • That approach cannot work on mobile devices.

i don't want to extend the selection simply by clicking out of range because...

  • It seems like that would make it more difficult to deselect the current range.
  • (spoiler alert...)
  • That behaviour would almost certainly change, and get a radically different meaning, if multi-range-select is ever implemented, so that multiple ranges could be selected.

(62) By sean (jungleboogie) on 2020-08-17 14:29:59 in reply to 54.2 [link] [source]

Hi Stephan,

Now that your branch is on trunk, I tried it out with the hosted Fossil repo and noticed when line numbers are enabled, the font size significantly increases.

Using forum.c as the example, notice enabling the line number enlarges the text.

Your json.c without line numbers and with line numbers enabled doesn't seem to enlarge the font.

Fossil www2 is a few commits behind so you can tell the difference there: forum.c on www2

So I guess my question is, how does your font not increase?

(63) By Stephan Beal (stephan) on 2020-08-17 15:32:15 in reply to 62 [link] [source]

Now that your branch is on trunk, I tried it out with the hosted Fossil repo and noticed when line numbers are enabled, the font size significantly increases.

That was intentional - my eyes aren't anywhere near as good as they used to be. That can be dialed back if it annoys too much - it's just a CSS tweak:

https://fossil-scm.org/home/file?udc=1&ci=tip&name=src%2Fdefault.css&ln=1160

(oh, that's soooo much easier than typing the line numbers in the URL bar.)

(64) By Florian Balmer (florian.balmer) on 2020-08-18 11:56:13 in reply to 26.3 [link] [source]

As always: feedback, suggestions, patches, etc...

  1. The "tooltip" (I'd rather call it a "popup", because it doesn't show up automatically when hovering the mouse over a certain area) that appears when clicking a line number has a copy button and says "line X" or "lines X-Y". This is misleading and sounds like it would copy the indicated source lines themselves, instead of a hyperlink with the indicated lines highlighted. I think the label should be renamed to "Copy Link to Lines X-Y", or similar.

  2. The "tooltip" can't be closed with the ESC key. Usually, when unsure whether the action offered by the "tooltip" is desired, but if it's also unclear whether clicking anywhere else would discard the current selection, it's a good reflex to hit ESC to make to "tooltip" go away. I think this feature should be added, as both the tooltips on the timeline and the hamburger menu support this.

  3. The animation of the copy button for the hyperlink is different from those on the timeline tooltips, or on the info page, i.e. the button fades out, and then the whole "tooltip" goes away, without the button to reappear. This is not a problem by itself, but the lacking consistency across the Fossil UI gives the impression that something is broken with the new "tooltip". I think it's better to wait for the full animation to complete, i.e. until the button is visible again, and then close the "tooltip". Inconsistent UIs quickly look hackish.

  4. The additional "toast notification" is redundant. And because visual attention may be far down the page when selecting lines and copying the link, the "toast notification" at the very top may be missed -- and may only be noticed after the "tooltip" to copy the link was closed, and despite its longer timeout, the "toast notification" may then disappear very quickly, only leading to confusion. If a textual feedback that the link was copied successfully is considered necessary (it's redundant, anyway, in my opinion: users are familiar with standard UI elements like copy icons and their functionality), it should go directly into the "tooltip" to copy the link, where visual attention is already focused on. (For example, the label text could be changed to "Copying ..." or "Copied!" while waiting for the animation of the copy button to complete.) The "toast notification" has no additional value, except for pointing out "Hey, look, we've got bells and whistles, just because we can!", again reminding me of my first steps with Windows GUI programming ~30 years ago. Also, the very fact that you had to advertise the "toast notification" with the words "watch along the top/left of the page after tapping the copy button" shows that it can be easily missed, already questioning its usability.

  5. The changing size of the text with line numbers enabled is indeed confusing, as already mentioned elsewhere. With line numbers enabled, I'm usually searching for a code spot to link to, that was most likely found with line numbers disabled (because that is the default), and it's unnecessarily harder to find the same spot again with the text changing shape. This seems to be fixed on trunk, but I haven't tested it, yet.

  6. Similarly to the tooltips in the timeline, there should be an option to disable this feature, because it's rather obtrusive. Also, disabling the feature should prevent the vast Javascript libraries to be loaded into the otherwise lean-and-mean pages.

  7. The copied URL should be clean and canonicalized. In particular, it should use the repository-default length for hashes instead of the length used by the current URL, and unnecessary query parameters like "udc=1" should be removed. (Since "udc" means "update display cookie", I think it's a bad habit to post links to the Forum that may update the display cookie of the reader, anyway! Yet, most Forum users do this...)

(65) By Stephan Beal (stephan) on 2020-08-18 14:11:05 in reply to 64 [link] [source]

The "tooltip" (I'd rather call it a "popup", because it doesn't show up automatically when hovering the mouse over a certain area)

LOL! It's funny you say that because the JS class for that was initially called TooltipWidget and i renamed it to PopupWidget because it's "not really a tooltip."

that appears when clicking a line number has a copy button and says "line X" or "lines X-Y". This is misleading and sounds like it would copy the indicated source lines themselves, instead of a hyperlink with the indicated lines highlighted. I think the label should be renamed to "Copy Link to Lines X-Y", or similar.

That's a good point - i'll change that.

The "tooltip" can't be closed with the ESC key. Usually, when unsure whether the action offered by the "tooltip" is desired, but if it's also unclear whether clicking anywhere else would discard the current selection, it's a good reflex to hit ESC to make to "tooltip" go away. I think this feature should be added, as both the tooltips on the timeline and the hamburger menu support this.

i'm torn on that point. i agree that it might be intuition, but i don't want that particular popup to close until the user has activated it. You can close it by clicking anywhere within the code, but then you cannot copy the link unless you re-activate the selected region. i don't really want to add Esc event handling to avoid any undesired side effects like features such as the hamburger menu. For example, the hamburger event handler would be registered first, so it would always be activated before i could cancel it, and then the popup would close when the user only wanted to close the hamburger.

The animation of the copy button for the hyperlink is different from those on the timeline tooltips, or on the info page, i.e. the button fades out, and then the whole "tooltip" goes away, without the button to reappear.

It initially worked like the timeline, but i changed it because its disappearance was confusing to me as a user. In the timeline, where the popup appears in response to hovering, that makes sense to me. In this interface, where the popup is showing the user the selected region and offering to copy the link, it doesn't make sense to me to hide it.

The additional "toast notification" is redundant.

i'm not emotionally attached to the toast notification. We can drop that if it annoys people. i added it to provide more information about what that little "lines 13-20" button does. Changing that label to "copy link to..." would clarify that, though.

Similarly to the tooltips in the timeline, there should be an option to disable this feature, because it's rather obtrusive.

If we disable it, you can't select lines except by modifying the URL by hand.

Also, disabling the feature should prevent the vast Javascript libraries to be loaded into the otherwise lean-and-mean pages.

It's not my policy to maintain separate JS and non-JS versions of features. The compressed JS payload sizes are amazingly small, so the lean-and-mean argument isn't as compelling to me as it would have been before seeing the numbers during testing. For that specific page, only 6k (compressed, 18k uncompressed) of JS is transferred, and it is cached long-term (a year), so the aggregate transfer size is insignificant.

Just coincidentally, i was talking with Richard about my push to JS-isfy and whether that was something he's okay with. The management summary is yes, at least for the cases of heavy user interaction, and one of my soon-to-do TODOs is to write up a document explaining the project's policies for, and use of, JS code (with feedback from the devs, of course, but a draft has to be written first).

The copied URL should be clean and canonicalized. In particular, it should use the repository-default length for hashes instead of the length used by the current URL,

That would require the JS code explicitly parsing and processing each argument. What it currently does now is takes the current URL, strips out the ln=..., and just appends its own ln=... part on the end. Thus it is following the canonical URL conventions as long as the link which led the user there is canonical.

and unnecessary query parameters like "udc=1" should be removed.

That's a fair point. i wasn't aware of what that parameter did. On the other hand i really don't want to have to maintain the JS code's link handling every time some parameter changes on the server. At a very minimum i'll strip out udc=X, though.

(66) By Florian Balmer (florian.balmer) on 2020-08-19 12:26:57 in reply to 65 [link] [source]

I don't really want to add Esc event handling to avoid any undesired side effects like features such as the hamburger menu.

Both the key event handlers for the hamburger menu, and for the timeline tooltip copy button, are enabled temporarily, only while the menu panel, or the tooltip, respectively, are visible. But even if the handlers were permanent, the events could still be dispatched in a fine grained manner, by exploiting event capturing/bubbling, controlling event propagation, preventing default actions, etc.

However, if it is possible to open the hamburger menu while the "Copy link to lines" popup is active, this seems like a bug, anyway. In fact, the popup window even stays on top of the hamburger menu, when it should really disappear.

Every tooltip, every popup window, and every menu panel on every desktop OS can be dismissed by hitting ESC. Just because you prefer the "mobile-first" approach -- where this probably doesn't work -- the "Copy link to lines" popup doesn't support it, either. I think this is not the best approach, any many desktop and/or keyboard users may intuitively reach for the ESC key as soon as anything is popping up, anywhere.

... animation ...

It initially worked like the timeline, but I changed it because its disappearance was confusing to me as a user. In the timeline, where the popup appears in response to hovering, that makes sense to me. In this interface, where the popup is showing the user the selected region and offering to copy the link, it doesn't make sense to me to hide it.

I'm sorry I don't understand your reply. But maybe you also got me wrong, so I'll try to summarize my points, again.

Current "click" animation sequence of the timeline tooltip copy button:

  1. Fade out the copy button.
  2. Fade in the copy button.

Current "click" animation sequence of the "Copy link to lines" popup:

  1. Fade out the copy button.
  2. Hide the popup.
  3. (Feels like something is missing, or something gone wrong.)

Expected "click" animation sequence of the "Copy link to lines" popup, for a consistent look and feel across the Fossil UI:

  1. Fade out the copy button.
  2. Fade in the copy button.
  3. Hide the popup (after another few milliseconds).

It's not my policy to maintain separate JS and non-JS versions of features.

See my reply on another thread for more comments about the new Javascript library.

(67) By Stephan Beal (stephan) on 2020-08-19 16:06:18 in reply to 66 [link] [source]

Every tooltip, every popup window, and every menu panel on every desktop OS can be dismissed by hitting ESC.

i disagree in this case. If the copy-line-link popup is showing and i tap ESC then it disappears, and i have no way of getting it back without re-selecting my range of lines (which might be larger than the screen).

That said: feel free to patch it to do so.

Current "click" animation sequence of the "Copy link to lines" popup:

i attempted to animate the popup's arrival and closing with CSS but failed - i could get it to animate when popping up but not popping down, but that's because my CSS know-how is insufficient, not because it can't be done. Doing the animation via JS is "old tech" and i didn't/don't want to go that route.

That said: feel free to patch it to do so. It would go somewhere near:

https://fossil-scm.org/fossil/file?udc=1&ci=4368f52961d0bc57&name=src%2Ffossil.popupwidget.js&ln=126-188

See my reply on another thread for more comments about the new Javascript library.

i will probably be a little slow responding to forum posts today but will get to it later on.

In case you haven't seen yet, your other suggestions were implemented in:

https://fossil-scm.org/fossil/info/7c98df415874259b

(68) By Florian Balmer (florian.balmer) on 2020-08-20 12:25:07 in reply to 67 [link] [source]

If the copy-line-link popup is showing and I tap ESC then it disappears, and I have no way of getting it back without re-selecting my range of lines (which might be larger than the screen).

One possible solution here is that the popup would reappear if the user is hovering -- or in this case clicking -- inside the selection (without discarding the selection), and to clear the selection only if the user is clicking outside of it.

Since you emphasize at every opportunity how happy you are not having to use Windows, you may think that Windows users are just double-clicking things all day long -- but you'd really be surprised how smooth things work in a decent UI!

I attempted to animate the popup's arrival and closing with CSS but failed ...

The popup itself doesn't need an animation, because it's appearing or disappearing in response to a click by the user, which is already sufficient visual feedback.

The copy button, however, is animated to indicate that the click was accepted and handled. (By the way, the animation was initially requested by drh.)

I'd really love to jump in to patch and tweak such little things, but unfortunately I'm at a complete loss with ES6 and your new library!

Are you at least interested in fixing this bug, because it can be triggered on the Fossil flagship website?

The easy "fix" may be to make sure that the "Copy link to lines" popup has a lower Z-order than the hamburger menu panel. (The real fix would either be to close the popup before the hamburger menu is opened, or, even better, to block the hamburger from opening as long as the popup is active, with a temporary page-wide "click" handler tied to the popup lifetime, for example.)

(69) By Stephan Beal (stephan) on 2020-08-20 20:33:46 in reply to 68 [link] [source]

I'd really love to jump in to patch and tweak such little things, but unfortunately I'm at a complete loss with ES6 and your new library!

ES6 is not so different from every prior version, so if you know JS from 2006, 98%+ of it is the same. They've only added to the language, not removed anything from it.

Are you at least interested in fixing this bug, because it can be triggered on the Fossil flagship website?

If you're talking about the animation, i don't consider it a bug, but a cosmetic personal preference. The current behaviour is that the copy button flashes, exactly as it does in other contexts, and then the popup closes. i'm happy with that behaviour, but i'm not emotionally attached to, so if someone wants to go change that they won't get any objection from me.

If you're talking about the popup appearing over the hamburger, the conditions for triggering it are "unusual," at best. One first has to be on the line-numbering page, then select 1 or 2 lines, then pop open the hamburger menu. i've just lowered its z-level to be below that of the hamburger (which i consider to have a too-low z-level, but that's something to tweak another day), but that won't take effect until the main site is updated to the latest trunk (it's currently running 2.12.1).

(The real fix would either be to close the popup before the hamburger menu is opened, or, even better, to block the hamburger from opening as long as the popup is active, with a temporary page-wide "click" handler tied to the popup lifetime, for example.)

Adding code for that level of UI micromanagement is, IMO, in nobody's interests.

(70) By anonymous on 2020-08-27 22:12:18 in reply to 1 [link] [source]

There's a bit of discord in the line number formatting between '/file' and '/annotate' views.

Annotate view presents the line number with a trailing colon ":" separator, while the file view does not.

The separator presence in the text output generally makes sense, as it signals the end of the "service" field and the start of the actual source line.

Perhaps, in the file view too the ":" should be appended to separate the line numbers from the source for consistency.

(71) By Stephan Beal (stephan) on 2020-08-28 04:01:18 in reply to 70 [link] [source]

Perhaps, in the file view too the ":" should be appended to separate the line numbers from the source for consistency.

To my eyes the colon in both views just adds noise. The file line number view has never had the colon, so we could argue that it should be removed from annotate for consistency. It does seem to serve a purpose in that view, though, as you say, where it would serve no useful purpose in file line number mode, so this tiny difference between the two doesn't bother me at all.