PerBothner / DomTerm

DOM/JavaScript-based terminal-emulator/console

Home Page:https://domterm.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

documentation improvement: show/hide button

albertz opened this issue · comments

Basically, a while ago, I asked this StackOverflow question, about what escape code to use for collapsing/folding text.
Now I read in the DomTerm doc about show/hide button (via \e[16u and \e[17u), but the description is quite short, and I am not sure I fully understand if this is what I asked in my SO question, and how to use it. An example, maybe including a screenshot (or GIF) would be very nice.

I was planning on writing this up, but never got around to it. Thanks for reminding me.

I did write a test/demo program, which I intend to turn into something more intructive.
Take the attached PrintNested.java.txt, rename it to PrintNested.java, compile it (javac PrintNested.java) and then run it (java PrintNested) in a DomTerm window. You see triangular hide/show buttons. Also try re-sizing the window, and see how the line-breaks adjust.

PrintNested.java.txt

Thanks for the example, that's very nice! That's very much what I had in mind. You should add such example code to the documentation (maybe in Python, that would be simpler to read, and much shorter).

One thing which might/should be improved: When you run that in a terminal emulator which does not support the escape codes, it looks a bit broken. It should be possible to do it in a way that for emulators which would ignore the escape codes to just have it printed as if it was all unfolded, and without the buttons. I.e. that also means that you would not directly print the buttons, but they are part of the escape codes.

I'm trying to play around with this right now (here) but I still don't fully understand it. Maybe you can make a simpler example?

What I want (maybe good for a simple example):

  • Some show/hide button, or basically having two states (shown and hidden).
  • In the shown state, should show text1 (e.g. the full long description of whatever).
  • In the hidden state, should show text2 (e.g. some short summary of whatever).

Or is this not possible, and in the hidden state, it will always not show anything? Or it will always show the same prefix?

This is basically what I managed so far (by playing around), but maybe I also did sth wrong:

  • Some show/hide button.
  • Some text which is always shown (no matter the state).
  • Some additional text which is only shown if in the shown state.

Some question which are unclear to me:

  • When do I need to use the logical block? I tried to look at your example, and it seems you at least nest them 2 times, for a single hide button.
  • I need to replace "\n" by "\033]118\007"? Why? Where is this documented? And when? Where? Always inside such a logical block?
  • When do I need to use this hide-button-span?
  • How to I get what I asked above?

I've spent some time polishing and cleaning up the demo. It is now checked in as org/domterm/util/PrintNested.java. The next step was writing documentation for the manual. I wanted a live demo, but got side-tracked by some problems with view-saved.

"Or is this not possible, and in the hidden state, it will always not show anything?"

That is correct - only the button is shown. In general when I see "folding" nothing is shown in the hidden state. However, it doesn't seem difficult to implement an extension to specify a "hide" text (or even a <span> of rich text).

Somewhat awkward is that the text to show/hide is implicitly delimited. This is somewhat forced for the "shell" use-case, where the only thing we can customise is the prompt string. Therefore the end of the text to show is the end of the line - or the end of the logical block (used for pretty-printing). I'm trying to figure out how to specify this more precisely.

It would help if you're familiar with the concept of Lisp-style pretty-printing. This blog article may help. It does not discuss folding, but its related because folding is limited by the surrounding logical block.

"When do I need to use the logical block?"

Informally, anything you want to end up as "block" (similar to CSS blocks but doesn't use CSS blocks) and indented together should be in a block. I.e. any logical unit.

"I tried to look at your example, and it seems you at least nest them 2 times, for a single hide button."

Not always. The printTree method creates a logical block for each child, where each child is printed by printObject - which does not always create a new block.

"I need to replace "\n" by "\033]118\007"?"

Not required, but it will work better. Basically, it replaces it by a "required newline" for the pretty-printer. This could probably be automated in the DomTerm JavaScript - though that would probably require some minor fixes to the JavaScript.

If you don't care about pretty-printing (automatic dynamic logical line-breaking) it should work to just wrap a logical block around each section of text you want to hide, with a button at the front. If you want different non-empty text when hidden, we'd have to extend the protocol, but I think it would be easy. After you add logical blocks you can add conditional newlines between logical "section" and/or adjust indentation.

It would still be nice to have some very short examples (e.g. like 5 lines of Python code), for some of the common (simple) cases. My goal is currently to extend some of my applications to hide some parts of the output away, and some example to do so would be quite helpful. Btw, for that use case, it would also be good to have some reliable way to detect whether it is run in DomTerm, e.g. some env var.

No, that alternative text for the hidden state is not necessarily needed for now.
But I tried with just regular "\n" and that looks awkward, there appear too many newlines then.
Also, I want it to be hidden by default/initially. In my demo here, this is the case via this hide-span block, but I'm not sure if I do it correctly. At least it works in this demo; it does not work if I use "\n".

"it would also be good to have some reliable way to detect whether it is run in DomTerm, e.g. some env var."

See this page (which I recently moved/updated).

The new (checked-in) version of PrintNested.java does test if it is running under DomTerm (see the isDomTerm field), though not as robustly as the script in the above-mentioned page.

I forgot about the \e[83u escape sequence ... too many features to keep them all in my head :-) I'm reviewing the logic of the code to understand all that it is trying to do, to see how to document it more precisely and may be if it can be simplified and/or generalized.

Text that is shown when the other text is hidden seems to work by doing this:

    hide_button()
    print("<always visible>", end="")
    sys.stdout.write("\033[83;1u{text when hidden}\033[83;0u");

This may not be super-robust, though. I have to think about and test it more.

The problem with "\n", am I doing something wrong, or is this "broken" by design? If I'm doing sth wrong, can you explain how to do it right? Or do I really always have to use "\033]118\007" instead of "\n"? Why?

A "\n" has certain extra side effects that are undesirable when inside a logical block. I'm looking into having "\n" check if it within a logical block and in that case act like a "required" newline. I haven't gotten it to work yet. (A complication is that we have to check for "\r\n" rather than "\n".)

I extended my demo a bit further, and have a screenshot now here:
domterm-foldtext1

I checked in a fix so a plain newline (or actually "\r\n") in a logical block is treated as a required newline, without having to emit the special escape sequence.

If the last char before the hide-span is a color escape code (\x1b[0m), it seems it is not correctly handled. See my most recent addition to my demo.

If you copy some folded text to the clipboard, it will not copy the hidden text (only if it is unfolded).
I'm not sure if this is by design or not.
In any case, I want to have an option that the hidden text will be copied to the clipboard in any case.
(Also, additionally, it would be nice if the show/hide button would not be copied to the clipboard.)

Another kind of feature request for the folding: It would be nice if I can set some identifier string for each show/hide button, and then:
Remember what state it is in (i.e. either shown or hidden). And if another button with the same id appears (e.g. you restart the tool from earlier), it will recover that state (i.e. either shown or hidden).

I created a live demo: http://domterm.org/demo/nested-1.html
This demo is just static files and does not depend on a server.
This demo will be linked to the documentation once I write it ...

"I want to have an option that the hidden text will be copied to the clipboard in any case."

I don't think that is a good idea. Normally, a browser's "Copy" only copies visible text. It wouldn't difficult to change the implementations (see DomTerm._selectionValue, which calls selection.toString()), but it would cause confusion I think. One issue: what if you have "replacement" text that is shown when an item is hidden? Do you want both the replacement text and the hidden text? That would be weird.

However, "Copy" will copy the selection both as text/plain and text/html, in which case the receiving application can choose which to use. There is also a "Copy as HTML" menu item, which copies the selection as HTML, but with mime-type text/plain, so it can be pasted into any application. The HTML does include both hidden and unhidden elements, and you can post-process it as you want. (It is well-formed XML as well as HTML, so lots of tools can work with it.)

"It would be nice if I can set some identifier string for each show/hide button, and then:
Remember what state it is in (i.e. either shown or hidden). And if another button with the same id appears (e.g. you restart the tool from earlier), it will recover that state (i.e. either shown or hidden)."

Not sure what you're asking for. Do you want to be able to link multiple buttons together, so clicking one is like clicking all of them? What do you mean by "restart the tool"? Do you mean re-running an application in the same DomTerm session, and having the initial folding state match the previous run?

It seems possible to assocate an application-provided string with each foldable section and with each button; clicking the button would flip the show/hude state of each foldable section with a matching string. Probably not that difficult, though nailing down the protocol might take a little work. However, I've never heard of this UI feature, so it may be a little hard to justify. However, if you really want it, I'll look into it. (It's nice to have active users!)

(You can detach and attach DomTerm sessions. When you attach to a detached session, it is supposed to restore the previious folding state. I assume that is not what you're referring to.)

I want to have an option that the hidden text will be copied to the clipboard in any case.

I don't think that is a good idea.

Well, I would say that depends on the use case. In some cases, I definitely agree. In e.g. my use case (this, error log output, extended stack trace), it is all hidden by default, i.e. folded away. And there are two kinds of people:

  • Developers would interactively show / fold out parts of the stack trace to show e.g. the values of local variables, and to understand why the crash happened, etc. Here it is quite useful that it is all hidden by default because it would be too much spam otherwise (stack traces + all locals can be long).
  • Other users would just copy the whole stdout text and paste it in a GitHub issue so that the developers can see the problem. This should contain the full information (all text unfolded / shown), and not how it is presented (i.e. all hidden).

What I say is that this should be controllable by the escape code as an option, which can configure this behavior. So the app can define the behavior, and the app developer can decide what he thinks is the right behavior for his use case.

What do you mean by "restart the tool"? Do you mean re-running an application in the same DomTerm session, and having the initial folding state match the previous run?

Yes, e.g. my use case with this extended stack trace again: Imagine there is the relevant function, which I folded out to see the content of the local variables, and then I try to fix it, run it again, and it again crashes with a very similar or same stack trace. And I repeat that a few times. It would be nice if it remembered that I folded out this specific frame in the stack trace before, and not by default hide everything, but show what I had previously also folded out.

Btw, maybe you want to join the discussion here about how to come up with a good standard for text folding, which can be adopted by many terminal emulators. DomTerm is mentioned there, but its text folding support (the show/hide button, and the escape codes) is not considered as a good solution as it is done right now. I kind of agree with the criticism. But anyway, the discussion is mostly about how to come up with a clean standard.