New command in RouterOs 7

Well, that’s easy. In terms of script-specific commands (e.g. not tied to a protocol/service), the only new ones (which are doc’d in link above already)

[:timestamp] - related to the :tonsec (and shown above), returns a “time” type contain the elapsed time from epoch (Jan 1, 1970), internally time is stored in nanoseconds.

[:rndnum from=0 to=1] - returns random “num” type (integer) using to= and from=

[:rndstr length=1] - returns a random “str” of length=

There is also…

/console/inspect - this is an “easter egg” – but I have an partial example of usage here:
http://forum.mikrotik.com/t/feature-request-openapi-for-rest-api/149360/1

/task, which is like UNIX “bg”, “fg”, and “jobs” but I haven’t used it.

[:retry] is also new I believe.

:retry delay=1s max=3 on-error={:put "got an error"} command={:put [/system/identity/get name]}
# Mikrotik
:retry delay=1s max=3 on-error={:put "I give up!"} command={:put "trying..."; :error "cause error"}                                
# trying...
# trying...
# trying...
# I give up!

Not directly scripting-specific, but “as-value” is new option in V7 for “/tool/snmp-get”, which can get values from SNMP OID into a script without parsing required in V6:

{
   :local interfaceOneName [/tool/snmp-get oid=.1.3.6.1.2.1.2.2.1.2.1 address=127.0.0.1 community=public as-value] 
   :put $interfaceOneName
   :put ($interfaceOneName->"value")
}
# oid=1.3.6.1.2.1.2.2.1.2.1;type=octet-string;value=ether1
# ether1

note: requires /ip/snmp being enabled, and likely using different community name for better security

Similarly [:execute] now has “as-string” as option, which make it synchronous (e.g. waits for script to finished BEFORE return with new “as-string”)

So, what we have today (to version 7.12):

:timestamp
:rndnum from=[num] to=[num]
:retry command={abc} delay=1 max=2 on-error={}
:rndstr from=[str] length=[num]
:convert from=[arg] to=[arg] transform=
:jobname
:tonsec
:terminal/ask preinput= prompt=
:console/inspect as-value request= path=
:task

:execute … as-string
*) console - improved multi-argument property parsing into array;
/tool /snmp-get … as-value

The new RB has a lot of RAM now, and Microtik developers have actively begun to develop new features, including in scripts. The main thing is not to overdo it and document the developments. Surely there are hidden commands and command parameters. I wonder how Amm0 and Rextended learn new things in Roc7? Maybe someone uses reverse engineering? Or through :console/inspect ?

I’ll digress a little from the main topic of the topic and give examples of the possibility of entering a line in the Terminal:

To enter a line from the Terminal, of course, you can write a small script using :terminal inkey like this:

:local EnterString do={
     :local cont; :local string
        :while ($cont!=13) do={
          :if ([:len $string]<254) do={
             :local key ([:terminal inkey])
                :if ($key!=13) do={
                     :local char [[:parse "(\"\\$[:pick "0123456789ABCDEF" (($key >> 4) & 0xF)]$[:pick "0123456789ABCDEF" ($key & 0xF)]\")"]]
             :set string ("$string"."$char")}
             :set cont $key
         }
      }
:return $string}

