[Script] Helping the Helpers: Providing well-formatted Command Output

This is still a work in progress; testing needed and very welcome.

Why

This helps with items 4 and 5 on this list:

We will combine the two, because inline code blocks should go away when they have fulfilled their duty, lest they obstruct the conversational context surrounding them.

How to do better

Let’s build us a little helper script that runs a command, collects its output, wraps it in BBCode for better readability and copies it to the clipboard, all in one fell swoop. After running it, all that’s left to do is to paste the text in the Discourse editor on an empty line.

Installation

Since there is nowhere to download this (yet?), here’s how to install it.

  1. We need some helper package(s) to make the script talk to the clipboard:
    sudo apt install wl-clipboard xsel
    
  2. Open the following details section, entitled `cat cmd2bb`, and copy the contained code block (note the clipboard icon in the top right corner of code blocks):
    cat cmd2bb
    What's a clipboard?

    It’s the invisible copy/paste buffer, where data goes when you “copy” something, e.g. by pressing the the keyboard shortcut (Ctrl-C) or by clicking the little icon in the top right corner of code blocks, which looks like a sheet of paper on a clipboard ;). It’s a small buffer to transfer data from one program to another. You’ve most probably been using it for a long time, but didn’t know it by that name.

    For the Pros: Fast Forward to 5)
    dest=/usr/local/bin/cmd2bb
    wl-paste | sudo tee "$dest"
    sudo chmod +x "$dest"
    unset dest
    
    Explanation

    And here is the script, demonstrating itself, for it was used to produce this output with the command in the “Details” summary. As you can see, it created a “Hide Details” block with a “Preformatted text” (code) block inside it, and the “Summary” of the former will always be `<command> <all> <arguments>`.

    For transparency, it also echos the raw command output to the terminal (stderr); just as an additional safety measure, so one can check if there’s any sensitive info in it.
    CAUTION: Do not mark, select and/or copy that text manually, otherwise you will undo all the hard work of cmd2bb.

    #!/bin/sh -e
    
    if [ "$XDG_SESSION_TYPE" = wayland ]; then
    	cb_copy () { wl-copy; }
    else
    	cb_copy () { xsel -b; }
    fi
    
    pr_cmd () { # restore quotes around args with spaces
    	for arg in "$@"; do
    		read -r _ rem <<-EOT
    			$arg
    		EOT
    		q=${rem:+\'}
    		printf '%s' "$q$arg$q"
    		i=$((i+1))
    		[ $i -lt $# ] && printf ' '
    	done
    	unset arg i rem q
    }
    
    cmd=$(pr_cmd "$@")
    
    cb_copy <<EOBB
    [details=$cmd]
    [code]
    $("$@" 2>&1 | tee /dev/stderr)
    [/code]
    [/details]
    EOBB
    
  3. Open a text editor, e.g. sudo nano /usr/local/bin/cmd2bb
  4. Paste the code there, save the file (requires root privileges; note the `sudo` in step 2) and exit the editor.
  5. Make file executable: sudo chmod +x /usr/local/bin/cmd2bb
  6. Done.

Demo

My first command, when something goes wrong, is always journalctl --no-hostname --boot --priority=err. So now we can just run cmd2bb journalctl --no-hostname --boot --priority=err, which puts the output into the clipboard, go back to Discourse and paste it on a new line:

journalctl --no-hostname --boot --priority=err
<redacted>
Apr 07 09:19:12 sudo[724142]: pam_unix(sudo:auth): conversation failed
Apr 07 09:19:12 sudo[724142]: pam_unix(sudo:auth): auth could not identify password for [peter]

It even works with pipelines; just run them as command argument of sh:

sh -c 'shellcheck cmd2bb && echo PASSED | cat'
PASSED

:smiling_face_with_sunglasses:


For reference, here is the discussion thread which motivated this.

2 Likes

Why not keep it simple? Here in discourse - why not instruct users to open a new line, press the button </> and enter/paste data in the created field?

(see Helpers for the helpers - #7 by g-schick)

* * * KISS - Keep It Short and Simple * * *

3 Likes

I find that neither short, nor simple. :wink:

Also, as I’ve pointed out in the referenced discussion, it’s also important that code sections be collapsible, and that becomes tedious very quickly, so nobody will do it manually. On my screen with my settings, they can span the whole height, losing me all surrounding conversational context. So there should always be a way to make them go away. I’ll take the hit for this being redundant with low line count output.

As a rule, inline code blocks should be collapsible. If they are just one line, the collapsed state will also just be one line. I am currently weighing a -D (omit details wrapper) option. But I’d really rather not do the whole getopts dance just for this pseudo-regression; KISS, BTW. :wink:

Plus, there should never be a single-line code block that is not a command itself, because the command that produced the output needs to precede it, hence the “Summary” doing just that. That lends itself rather nicely as a filter, if I may say so myself. “Oh, I’ve read that one already, so I won’t even open it this time around.” Or, “where was the journalctl output again? Ah that’s where.”

For me hiding everything in detail sections would be tedious because I prefer using the keyboard to scroll over a topic. If every preformatted section is collapsed I’m forced to use the mouse or other additional actions to open each section to have a look at it.
Just because you, @peterwhite23 prefer everything totally collapsed doesn’t mean everybody else wants it like that …

That’s a UI issue with Discourse in particular and with the whole GUI interface approach in general. I am using the Tridactyl addon with Firefox and can just hit f to follow links; and the open action for collapsed Details is just another link.
Also, fix things in the right place. This sounds like something that can be configured in some Discourse preference; i.e. “un-collapse all details” by default, or whatever. In case it can’t, it ought to be.
And you can always jump between links with Tab in plain old Firefox, or any browser, for that matter.

That goes both ways. :wink: My approach gives the recipient at least the option to make code go away again after having been read. That’s impossible when the author of the message hasn’t thought to make it so.
Plus, those logs and whatnot are literally just details, which shouldn’t take center stage but be available if need be.

I’ve kept gnawing on this and have since found that the HTML <details> element has the open attribute, but I cannot even use it with BBCode. And it gets rather messy to switch to pure HTML, because then it’s no longer transparent in the RT (rich text) editor, which may put off the very novice users.

Also, the HTML is still not 100% passed through, because aside from open all other attributes are discarded by the HTML “cook”. I’d really like to leverage the name attribute, because that allows “accordions”, i.e. only one <details> block of the same name can be open at a time; opening one, closes the other. Combined with the open attribute, that allows the first code block to be open by default and one can easily jump between them with Tab.
Long story short, I don’t think it is feasible to do this, given the way Discourse “cooks” HTML. But there are browser extensions, which can manipulate attributes of arbitrary HTML elements, so you might be able to have that functionality by using one of those.

Did you see this post? I think the user did quite well in formatting within discourse.


On the other hand there is this post - please have a look at the unedited post too. It looks like users need to understand formatting within discourse anyway. Despite your script.


By the way please read Support and Help posting guide carefully. In section When asking for technical support points 4 and 5 read like use ‘preformatted text’ for long output OR as another option ‘hide details’. In section When answering technical support issues point 7 again have a close look: ‘(…) preformatted text icon OR use the “spoiler” option (…)’.

As stated earlier I’d prefer ‘preformatted text’ format because it can be read (at least some part of it) using solely spacebar without needing mouse or additional key commands.
With your script every short output would get hidden within ‘hide details’ else you need to instruct users for short outputs to use formatting within discourse.

Why not just teach users to use discourse formatting within discourse?


Please stop to instruct users to use both - it doesn’t comply with ‘Support and Help posting guide’. (for example this post)

1 Like

Not quite; it’s a happy accident because the lines aren’t longer. If you look closely, you’ll see that it’s a regular “Details” element, with an unedited literal “Summary” – one of my points: laziness. And there is no “Code” block inside, so long lines wrap, which is just awful to read, for starters, and no clipboard icon to copy the whole thing. The latter is a big plus; if need be, I can just click that and paste it to an editor or view it in a pager, locally. Try that with a wall of text spanning multiple pages, and no button.

As a matter of fact, I was there, when it happened and I’ve spent the better part of night before last to try and debug this with the user. He did use my script for that. But what nobody could expect was that his Vivaldi browser ate the newlines.

The “despite” is a bit premature. So far I only know of two users who have actually used it. And one of them had a buggy or mis-configured browser.
The actual point of the script is to take as much of the tedium involved in good formatting out of the users’ hands. Just browse the “Help and Support” category, just last week; you won’t have to look very far to find walls of line-wrapped console output somebody asked for.

That’s no XOR. :wink: Seriously, if that is the actual intent, it’s a glaring bug in my book, because long log sections, that aren’t rendered as [code], don’t get any more readable by being wrapped in a “Details” element. They only get easier to ignore that way; I posit that’s what most annoyed readers will do. And the real fun with long log lines starts when they span more than just two lines.

And I have tried to show you an alternative to have your way right now.

Much simpler than that: everybody is free not to use my script to begin with, and one can always edit the code before hitting the “Reply” button.

Because they aren’t here for Discourse but for seeking help. That’s why there are so many badly formatted posts. It’s tiresome to read them and it is tiresome to keep begging, almost, for proper formatting and being ignored or seeing them fail.

I disagree with your interpretation of that list. It’s also just a guideline and not some kind of rule book. Look at it this way – start by looking again at the thread title – many people who might be able to help may simply choose to ignore badly formatted posts. And you’ll certainly never hear from them.

This is to help both sides.

One of two! If your script depends that much on local setting on user side it will always be problematic and error prone. And it took you "(…) the better part of night (…) to debug this with the user (…). Are you prepared to do this for every user? And I guess you did this debugging in private messages - and that’s no nagging? Because the user didn’t need this at all …

That happened without my script as well; it just took us a while to realize that. It’s an issue with Vivaldi. So asking such a user to do it manually will yield the exact same result.

I kindly asked, if he was willing to be my guinea pig and he said yes.

This problem won’t exist in my proposed upload of terminal-output-files with a simple redirect in terminal because all white space characters would be processed by the server on importing content.


No. it’s not.

Why do you insist to apply ‘hide details’? Although I don´t think your script is necessary I would be fine with it if you just drop the ‘hide details’ formatting and stick with ‘preformatted text’. You may insert a heading or bold text (executed command?) before the preformatted text instead of the ‘summary’.

1 Like

Tried it for the first time. But a simple instruction could be:

insert your output between [code] and [/code] … it shows all output.

insert your output between [details="my output"] and [/details] … output is hidden.
Click on the triangle to expand the output.

You mean a simple instruction like the one in post #2:


That’s not correct. If the output spans multiple lines ‘preformatted text’ (same as ‘code’ tags) adds scrolling automatically (‘hide details’ doesn’t do that!). Thus using ‘preformatted text’ is the better option and doesn’t need to be enclosed in ‘hide details’ section at all (at least for support requests).

Not sure I understand the issue.

using </>

1
2
3

using [code]

1
2
3

using [details="bla"]

bla

1
2
3

Apologies since you mentioned </> in post #2.

Numbers 1 to 100

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
Numbers 1 to 100

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


Sorry for the lack of precision. If there are a lot of lines ‘preformatted text’ will add scrolling automatically.
And if there are not that many lines all lines will be displayed and can be read without needing any additional action.

2 Likes

Correct.

And you can also open the selection by clicking on the fullscreen pointer next to copy on the top right of the code box.

Personally, I think Hide Details only really makes sense for large blocks of non-code text (e.g. an explanation about something or perhaps multiple items like here).

1 Like

I don’t think any more explaining is required. My little text module, which I use when asking for logs the first time, provides a condensed version of that set of instructions, points to the Posting Guide and, only after opening the “details” element, which are clearly marked “Optional”, will it direct here, if one doesn’t want to do that manually:

But code blocks can span the whole screen height, which obstructs the rest of the conversation from view. As is shown in the OP and reiterated further down and in the linked discussion thread, it doesn’t have to be mutually exclusive. Logs and other sample output are (important) details. :wink:

If I got @pavlos post right it’s the proposal for a simple and short instruction on how to post.
No need to read lengthy instructions, install (additional, probably not necessary) packages and scripts before being able to submit a simple support request …
As of the thread title ‘Helping the Helpers: Providing well-formatted Command Output’ doesn’t need a script. It would be helpful if you start this thread with a short instruction like the one provided by @pavlos how to format properly. After this you may provide your optional script.
(Because you do not mention the manual formatting procedure it may look like your script is mandatory …)


I just tried on laptop, phone, … with above maximized ‘preformatted text’ section. Only on my phone in landscape orientation it spans the whole screen …

What screen are you using? What zoom level?

You mean like this very post you saw fit to criticize?

I am not even insisting on the hide details, but the </> blocks aren’t optional, whatsoever.

Laptop, zoom level 150%, because I don’t want to waste even more horizontal space; Discourse needlessly narrows the canvas to one third of screen width.
Anyway, even if they don’t span the whole screen for everybody, code blocks take up to 28 lines, which is always more than half the screen.