vipsi - the built-in words
Author: kio@little-bat.de
Keywords: vipsi shell script interpreter programming

# vipsi - shell and script language

## the built-in words

### instructions

#### new

    new [name [=value] | file text_value | dir text_value] [,…]

create variable, file or directory.
optionally assign initial value to variable.

#### del

    del [name | * | file text_value | dir text_value] [,…]

delete and forget variable, file or directory.
use the special argument * to delete all variables and functions of the current context, e.g. within a procedure body, local context or really all global variables.
del can also be used to delete individual items in lists.

e.g.: `del a,b[1],c.wert, file "trashfile"`

#### swap

    swap [variable,variable | file text_value,file text_value] [,…]

swap two list items or two files.
the indicated variables are entirely swapped in place, that is, including name and value. please note, that swap is intended for re-ordering list items, not for exchanging values of variables.
if two files are swapped, then the contets of these files are exchanged.

    vipsi> var a = { x=22, y=33, z=44 }
    vipsi> put a  { x=22, y=33, z=44 }
    vipsi> swap a.y,a.z
    vipsi> put a  { x=22, z=44, y=33 }
    vipsi>
    vipsi> var a = 22, b=33
    vipsi> put a,b  2233
    vipsi> swap a,b
    vipsi> put a,b  2233

#### var

    var identifier [=value] [,…]

Create variable if it does not already exist.
optionally assign initial value.

#### freeze

    freeze [text_var | file text_value]

compress text or file. undo compression with melt.
note: files must fit into ram twice.

e.g.: `var a="fuzzy";a#=a;a#=a;a#=a; freeze a; count a;`

#### melt

    melt [text_var | file text_value]

uncompress text or file which has been compressed with freeze.
note: files must fit into ram twice.

e.g.: `var a="fuzzy";a#=a;a#=a;a#=a; freeze a; melt a;`