This small function allows you to enter a string of up to 254 characters character by character. In this example, the input stops if the user presses the “Enter” key (Enter key code=$0D (13). Of course, character-by-character input allows you to use any other restrictions for the end of the input (for example, another ending character or the number of characters entered), which allows you to configure the input most flexibly.
It can be supplemented with different buns with instant verification of the entered characters, limit the length of the generated string, etc…


But, if you need it easier and faster, you can use such a feature: http://forum.mikrotik.com/t/script-input-from-console-works/120030/1

:local input do={:put $1; :return;}
:local login [$input "Enter login:"]
:local password [$input "Enter password:"]
:put "Login is [$login] and password is [$password]"

The trick is that it is empty: return from the Terminal always prompts you to enter a value. The end of the input is necessarily the “Enter” key.The only inconvenience will be the output of the word “value:” as an invitation before entering, but if it’s not annoying, then everything works fine.
It is convenient to use from interactive scripts configuration settings, etc…


Another possibility has appeared in the Router OS 7.11 - the use of :terminal ask. This new command is devoid of the inconvenience associated with the output of the prompt to enter the value :value. The end of the input is also necessarily the “Enter” key.

:global Answer [:terminal/ask "Do you agree to use Router OS 7?"]
:put $Answer

Well, or something like that (for example):

{
:global Answer []
:while ($Answer!="yes") do={
:set Answer [:terminal/ask "Do you agree to use Router OS 7?"]
}
}

You can also specify any input prompt if you use the “preinput” parameter:

:global userinput [/terminal/ask preinput="preinput>" prompt="Some text that in prompt"]

I wrote a short article for the Russian-speaking audience on the new commands of the scripting language in the Router OS based on the materials of this topic. I hope I didn’t mix anything up. I also thanked our respected gurus Rextended and Amm0 in the article for their help, explanations and examples of scripts.

https://habr.com/ru/articles/759564/

Thanks :wink:

Hi @Amm0, Is it possible to dump the command list (/console/inspect) in a file for future reference?

Thanks.

Let’s not forget there is a 4K file limit, so while script can get all commands to memory. Writing it out gets trickier…
http://forum.mikrotik.com/t/the-maximum-size-of-a-read-written-file/167507/1

I’ll start that script, and mull how to get it disk somehow. It takes a few hours to run actually.

So, to keep it short, if I just want to get information about a specific command, for example “/ip/firewall”, it would be something like this?

:put [/console/inspect as-value request=syntax path="/ip/firewall/"]

I’ve tried it and it doesn’t work
Can you give me an example please?

Thanks

Reflections on /console/inspect

If you start at request= you get the gist of what’s possible:

/console/inspect request=      
child     completion     error     highlight     self     syntax

In request=syntax, path= needs to be set. So the main trick is path= is CLI list… The logic is “metadata”/information about commands, not actually commands, so you need commas in path= as that’s how the CLI takes a list.

So to get the options for /ip/address, it looks like:

/console/inspect request=syntax path=ip,address

Columns: TYPE, SYMBOL, SYMBOL-TYPE, NESTED, NONORM, TEXT
TYPE    SYMBOL   SYMBOL-TYPE  N  NON  TEXT                                                                    
syntax           collection   0  yes                                                                          
syntax  ..       explanation  1  no   go up to ip                                                             
syntax  add      explanation  1  no   Create a new item                                                       
syntax  comment  explanation  1  no   Set comment for items                                                   
syntax  disable  explanation  1  no   Disable items                                                           
syntax  edit     explanation  1  no                                                                           
syntax  enable   explanation  1  no   Enable items                                                            
syntax  export   explanation  1  no   Print or save an export script that can be used to restore configuration
syntax  find     explanation  1  no   Find items by value                                                     
syntax  get      explanation  1  no   Gets value of item's property                                           
syntax  print    explanation  1  no   Print values of item properties                                         
syntax  remove   explanation  1  no   Remove item                                                             
syntax  reset    explanation  1  no                                                                           
syntax  set      explanation  1  no   Change item properties

And you can the properties by adding a “/set” to the path (again using commas):

/console/inspect request=syntax path=ip,address,add

Columns: TYPE, SYMBOL, SYMBOL-TYPE, NESTED, NONORM, TEXT
TYPE    SYMBOL     SYMBOL-TYPE  NESTED  NONORM  TEXT                                   
syntax             collection        0  yes                                            
syntax  address    explanation       1  no      Local IP address                       
syntax  broadcast  explanation       1  no      Broadcast address                      
syntax  comment    explanation       1  no      Short description of the item          
syntax  copy-from  explanation       1  no      Item number                            
syntax  disabled   explanation       1  no      Defines whether item is ignored or used
syntax  interface  explanation       1  no      Interface name                         
syntax  netmask    explanation       1  no      Network mask                           
syntax  network    explanation       1  no      Network prefix



There are few more request= things too. The main one is request=child – this one is useful to know what the “command tree” looks like – that the one used in the larger script to export an abstractly, an AST (“abstract syntax tree”). Again it use the path= with CLI list formatting…

So with no path=, it’s the top of the tree. If the “type” is “child”, it means there might be children in AST request=child tree, and you use “name” in the another call to /console/inspect with that child name appended in “path=”.

/console/inspect request=child           
         
Columns: TYPE, NAME, NODE-TYPE
TYPE   NAME           NODE-TYPE
self   root           path     
child  beep           cmd      
child  blink          cmd      
child  certificate    dir      
child  console        dir      
child  container      dir      
child  convert        cmd      
child  delay          cmd      
child  disk           dir      
child  do             cmd      
child  dude           dir      
child  environment    dir      
child  error          cmd      
child  execute        cmd      
child  file           path     
child  find           cmd      
child  for            cmd      
child  foreach        cmd      
child  global         cmd      
child  if             cmd      
child  import         cmd      
child  interface      path



/console/inspect request=child path=ip,address 

Columns: TYPE, NAME, NODE-TYPE
TYPE   NAME     NODE-TYPE
self   address  dir      
child  add      cmd      
child  comment  cmd      
child  disable  cmd      
child  edit     cmd      
child  enable   cmd      
child  export   cmd      
child  find     cmd      
child  get      cmd      
child  print    cmd      
child  remove   cmd      
child  reset    cmd      
child  set      cmd



/console/inspect request=child path=ip,address,set

Columns: TYPE, NAME, NODE-TYPE
TYPE   NAME       NODE-TYPE
self   set        cmd      
child  address    arg      
child  broadcast  arg      
child  comment    arg      
child  disabled   arg      
child  interface  arg      
child  netmask    arg      
child  network    arg      
child  numbers    arg

request=self but largely same request=child…

/console/inspect request=self path=ip

Columns: TYPE, NAME, NODE-TYPE
TYPE   NAME          NODE-TYPE
self   ip            path     
child  address       dir      
child  arp           dir      
child  cloud         dir      
child  dhcp-client   dir      
child  dhcp-relay    dir      
child  dhcp-server   dir      
child  dns           dir      
child  firewall      dir      
child  hotspot       dir      
child  ipsec         dir      
child  kid-control   dir      
child  neighbor      dir      
child  packing       dir      
child  pool          dir      
child  proxy         dir      
child  route         dir      
child  service       dir      
child  settings      dir      
child  smb           dir      
child  socks         dir      
child  ssh           dir      
child  tftp          dir      
child  traffic-flow  dir      
child  upnp          dir      
child  vrf           dir      
child  export        cmd



Another one is request=completion. This using “input=” as a proxy for what someone would type at the command line. So if we want to know what options /console/inspect ITSELF offered for the request=… the following get same list as top of this post:


/console/inspect request=completion input="/console/inspect request="

Columns: TYPE, COMPLETION, STYLE, OFFSET, PREFERENCE, SHOW, TEXT
TYPE        COMPLETION  STYLE        OFFSET  PREFERENCE  SHOW  TEXT                         
completion              none             25  -1          no    whitespace                   
completion              none             25  64          no                                 
completion  [           syntax-meta      25  75          no    start of command substitution
completion  (           syntax-meta      25  75          no    start of expression          
completion  $           syntax-meta      25  75          no    substitution                 
completion  "           syntax-meta      25  75          no    start of quoted string       
completion  self        none             25  96          yes                                
completion  child       none             25  96          yes                                
completion  completion  none             25  96          yes                                
completion  highlight   none             25  96          yes                                
completion  syntax      none             25  96          yes                                
completion  error       none             25  96          yes

Some more examples of request=completion …


/console/inspect request=completion input="/ip/add" 

Columns: TYPE, COMPLETION, STYLE, OFFSET, PREFERENCE, SHOW, TEXT
TYPE        COMPLETION  STYLE        OFFSET  PREFERENCE  SHOW  TEXT                    
completion  address     dir               4  96          yes   Address management      
completion  /           dir               7  95          yes   top of command hierarchy
completion              none              7  -1          no    whitespace              
completion  {           syntax-meta       7  40          no    start of command block  
completion  ;           syntax-meta       7  40          no    end of command



/console/inspect request=completion input="/ip/addr/set "
Columns: TYPE, COMPLETION, STYLE, OFFSET, PREFERENCE, SHOW, TEXT
TYPE        COMPLETION  STYLE        OFFSET  PREFERENCE  SHOW  TEXT                                   
completion  !           none             13  80          no    whitespace                             
completion  address     arg              13  96          yes   Local IP address                       
completion  broadcast   arg              13  95          yes   Broadcast address                      
completion  comment     arg              13  96          yes   Short description of the item          
completion  disabled    arg              13  96          yes   Defines whether item is ignored or used
completion  interface   arg              13  96          yes   Interface name                         
completion  netmask     arg              13  95          yes   Network mask                           
completion  network     arg              13  96          yes   Network prefix                         
completion  numbers     arg              13  96          yes   List of item numbers                   
completion              none             13  64          no                                           
completion  [           syntax-meta      13  75          no    start of command substitution          
completion  (           syntax-meta      13  75          no    start of expression                    
completion  $           syntax-meta      13  75          no    substitution                           
completion  "           syntax-meta      13  75          no    start of quoted string                 
completion  *           none             13  -1          no    id prefix                              
completion  <number>    none             13  -1          no    decimal number



/console/inspect request=completion input="set" path=ip,address

Columns: TYPE, COMPLETION, STYLE, OFFSET, PREFERENCE, SHOW, TEXT
TYPE        COMPLETION  STYLE        OFFSET  PREFERENCE  SHOW  TEXT                  
completion  set         cmd               0          96  yes   Change item properties
completion              none              3          80  no    whitespace            
completion  ;           syntax-meta       3          40  no    end of command

/console/inspect request=completion still support a path=, in additional the require input=. path= reflects what “directory” the CLI is at (e.g. similar to typing /ip/address and then doing “set” in a new line). So you can see input is a space " ", which is kinda weird, but your looking for command completion here…

/console/inspect request=completion input=" " path=ip,address,set   

Columns: TYPE, COMPLETION, STYLE, OFFSET, PREFERENCE, SHOW, TEXT
TYPE        COMPLETION  STYLE        OFFSET  PREFERENCE  SHOW  TEXT                                   
completion  !           none              1  80          no    whitespace                             
completion  address     arg               1  96          yes   Local IP address                       
completion  broadcast   arg               1  95          yes   Broadcast address                      
completion  comment     arg               1  96          yes   Short description of the item          
completion  disabled    arg               1  96          yes   Defines whether item is ignored or used
completion  interface   arg               1  96          yes   Interface name                         
completion  netmask     arg               1  95          yes   Network mask                           
completion  network     arg               1  96          yes   Network prefix                         
completion  numbers     arg               1  96          yes   List of item numbers                   
completion              none              1  64          no                                           
completion  [           syntax-meta       1  75          no    start of command substitution          
completion  (           syntax-meta       1  75          no    start of expression                    
completion  $           syntax-meta       1  75          no    substitution                           
completion  "           syntax-meta       1  75          no    start of quoted string                 
completion  *           none              1  -1          no    id prefix                              
completion  <number>    none              1  -1          no    decimal number

I never really messed with request=highlight but gets the syntax formatting using similar path= and input= scheme as rest… And request=error – I don’t know how it works.

All the /console/inspect things support an “as-value” to store array with data to a variable, but I skipped that since it easier to cut-and-paste without it here.

A great masterclass!
Thank you very much for helping me to understand it.

BR.

Some useful to compare news on different versions…

:global cmdtree do={
:global cmdtree ; # declared again for the recursive call
:local start [:tostr $1]
:local qpath “”
:local temp “”
:local spac “”
:local arrPath [:toarray “”]
:local arrDir [:toarray “”]
:local arrCmd [:toarray “”]
:local arrArg [:toarray “”]
:local arrUnknw [:toarray “”]
:local argreq [:toarray “”]
:local currType “”
:local currName “”
:local currPrfx “”

:if ($start != "") do={
    :for pos from=0 to=([:len $start] - 1) do={
        :set temp [:pick $start $pos ($pos + 1)]
        :if ($temp = "/") do={:set temp ","}
        :set qpath "$qpath$temp"
        :set spac "$spac "
    }
}

:local request  [/console/inspect request=child path=$qpath as-value]
:foreach item in=$request do={
    :if (($item->"type") = "self") do={
        :set currPrfx ($item->"name")
    } else={
        :set currType ($item->"node-type")
        :set currName ($item->"name")
        :if ($currType = "path") do={
            :set arrPath ($arrPath,$currName)
        } else={
            :if ($currType = "dir") do={
                :set arrDir ($arrDir,$currName)
            } else={
                :if ($currType = "cmd") do={
                    :set arrCmd ($arrCmd,$currName)
                } else={
                    :if ($currType = "arg") do={
                        :set arrArg ($arrArg,$currName)
                    } else={
                        :set arrUnknw ($arrUnknw,"$currType = $currName")
                    }
                }
            }
        }
    }
}

:if ($start = "") do={:put "/" ; :set spac " "} else={:put $start}
:foreach item in=$arrCmd do={
    :put "$spac$item"
    :set argreq [/console/inspect request=child path="$qpath,$item" as-value]
    :if (($argreq->"type") != "self") do={
        :foreach par in=$argreq do={
            :if (($par->"type") != "self") do={
                :set currType ($par->"node-type")
                :set currName ($par->"name")
                :if ($currType = "arg") do={
                    :put "$spac(a) $currName"
                } else={
                    :put "$spac(UNKNOW) $currType = $currName"
                }
            }
        }
    } else={
        :put "$spac(no arg)"
    }
}
:foreach item in=$arrArg do={
    :put "(a) $item"
}
:foreach item in=$arrUnknw do={
    :put "$start/$item (UNKNOWN)"
}
:foreach item in=$arrPath do={
    $cmdtree ("$start/$item")
}
:foreach item in=$arrDir do={
    $cmdtree ("$start/$item")
}

}

$cmdtree
For save results…

:execute "\$cmdtree" file="all_cmd_$[/system resource get version]"

$cmdtree accept path as parameter, both on /ip/address and ip,address format

The file are too big for the forum, first 466 lines of all_cmd_7.13.1 (stable).txt
/
beep
(a) as-value
(a) frequency
(a) length
convert
(a) from
(a) from-scheme
(a) to
(a) to-scheme
(a) transform
(a) transform-scheme
(a) value
delay
(a) delay-time
deserialize
(a) from
(a) value
do
(a) command
(a) if
(a) on-error
(a) while
error
(a) message
execute
(a) as-string
(a) file
(a) script
find
(a) from
(a) in
(a) key
for
(a) counter
(a) do
(a) from
(a) step
(a) to
foreach
(a) counter
(a) do
(a) in
global
(a) do
(a) name
(a) value
grep
(a) after
(a) as-array
(a) before
(a) filename
(a) pattern
(a) script
if
(a) condition
(a) do
(a) else
import
(a) file-name
(a) from-line
(a) verbose
jobname
(no arg)
len
(a) value
local
(a) do
(a) name
(a) value
nothing
(no arg)
onerror
(a) do
(a) error
(a) in
parse
(a) value
password
(a) as-value
(a) confirm-new-password
(a) new-password
(a) old-password
pick
(a) begin
(a) counter
(a) end
ping
(a) address
(a) arp-ping
(a) as-value
(a) count
(a) do-not-fragment
(a) dscp
(a) interface
(a) interval
(a) size
(a) src-address
(a) ttl
(a) vrf
(a) without-paging
put
(a) message
quit
(no arg)
redo
(no arg)
resolve
(a) domain-name
(a) server
(a) server-port
retry
(a) command
(a) delay
(a) max
(a) on-error
return
(a) value
rndnum
(a) from
(a) to
rndstr
(a) from
(a) length
serialize
(a) to
(a) value
set
(a) do
(a) name
(a) value
time
(a) command
timestamp
(no arg)
toarray
(a) value
tobool
(a) value
toid
(a) value
toip
(a) value
toip6
(a) value
tonsec
(a) value
tonum
(a) value
tostr
(a) value
totime
(a) value
typeof
(a) value
undo
(no arg)
while
(a) condition
(a) do
export
(a) compact
(a) file
(a) hide-sensitive
(a) show-sensitive
(a) terse
(a) verbose
(a) where
/interface
blink
(a) numbers
comment
(a) comment
(a) numbers
disable
(a) numbers
edit
(a) number
(a) value-name
enable
(a) numbers
find
(a) where
get
(a) as-string
(a) as-string-value
(a) number
(a) value-name
monitor-traffic
(a) append
(a) as-value
(a) do
(a) duration
(a) file
(a) interface
(a) interval
(a) once
(a) without-paging
print
(a) append
(a) as-value
(a) brief
(a) count-only
(a) detail
(a) file
(a) follow
(a) follow-only
(a) follow-strict
(a) from
(a) interval
(a) oid
(a) proplist
(a) show-ids
(a) stats
(a) stats-detail
(a) terse
(a) value-list
(a) where
(a) without-paging
reset
(a) comment
(a) disabled
(a) l2mtu
(a) mtu
(a) name
(a) numbers
reset-counters
(a) numbers
set
(a) comment
(a) disabled
(a) l2mtu
(a) mtu
(a) name
(a) numbers
export
(a) compact
(a) file
(a) hide-sensitive
(a) show-sensitive
(a) terse
(a) verbose
(a) where
/interface/6to4
add
(a) clamp-tcp-mss
(a) comment
(a) copy-from
(a) disabled
(a) dont-fragment
(a) dscp
(a) ipsec-secret
(a) keepalive
(a) local-address
(a) mtu
(a) name
(a) remote-address
comment
(a) comment
(a) numbers
disable
(a) numbers
edit
(a) number
(a) value-name
enable
(a) numbers
export
(a) compact
(a) file
(a) hide-sensitive
(a) show-sensitive
(a) terse
(a) verbose
(a) where
find
(a) where
get
(a) as-string
(a) as-string-value
(a) number
(a) value-name
print
(a) append
(a) as-value
(a) brief
(a) count-only
(a) detail
(a) file
(a) follow
(a) follow-only
(a) follow-strict
(a) from
(a) interval
(a) proplist
(a) show-ids
(a) terse
(a) value-list
(a) where
(a) without-paging
remove
(a) numbers
reset
(a) clamp-tcp-mss
(a) comment
(a) disabled
(a) dont-fragment
(a) dscp
(a) ipsec-secret
(a) keepalive
(a) local-address
(a) mtu
(a) name
(a) numbers
(a) remote-address
set
(a) clamp-tcp-mss
(a) comment
(a) disabled
(a) dont-fragment
(a) dscp
(a) ipsec-secret
(a) keepalive
(a) local-address
(a) mtu
(a) name
(a) numbers
(a) remote-address
unset
(a) numbers
(a) value-name
/interface/bonding
add
(a) arp
(a) arp-interval
(a) arp-ip-targets
(a) arp-timeout
(a) comment
(a) copy-from
(a) disabled
(a) down-delay
(a) forced-mac-address
(a) lacp-rate
(a) lacp-user-key
(a) link-monitoring
(a) mii-interval
(a) min-links
(a) mlag-id
(a) mode
(a) mtu
(a) name
(a) primary
(a) slaves
(a) transmit-hash-policy
(a) up-delay
comment
(a) comment
(a) numbers
disable
(a) numbers
edit
(a) number
(a) value-name
enable
(a) numbers
export
(a) compact
(a) file
(a) hide-sensitive
(a) show-sensitive
(a) terse
(a) verbose
(a) where
find
(a) where
get
(a) as-string
(a) as-string-value
(a) number
(a) value-name
monitor
(a) append
(a) as-value
(a) do
(a) duration
(a) file
(a) interval
(a) numbers
(a) once
(a) without-paging
monitor-slaves
(a) as-value
(a) bond
(a) duration
(a) freeze-frame-interval
(a) once
(a) without-paging
print
(a) append
(a) as-value
(a) brief
(a) count-only
(a) detail
(a) file
(a) follow
(a) follow-only
(a) follow-strict
(a) from
(a) interval
(a) proplist
(a) show-ids
(a) terse
(a) value-list
(a) where
(a) without-paging
remove
(a) numbers
reset
(a) arp
(a) arp-interval
(a) arp-ip-targets
(a) arp-timeout
(a) comment
(a) disabled
(a) down-delay
(a) forced-mac-address
(a) lacp-rate
(a) lacp-user-key
(a) link-monitoring
(a) mii-interval
(a) min-links
(a) mlag-id
(a) mode
(a) mtu
(a) name
(a) numbers
(a) primary
(a) slaves
(a) transmit-hash-policy
(a) up-delay
set
(a) arp
(a) arp-interval
(a) arp-ip-targets
(a) arp-timeout
(a) comment
(a) disabled
(a) down-delay
(a) forced-mac-address
(a) lacp-rate
(a) lacp-user-key
(a) link-monitoring
(a) mii-interval
(a) min-links
(a) mlag-id
(a) mode
(a) mtu
(a) name
(a) numbers
(a) primary
(a) slaves
(a) transmit-hash-policy
(a) up-delay
unset
(a) numbers
(a) value-name

Does the entire command tree even fit in a 64k variable? What be interesting to see is the count of commands from various versions....

I have some JS code that generates a scheme for the REST API (REST API schema for Postman & more). I had use JavaScript to call /console/inspect via REST since the variable size limited generating the scheme in RouterOS script... But perhaps JUST commands and attributes alone fit, so I could avoid the JavaScript in my "REST schema generator" at some point.

The function was created to save a file, to be taken outside the routerboard and then compared between those of different installed versions/packages.

It takes little to modify it and use it to create a variable.
:global cmdtreeVar do={
:global cmdtreeVar ; # declared again for the recursive call
:local ret “”
:local start [:tostr $1]
:local qpath “”
:local temp “”
:local spac “”
:local arrPath [:toarray “”]
:local arrDir [:toarray “”]
:local arrCmd [:toarray “”]
:local arrArg [:toarray “”]
:local arrUnknw [:toarray “”]
:local argreq [:toarray “”]
:local currType “”
:local currName “”
:local currPrfx “”

:if ($start != "") do={
    :for pos from=0 to=([:len $start] - 1) do={
        :set temp [:pick $start $pos ($pos + 1)]
        :if ($temp = "/") do={:set temp ","}
        :set qpath "$qpath$temp"
        :set spac "$spac "
    }
}

:local request  [/console/inspect request=child path=$qpath as-value]
:foreach item in=$request do={
    :if (($item->"type") = "self") do={
        :set currPrfx ($item->"name")
    } else={
        :set currType ($item->"node-type")
        :set currName ($item->"name")
        :if ($currType = "path") do={
            :set arrPath ($arrPath,$currName)
        } else={
            :if ($currType = "dir") do={
                :set arrDir ($arrDir,$currName)
            } else={
                :if ($currType = "cmd") do={
                    :set arrCmd ($arrCmd,$currName)
                } else={
                    :if ($currType = "arg") do={
                        :set arrArg ($arrArg,$currName)
                    } else={
                        :set arrUnknw ($arrUnknw,"$currType = $currName")
                    }
                }
            }
        }
    }
}

:if ($start = "") do={:set ret ("$ret/\r\n") ; :set spac " "} else={:set ret ("$ret$start\r\n")}
:foreach item in=$arrCmd do={
    :set ret ("$ret$spac$item\r\n")
    :set argreq [/console/inspect request=child path="$qpath,$item" as-value]
    :if (($argreq->"type") != "self") do={
        :foreach par in=$argreq do={
            :if (($par->"type") != "self") do={
                :set currType ($par->"node-type")
                :set currName ($par->"name")
                :if ($currType = "arg") do={
                    :set ret ("$ret$spac(a) $currName\r\n")
                } else={
                    :set ret ("$ret$spac(UNKNOW) $currType = $currName\r\n")
                }
            }
        }
    } else={
        :set ret ("$ret$spac(no arg)\r\n")
    }
}
:foreach item in=$arrArg do={
    :set ret ("$ret(a) $item\r\n")
}
:foreach item in=$arrUnknw do={
    :set ret ("$ret$start/$item (UNKNOWN)\r\n")
}
:foreach item in=$arrPath do={
    :set ret ("$ret$[$cmdtreeVar ("$start/$item")]")
}
:foreach item in=$arrDir do={
    :set ret ("$ret$[$cmdtreeVar ("$start/$item")]")
}

:return $ret
}

:put [:len [$cmdtreeVar]]
$cmdtreeVar accept path as parameter, both on /ip/address and ip,address format

Output is 972.386 Bytes (RouterOS 7.13.1 with routeros + user-manager without any wireless/wifi packages)
More than “virtual” 64K limit.

I forgot:

Both $cmdtree and $cmdtreeVar accept path as parameter, both on /ip/address and ip,address format

FWIW, I already had a GitHub project that compiled the REST schema, and as part of that there is an “inspect.json” that get generates with output of /console/inspect. I recently automated it all at GitHub, and put a tiny web page that has downloadable form of the “command schema”:

https://tikoci.github.io/restraml

On the web page, I wrote a quick-and-dirty “diff tool” for output a recursive /console/inspect. So you can compare command difference in between various releases. Since it does this in the browser, it take may take a dozen seconds to show diffs.

And to also digress… There is a new [:convert from=byte-array] method in 7.15, I put a few examples here: http://forum.mikrotik.com/t/how-to-covert-int-to-hex-type-value-and-save-it-in-a-string/52654/1 – but it’s useful to the /termina/inkey discussed above…

For /terminal/inkey, there is an handy method, in 7.15, to get the actual string of the char pressed, so you don’t need to compare the ASCII int code. So if you run this code, and hit the letter “a”, you can see you get the actual “a” back:

:put [/terminal/inkey]                                                   
# 97
:put [:convert from=byte-array to=raw {[/terminal/inkey]}]
# a

You guys are amazing, for me its like reading chinese…incomprehensible.
Some day I need to go to California or Italy for a 2 week scripting camp. ( which would barely scratch the surface ).

:laughing: :sunglasses: