šŸŽ© Pretty Columns in :put

As it turns out, using just a \r without it Windows compatriat \n will, well, return cursor to start on line, without, well, adding a newline. This may seem obvious… however, I never thought ā€œcarriage returnā€ was literal.

@Druvis had it one of his video I re-watched since I’d recommended it another thread. He used \r\t\t\t in a :put to show an array-of-arrays to organize columns. You have to pause to catch the subtlety.

This may be esoteric to most, but avoids the [/terminal/cuu] (ā€œcursor move one line upā€) to do similar, which is more complex scheme to do columns since you have :put each cell, the use /terminal/cuu. Nor, calculating the number of tabs needed to include in [carefully] crafted string.

Anyway here is an example:

:for i from=0 to=10 do={ 
     :local rnd do={:return [:rndstr length=[:rndnum from=5 to=20]]}
     :local k "key-$[$rnd]"
     :local v "value $[$rnd]"
     :local m "#metadata?$[$rnd]"
     :put " $k \r\t\t\t $v \r\t\t\t\t\t\t $m" 
}
 key-ofROyWb982Uha7rbkAA value 6tONhZrm4uug      #metadata?HZG6EyRzrdc
 key-tQUsw5xyqP54eb2GqTV value hy525M            #metadata?aWMVnISf8gPPBNjvxZb
 key-fHbrkZ4             value 8sby0Tc           #metadata?eUXMPoGRM
 key-P9Ls5ldiRvjJwVpaGv  value 3O1kBNfO1Cl6APPYe #metadata?dAoedoPR3
 key-DeCtksUVDDWEc       value frDDy08Kx         #metadata?SzrfzPpkd98Mt
 key-7pkLfVq5CJ          value fiejKZ2AAh        #metadata?v9Wn4
 key-3jrae5HfHLtmV       value FkFg51MLfrQBbfxJ  #metadata?jBNqcXp6E9LJ
 key-SPr0bPQh            value APLo12Nt9e        #metadata?kfbmVZZEERET
 key-VQl4hORKpObCH       value Nvsd3cG4          #metadata?7DaB7
 key-F7uW86HBsJQIGWO3    value twdkfht9dPmq      #metadata?LAdEnHUzar
 key-o0lRm8kxNft         value L8Jt0Kodh8EVy     #metadata?l3wxNXnmJ4

With the important line being:

:put " $k \r\t\t\t $v \r\t\t\t\t\t\t $m" 

And that… \t == 8 characters forward

So the first \r\t\t\t means go to beginning of line, and move 3 * 8 (24) characters forward (without overriding text, apparently). And second group of \r\t\t\t\t\t\t start the third column at 24 (\t\t\t) for 1st column + another 24 \t\t\t allowed for 2nd column. With \r helping to keep the math simple:
desired output column # / 8 === number of \t tabs needed
With :put internally adding the \n for you.

I suppose this how the print command prints it’s columns too - just never thought about it.

1 Like

Well, in the good ol’days of typewriters you would use the line space lever, pushing It towards right until the carriage would reach the end position, making a carriage return and then the gear and ratchet would engage making the new line by rotating the drum.

But you could push the carriage rightwards pushing the left knob, thus only issuing a carriage return.

And, with carriage already on the right, you could insert blank lines by pushing on the line space lever.

In this the CR+LF DOS (and Windows) use are more traditional than the Unix/Linux lonely LF.

But I would have never thought that a Linux based OS terminal would ā€œrespectā€ the CR on itself, good find. :smile:

And on older Macs (OS <= 9) \r was used as line breaks.

Furthermore ā€˜\r’ (ASCII 13) is the code that the Enter key on the keyboard produces, that includes PC keyboards. And it’s still used when comparing ā€œkey pressesā€.

Yup. Normally the different line endings are a PITA. Finally some useful case, albeit a 50+ year old one.

You can see the alternative approach to columns here:

I may write a wrapper function to take an array an output it reasonably as a table.

2 Likes

The alternative (historically) for outputting nicely looking tables from (say) batch used to be padding each item up to a given fixed length with spaces, which - using a subroutine - wasn’t that bad after all.

I made a few tests and we can evolve from the ā€œ8 characters forward step or nothingā€.

\b (backspace) is also accepted.

So:
\r\t means ā€œposition the cursor at the beginning of line, then jump forward 8 charactersā€, or ā€œto column 9ā€

and

\r\t\b means "position the cursor at the beginning of the line, then jump forward 8 characters AND take one back (to honour the God of ASCII), or ā€œto column 8ā€

\r\t\b\b is then ā€œto column 7ā€

and so on …

Is there a way to get that code block and save it to a file while maintaining that structure?
i’ve tried mucking around with it but the /file set seems to handle the \r\t differently to the cli.

So this chunk of code pumped in to the cli.

{
:local rnd do={:return [:rndstr length=[:rndnum from=5 to=20]]}
:local k "key-$[$rnd]"
:local v "value $[$rnd]"
:local m "#metadata?$[$rnd]"
:put " $k \r\t\t\t $v \r\t\t\t\t\t\t $m"
/file add name=script.txt contents= "$k \r\t\t\t $v \r\t\t\t\t\t\t $m"
}

Gives me this output on the cli

key-9QWSjxuWjLRyrygXGcG value lT0UbOvnALLhLvlN #metadata?zLTRU4CvOq

But when I extract the script.txt file and open it in Notepad++ I see this.

UPDATED

Now I see. You're looking at the output. That's right. Unless you copy the text shown at CLI (which would have "resolved" the tabs by then). But in a text file, that what actually output.

The reason "columns" come from that RouterOS CLI will read the \t \r things, to control a cursor, but there no terminal to "intercept" those when writing a file, it just the raw stream (no cursor to control).

For files, you should use :serialize to=dsv delimiter="\t" <array-variable> file=myfile.txt file to output columns.

(before the edit)

No, I not use Notepad++ :wink:

You can not save terminal VISUAL results inside a text file...
and pretend to see inside notepad++ or other editor the VISUAL results of the terminal...

I do not know if some program that open text files can simulate the terminal results.

The doctor is on duty quick - my bad... I always forgot, but some other "regular" here always uses Notepad++.

The issue is output of the script will not have column when in file, not Notepad++.

1 Like

:sweat_smile:

Sorry, I should have been more accurate in saying that any word editing program doesn’t handle the ā€˜columns’ that we create here in the CLI.

I think I understand why, the manual says it for creating escape sequences within the string. So when a Mikrotik device handles that, it does those escape sequences, as we programmed, but when a foreign program like Notepad++ see’s it, it just tries it’s best and ends up doing something different.

Anyhow, I’ll give the serialise command a go and see what I can make out of it.

Issue here is that when printing to console \r control characters behaves as actual carriage return (returns cursor at beginning of line) while text editors represents it as new line (Mac new line format). If text editor would show characters same as printed in console in some cases it will not display all characters and it will lose its purpose, eg. :put "a\rb" - it prints only b becase a is overwritten when cursor returns.

To get exact file prevew with fixed tabbed column spacing you need some text viewer that will treat \r same as console or use terminal to print file content.

In an environment where you often want to print neat columns with monospace fonts, you should have some tool to do that for you. E.g. in the Unix/Linux system, which is traditionally built from such tools, there is ā€œcolumnā€ which you can feed a number of lines with TAB-separated fields (or you can use another separator character) and it will convert them to lines with the proper number of spaces to line up everything. More or less like a HTML table does.

But in RouterOS scripts I just use the crude method of first adding a sufficient number of spaces to the end of each value and then use [:pick $value 0 8] for example to get a constant width.