#### put

    put [#num_value,] value [,…]

write data in text format.
default stream is stdout. stream may be changed with #num_value.
default text encoding is UTF-8 unicode.

    text:   write as is. character set and end-of-line conversion applied.
    number: number is written in readable decimal format; e.g. 22, 22.5, +123.456e-78.
    list:   enclosed in curly brackets; e.g.: { x=123, y=456, "anton", {} }.
    proc:   prints source (if available) or disassembly.

text output to a tty is colorized by vipsi to make it unique for stdin, stdout and stderr:
`this is text to stdout` and `this is text to stdin` and `this is text to stderr`.
the color and attributes are choosen to hopefully match the capabilities of your terminal and can be overridden by preferences in ~/.vipsi/shell.prefs:

    # e.g.: normal, black, dark blue, bright_red, bold blue,
    #       inverse, bold underline green
    color_put
    color_get       blue
    color_err       inverse red

#### log

    put [#num_value,] value [,…]

write data in text format.
default stream is stdout. except for that, 'log' works exactly like 'put'.

#### get

    get [#num_value,] variable [,…]

read data in text format. default stream is stdin. stream may be changed with #num_value. default text encoding is UTF-8 unicode. default timeout-style is 'blocking'. input stops at next end of line for each variable. reading from a tty (terminal) uses the line editor. input is colorized according to the settings for stdin.

#### edit

    edit [#num_value,] variable [,…]

edit (write and re-read) data in text format.
default stream is stdin. stream may be changed with #num_value.
default text encoding is UTF-8 unicode.
default is blocking.

edit finished with end of line (return) for each variable.
reading from a tty (terminal) uses the line editor. input is colorized according to the settings for stdin.
data presentation is the same as for 'put'.

#### getchar

    getchar [#num_value,] variable [,…]

read single character in text format.
default stream is stdin. stream may be changed with #num_value.
default text encoding is UTF-8 unicode.
default timeout is non-blocking. (version 0.8.3: not yet implemented!) returns empty string if no input available.
reads from tty (terminal) without echo.

#### write

    write [#num_value,] variable

write text in binary mode.
default stream is stdout. stream may be changed with #num_value.
no conversions applied. text is written 'as is'. all characters written are masked to fit into bytes! you may convert your data to the desired destination format using convert.

    vipsi>convert mytext to ucs_4
    vipsi>openout #9, "myfile.txt"
    vipsi>write #9, mytext
    vipsi>close #9

#### read

    read [#num_value,] variable

read text in binary mode.
default stream is stdin. stream may be changed with #num_value.
default is blocking.

reads from tty (terminal) without echo.
no conversion applied. text is read 'as is', every byte making a character.
destination text variable is filled with data from stream. on timeout, eof or error the text is truncated according to the number of bytes actually read.

    vipsi>openin #9, "myfile.txt"
    vipsi>read #9, mytext
    vipsi>close #9
    vipsi>convert mytext from ucs_4

#### ioctl

    ioctl [#num_value,] [identifier=value|variable=identifier]

Set stream settings or querry stream state

••• still under development•••

set only:

            ioctl flush|flushin|flushout

set/read:

            ioctl timeout = 0 (off)  or  number (seconds)
            ioctl text    = "utf-8"  or  "mac-roman"
            ioctl pos     = number         (file: read-write-pointer)
                            {row,col}      (tty:  cursor location)

read only:

            ioctl var = type               ("tty", "file", etc.)
            ioctl var = inavail            (bytes readable w/o blocking)
            ioctl var = outfree            (bytes writable w/o blocking)
            ioctl var = error              (0=ok, 1=eof, 2=timeout, ...)
            ioctl var = size               (file: number, tty: {rows,cols})
            ioctl var = name               (filename)
            ioctl var = isopen/isopenin/isopenout

#### eval

    eval text

parse and execute text as a vip script.

the text is parsed just like a script, so almost every expression is possible here, including execution of own procedures.

eval may also be used as a function returning a result value.

    vipsi> eval "put \"hello!\""  hello!

#### call

    call path_to_vip_script, [arg1, [,…]]

call another vip script like a function with parameters and return a result.
the called script is very similar to a standard shell script except that it can be passed and return variables of any type. it shares the preferences of the current context but cannot access it's variables and functions.

call may also be used as a function returning a result value.

    e.g.: call "utils/store_db_entry.vs", user_id, number, value

#### sys

    (1) sys [#num_value,] path_to_system_command [ ,listarg | ,argtext1 [,…] ]
    (2) text = sys ( path_to_system_command [ ,listarg | ,argtext1 [,…] ] )

execute a system command or script with parameters and print it's text output.
the named command is called and passed all the supplied text parameters.
you can provide a hard path or a partial path, which will be completed from the environment variable env.PATH.

(1) instruction: print output to stdout or selected stream number.
(2) function: all output to stdout is returned as a single text value.

text output to stderr is still printed to stderr. (version 0.8.3: the original stderr, when vipsi was launched. redirection of stderr output to vipsi's stderr stream will be added in the future.)

if the called system command returns a non-zero return code, then an error condition is set and the program aborts, if you don't have installed an error handler with try.

you can either pass all arguments in a list variable, which is more convenient for calculated argument lists, which may have a varying number of arguments or you can pass each argument as individual text arguments. if the first argument is a list, then method 1 is assumed and no more arguments must follow, else method 2 is assumed.

e.g.:

    sys "/bin/ls" , "-lR" , "/home"   // will probably take a while ;-)
    sys "rm", "-Rf", "/tmp/*"         // cleaning up
    sys "cp", file_list##target_dir   // passing file_list and target_dir as a single list
                                      // argument, using the list concatenation operator ##
    var dir_text = sys ( "ls", the_dir # "/" # my_filemask )

#### include

    include text_value [,…]

load and execute named script file just as if it's contents were part of the current source.

note: the file is included at the time when this instruction is executed, that means: maybe never, maybe repeatedly, if it occurs in a loop. it is not included at pre-compile time or in some kind of pre-processor as in C.

#### dir

    dir [#num_value,] text_value

print contents of named directory.
the path may be full or partial or start with ~ for user's home directory.
the path may contain a match pattern with wildcards for files to list.
dir prints a beautified folder listing to stdout or stream number.
there is also a function dir which returns the contents of the named folder in a two-dimensional array.

if an empty text is passed as path name, then a list of all mounted file systems is printed which includes additional information like empty space on each volume.

#### wait

    wait num_value

release cpu and wait for the given amount of time. the time passed is in seconds, the actual granularity of wait time is system dependent.

#### info

    info "identifier" [,…]

print info for built-in word:

    info "token|idf" | idf|token | @"idf|token"

note: the name to querry should be passed as text, though passing a naked identifier also works in most cases. but e.g. for flow control words the parser will claim an error.

#### sort

    sort list_var [,…]

sort list in ascending order.
if items of different data type are encountered, they a sorted solely based on their data type.

#### rsort

    rsort list_var [,…]

sort list in descending order.
if items of different data type are encountered, they a sorted solely based on their data type.

#### split

    split text_var [,separator]

split the text at the given separator and store the resulting list of text chunks in the original variable.
the separator may be a character or any text. it is removed and not preserved when splitting a line.
if no separator is given, then the text is split at any character which looks like a line break: char(0), char(10), char(13) and char(10)+char(13).

there is also a function split which returns the list of text fragments.

#### convert

    (1) convert variable from|to encoding
    (2) text = convert ( text to|from encoding )

convert text from or to named encoding.
(1) instruction: the variable is overwritten with the result of the conversion.
(2) function: the converted text is returned as result.

possible encodings:

    escaped      [un]escape characters breaking typical syntax for text literals
    printable    same as 'escaped'
    quoted       [un]escape and add|remove '"'s at both ends
    html         convert '>' etc. to|from &gt;
                 encode: does not encode non_ascii characters to entities.
                         declare the character set of your html file as UTF-8.
                 decode: decodes named entities and character code entities
    url_all      convert to|from UTF-8 and [un]escape special characters for URLs
    url          as above but do not encode the directory separator '/'
                 most time you will need 'url', not 'url_all'.
    tabs[2..9]   en|detab text to tab with 2 … 9 characters
    mac_roman    convert to|from mac roman character set
    iso_latin_1  convert to|from iso-latin-1 character set
    windows      same as iso_latin_1
    utf_8        convert to|from UTF-8 unicode
                 this splits each character into up to 6 characters (typically only 1)
                 which all fit into bytes, ready to be written in binary mode.
                 note: you must not convert text for 'put', 'get', etc. manually
                 because these instructions already do the character set conversion.
                 UTF-8 is the default encoding.
    ucs_2        convert to|from UCS-2 unicode
                 this splits each character into 2 characters which fit into bytes,
                 ready to be written in binary mode to a file.
    ucs_4        convert to|from UCS-4 unicode
                 this splits each character into 4 characters which fit into bytes,
                 ready to be written in binary mode to a file.
    ascii_us     convert to|from 7-bit ASCII
    ascii_ger    convert to 7-bit ASCII, German variant (Ä…ß instead of […\)
    dos, cp_437  convert to|from DOS Latin US character set (codepage 437)
    atari_st     convert to|from Atari ST character set

    uppercase    convert to uppercase
    lowercase    convert to lowercase

    e.g.: convert mytext to printable;
          convert mytext to mac_roman;
          convert mytext from html;
          put "http://", convert(mytext to url)

special note on conversion to|from multi-byte character sets, e.g. UTF-8, UCS-2 or UCS-4:

converting text to UCS-4 expands each character to 4 characters, each representable in 1 byte, suitable for writing in binary mode to a file e.g. with write.

converting text from UCS-4 combines every 4 characters into one character, assuming that the source text only contains bytes e.g. read in binary mode with read.

var a = file "filename" and file "filename" = a also read/write binary data and are suitable targets for a by-hand conversion.

get or put already include a conversion from|to UTF-8 (may be changed with ioctl - not yet implemented in version 0.8.3). applying a conversion after reading / before writing to a stream without having disabled any conversion is certainly an error.

#### replace

    (1) replace targettext, oldtext, newtext
    (2) text = replace ( sourcetext, oldtext, newtext )

replace any occurance of 'oldtext' with 'nowtext'.
(1) instruction: the target text variable is overwritten with the result of the conversion.
(2) function: the converted text is returned as result.

the source text is scanned from left to right and replaced text is not scanned again. if the search text 'oldtext' is an empty string, then nothing is done.

version 0.8.3: replace does not yet work on lists. this will be implemented in the near future.

    e.g.: put replace ( my_email_addr, "@", "&#64;" )    // obscure mailto link
          replace html_file, old_homepage, new_homepage

#### open

    open [#num_value,] filename

open file/stream for reading and writing.
default stream is stdout which should be changed by supplying another stream number with #.
though you should not do so, you can open a stream for stdin, stdout and stderr even in interactive shell mode. the shell's line editor uses a private copy of stdin so that you are not suddenly left alone in the dark...

#### openin

    openin [#num_value,] filename

open file/stream for reading.
default stream is stdin which should be changed by supplying another stream number with #.
though you should not do so, you can open a stream for stdin, stdout and stderr even in interactive shell mode. the shell's line editor uses a private copy of stdin so that you are not suddenly left alone in the dark...

#### openout

    openout [#num_value,] filename

open file/stream for writing.
default stream is stdout which should be changed by supplying another stream number with #.
though you should not do so, you can open a stream for stdin, stdout and stderr even in interactive shell mode. the shell's line editor uses a private copy of stdin so that you are not suddenly left alone in the dark...

#### close

    close [#num_value]

close open file/stream.
default stream is stdout which should be changed by supplying another stream number with #.
streams 0 to 2 (stdin, stdout and stderr) can be closed but will reset to their initial stream afterwards.

#### rename

    rename [variable = text  |  file text = text]

1. rename or assign name to variable. e.g. `rename a[0]="anton"`
2. rename file. file can be moved to another directory this way.

#### cd

    cd text

change working directory. e.g.: `cd "../";`

#### pwd

    pwd [#num_value]

print working directory path. default stream is stdout. similar to `log fullpath "./".`

#### words

    words [#num_value]

List built-in words. default stream is stdout.

    vipsi> words
    _____________________________________________________________________________
    separators:
        ,  (  )  [  ]  {  }  tEOF
    monadic operators:
        ++  --  !  ~  @
    assignment operators:
        =  +=  -=  *=  /=  %=  #=  >>=  <<=  &&=  ||=  ^=  &=  |=  ##=
    other diadic operators:
        +  -  *  /  %  #  ##  >  <  >=  <=  ==  !=  <<  >>  &&  ||  &  |  ^  .
    triadic operators:
        ?  :
    constants:
        ec  pi  nl  tab  stdin  stdout  stderr
    functions:
        file  mdate  count  index  name  random  abs  sign  int  fract  round  min
        max  cos  sin  tan  acos  asin  atan  cosh  sinh  tanh  logn  log2  loge
        log10  exp  exp2  expe  exp10  square  sqrt  istext  isnumber  islist
        isproc  isfile  isdir  exists  string  upperstr  lowerstr  charstr  charcode
        hexstr  binstr  substr  midstr  leftstr  rightstr  datestr  now  dateval
        find  rfind  env  match  fullpath
    instructions:
        new  del  swap  var  freeze  melt  put  log  get  edit  getchar  write  read
        ioctl  eval  call  sys  include  dir  wait  info  sort  rsort  split
        convert  open  openin  openout  close  rename  ;  cd  pwd  words  globals
    flow control:
        proc  return  end  do  then  if  else  while  until  exit  next  loop

    vipsi>