##
## "VIEW", a data viewing program,
##   Copyright (C) 1987, 1990 California Institute of Technology.
##   Original authors: Dave Gillespie, port by Rick Koshi
##   Unix Port Maintainer: John Lazzaro
##   Maintainers's address: lazzaro@hobiecat.cs.caltech.edu;
##                          CB 425/ CU Boulder/Boulder CO 91125. 
##
##
##This program is free software; you can redistribute it and/or modify
##it under the terms of the GNU General Public License as published by
##the Free Software Foundation (Version 1, Feb 1989).
##
##This program is distributed in the hope that it will be useful,
##but WITHOUT ANY WARRANTY; without even the implied warranty of
##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##GNU General Public License for more details.
##
##You should have received a copy of the GNU General Public License
##along with this program; see the file ../COPYING.  If not, write to
##the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
##
##
## caged_process='view -c $F >$B.out$M'
## cagedx_process='view -c $F$M'
## set trace=1
set log=examples.log

## Sample inputs for "readln" and "readnum" commands below
typeahead 7\n1 2 3\n4 5\n\n$$y $$x\nbar\nDave\n\n$$foo G.\n







#############################  Some Examples  #############################
#########################           of             ########################
########################  View Language Constructs  #######################


## Table of contents:

##    Reader (";;", "\\", and "##" notations)
##    Expander ("$" notations)
##    Arithmetic expressions
##    Conditional statements: if, switch
##    Looping statements: for, while, repeat
##    Input and output statements
##    Defining your own commands
##    Defining your own math functions
##    Fun examples


## Note: This entire file is executable.  Every command (except those
##       commented out) works exactly as shown.







##############################  Reader  ###################################


##########  Multiple statements per line

print 'foo' ;; print 'bar'       ## Prints 'foo' then 'bar'

if 1>2 ;; print 1 ;; else ;; print 2 ;; endif      ## Prints: 2


##########  Multiple lines per statement

print \\                ## Prints 'foo'
   'foo'                ## Note: \\ must be last thing on line except comments


##########  Comments

print 'foo'             ## You are now reading a comment
print '## hello'        ## Prints: ## hello     (quotes protect special chars)
# Another command          Single # allowed at beginning of a line
                        ## Double ## allowed anywhere.  Preferred usage is
                        ## to write ## exclusively.






#############################  Expander  ##################################


###########  The basic idea

foo = 'bar'
bar = 42
print foo               ## Prints: bar    (PRINT evaluates its arguments)
print $foo              ## Prints: 42

echo foo                ## Prints: foo    (ECHO just echoes the argument line)
echo $foo               ## Prints: bar


###########  Mixing expansions into names

i = 5 ;; a5 = 43
print a$i               ## Prints: 43

j = 8 ;; a5_8 = 19
print a${i}_$j          ## Prints: 19
                        ## Note: a$i_$j would not work since "i_" would be
                        ## interpreted as the variable name instead of "i"


###########  Expanding arithmetic expressions

i = 5
echo $i                 ## Prints: 5
echo ${i+3}             ## Prints: 8
echo ${'hi'+'there'}    ## Prints: hithere


###########  Nested expansions

a3_4 = 7 ;; b7 = 4 ;; i = 3 ;; j = 4 ;; k = 7
echo    a${i}_$j        ## Prints: a3_4
print   a${i}_$j        ## Prints: 7
echo  b${a${i}_$j}      ## Prints: b7
print b${a${i}_$j}      ## Prints: 4

echo          b$k       ## Prints: b7
print         b$k       ## Prints: 4
echo  a${i}_${b$k}      ## Prints: a3_4
print a${i}_${b$k}      ## Prints: 7

echo 'foo$i'            ## Prints: 'foo$i'   ($ not expanded inside ' ')
echo "foo$i"            ## Prints: "foo3"    ($ is expanded inside " ")
echo $$foo              ## Prints: $foo      ($$ expands to $)


###########  Format specifiers

name = '  Foo  '  ;;  food = 'spam'   ;;  blank = ''
i = -16.3e+12     ;;  j = 6

echo *$name*            ## Prints: *  Foo  *
echo *${name}*          ## Prints: *  Foo  *    (the same thing)
echo *${name:t}*        ## Prints: *Foo*        (trimmed)
echo *${name:u}*        ## Prints: *  FOO  *    (uppercase)
echo *${name:l}*        ## Prints: *  foo  *    (lowercase)
echo *${name:q}*        ## Prints: *'  Foo  '*  (quoted)
echo *${name:v}*        ## Prints: *name*       (verbatim)
echo foo${i}            ## Prints: foo-16.3e+12 (not a valid variable name)
echo foo${i:n}          ## Prints: foo_16.3e12  (convert number -> safe name)
echo *${blank}*         ## Prints: **
echo *${blank::yow}*    ## Prints: *yow*        (default)
echo *${name::yow}*     ## Prints: *  Foo  *    (default used only if blank)
echo *${blank::$i}*     ## Prints: -16.3e+12    (expansions within default)
## echo *${i/0}*        ## fails with "Division by zero"
echo *${i/0:e}*         ## Prints: **           (any errors -> blank)
echo *${i/0:e:$i}*      ## Prints: *-16.3e+12*  (any errors -> default)
echo *${i/0:e:i}*       ## Prints: *i*          (a common mistake -- beware!)
echo *${zoo:e:yow}*     ## Prints: *yow*        (here 'zoo' is undefined)
echo *${pi}*            ## Prints: *3.141592*   (pi is a built-in name)
echo *${pi:5w}*         ## Prints: *3.142*      (set width)
echo *${j:5w}*          ## Prints: *    6*      (numbers padded on left)
echo *${food:5w}*       ## Prints: *spam *      (strings padded on right)
echo    ${j:q}          ## Prints: '6'
echo *${${j:q}:5w}*     ## Prints: *6    *      (trick for right-padded nums)
echo *${pi:5d}*         ## Prints: *3.14159*    (set number of decimal places)
echo *${pi:2d6w}*       ## Prints: *  3.14*     (set width + digits)
echo *${pi:2d${j}w}*    ## Prints: *  3.14*     (for variable widths, etc.)
echo *${food}*          ## Prints: *spam*
echo *${food:2F}*       ## Prints: *pam*        (set "From" position)
echo *${food:3T}*       ## Prints: *spa*        (set "To" position)
echo *${food:2F3T}*     ## Prints: *pa*         (From-To substring)
echo *${food:2F1L}*     ## Prints: *p*          (From-Length substring)
echo z=${food:q}        ## Prints: z='spam'     (building up a combination)
echo z=${food:uq}       ## Prints: z='SPAM'
echo z=${food:6wuq}     ## Prints: z='SPAM  '
echo z=${food:3F6wuq}   ## Prints: z='AM  '
echo z=${food:3F3L6wuq} ## Prints: z='AM '








#######################  Arithmetic Expressions  ##########################


## Note: Certain operators ('@', '=', ':') are treated by View as
##       punctuation characters and so must be enclosed in parentheses
##       when use in the context of some View commands.  See examples below.


###########  Simple arithmetic

print 1+2               ## Prints: 3            (addition)
print 'hi'+'there'      ## Prints: hithere      (concatenation)
print 1-2               ## Prints: -1           (subtraction)
print 3*2               ## Prints: 6            (multiplication)
print 3/2               ## Prints: 1.5          (real division)
print 3^2               ## Prints: 9            (powers)


###########  Integer operations

print 1234\100          ## Prints: 12           (integer division)
print 1234%100          ## Prints: 34           (modulo)
print 10&6              ## Prints: 2            (binary 1010 AND 0110 = 0010)
print 10|6              ## Prints: 14           (binary 1010 OR  0110 = 1110)
print (10@6)            ## Prints: 12           (binary 1010 XOR 0110 = 1100)
print ~6                ## Prints: -7           (binary NOT 000110 = 111001)
print 6<<2              ## Prints: 24           (arithmetic shift left)
print 6>>2              ## Prints: 1            (arithmetic shift right)


##########  Comparisons

print (6=7)             ## Prints: 0            (0 = "false")
print (7=7)             ## Prints: 1            (1 = "true")
print (6<>7)            ## Prints: 1            (not equal to)
print (6<7)             ## Prints: 1            (less than)
print (6<=7)            ## Prints: 1            (less than or equal to)
print (6>7)             ## Prints: 0            (greater than)
print (6>=7)            ## Prints: 0            (greater than or equal to)

print ('a'<'b')         ## Prints: 1            (strings use in ASCII order)
print (''<='any str')   ## Prints: 1
print ('foo'<'fool')    ## Prints: 1

print 1+(6<7)           ## Prints: 2            (using conditions in math)

print (1=1||2=3)        ## Prints: 1            (logical OR)
                        ##                      (Parens are to enclose '=')
print (1=1&&2=3)        ## Prints: 0            (logical AND)
print !(1=1)            ## Prints: 0            (logical NOT)


##########  Conditional operators

print 67||23            ## Prints: 67           (general use of logical OR)
print 0||23             ## Prints: 23           (0 = false, nonzero = true)

print 67&&23            ## Prints: 23           (general use of logical AND)
print 0&&23             ## Prints: 0

print 'foo'||'bar'      ## Prints: foo          (logical AND/OR on strings)
print ''||'bar'         ## Prints: bar          (blank = false)

print (1?67:23)         ## Prints: 67           (if-then-else construct)
print (0?67:23)         ## Prints: 23
print (2=3?67:23)       ## Prints: 23
print (i<1?1:i>10?10:i)    ## Prints i clipped to within [1..10]

print (1?'foo':'bar')   ## Prints: foo
print (0?'foo':'bar')   ## Prints: bar

print (''?67:23)        ## Prints: 23           (blank = false)
print ('yow'?'a':'b')   ## Prints: a            (non-blank = true)

## print 1?67:23        ## Syntax error: parentheses needed in a PRINT command
                        ## because PRINT uses colons for something else


##########  Curve-related functions

basis b1 = 0:10:2       ## Create a basis curve with 6 data points
print cvlen('b1')       ## Prints: 6            (note curve name in quotes!)
mycurve = 'b1'
print cvlen(mycurve)    ## Prints: 6
print cvidx('b1',1)     ## Prints: 0            (first y-value of b1)
print cvidx('b1_x',2)   ## Prints: 2            (second x-value of b1)
print cvidx('b1', \\    ## Prints: 10           (last y-value of b1)
         cvlen('b1'))

c1 = b1 + cvrelidx('b1',1)    ## Each i'th value of c1 is the sum of
                              ## the i'th and i+1'st values of b1
                              ## (The last value will be undefined: "X")

c1 = cvrelidx('b1',1)         ## This command FAILS because View does not
                              ## know which basis to use for the computation.
                              ## (The name 'b1' is in quotes).

c1 = cvrelidx('b1',1) : b1    ## This command works: it means "evaluate
                              ## with respect to the basis of b1."

c1 = 0 : b1                   ## Create a curve with b1's basis, all y's = 0.





#######################  Conditional Statements  ##########################


if 2 = 2
   print 'hello'        ## Prints: hello
endif                   ## Note: indentation is optional but recommended!

if 2 = 3
   print 'hello'        ## Skips this statement
endif


if i = 0
   print 'true'         ## Prints this if i is zero
else
   print 'false'
endif


if i = 0
   print 'zero'
elseif i < 0            ## Multiple choices
   print 'negative'
else
   print 'positive'
endif


if i = 0
   print 'zero'
else
   if i < 0             ## Alternate method using nested if's
      print 'negative'
   else
      print 'positive'
   endif
endif


switch i+1              ## The SWITCH statement is patterned after C
   case 1
      print 'one'
      break
   case 2
      print 'two'       ## No BREAK statement, so this will fall through
   case 3               ## and do the next case, too.
   case 4
      print 'two, three or four'
      break
   otherwise            ## If OTHERWISE is omitted, the SWITCH construct
      print 'I dunno'   ## is ignored if no cases match
endswitch


name = 'joe'
switch name
   case 'Joe'
      print 'Joe'       ## Not printed: strings are case-sensitive
      break
   rcase jo*hn          ## Regular expression case
      print 'jhn, john, joohn, jooohn, etc.'
      break
   pcase j*             ## Wildcard pattern case
      print 'Name starts with "j"'     ## This one will be printed
endswitch


switch [ci] name        ## Case-insensitive switch
   case 'Joe'
      print 'Hi, Joe.'  ## This time it is printed
endswitch





#########################  Looping Statements  ############################


for i = 1:5             ## Count from 1 to 5, default step is 1
   print i
endfor

for i = 5:1             ## Never executes, since 5 > 1
   print i
endfor

for i = 1:5:2           ## Count by 2: prints 1, 3, 5
   print i
endfor

for i = 5:1:-1          ## Count down by -1
   print i
endfor

for i = 0:1:0.1         ## Count by 0.1: loop executes 11 times
   print i
endfor

i = 1
while i <= 5            ## Also counts 1, 2, 3, 4, 5
   print i
   i = i + 1
endwhile

i = 1
repeat                  ## Also counts 1, 2, 3, 4, 5
   print i
   i = i + 1
until i > 5

i = 1                   ## Also counts 1, 2, 3, 4, 5
while                   ## "Infinite" loop
   print i
   if i = 5 ;; break ;; endif    ## BREAK jumps out of the loop
   i = i + 1
endwhile

i = 1
while i > 5             ## False right away: skips the body of the loop
   print i ;; i = i - 1
endwhile


repeat                  ## Get a value in a reasonable range
   readnum size : Enter size of boulders:
until size > 0 && size < 1e6     ## "&&" = logical AND


j = 5
for i = 1 : j           ## Prints 1, 2, 3, 4, and 5
   print i
   j = 2                ## Doesn't affect loop since j is copied at the start
endfor


for i = 1 : 5          ## Prints 1, 2, 3, 4, 5
   print i
   if i = 2 ;; i = 4 ;; endif  ## Changing the loop variable inside the loop
endfor                         ##   has no effect either


for i = 1:10
   for j = 1:10
      break
   endfor               ## BREAK jumps to the innermost ENDFOR
endfor

for i = 1:10
   for j = 1:10
      break 2
   endfor
   print 'never printed'
endfor                  ## BREAK 2 jumps to the second innermost ENDFOR





#######################  Input/Output Statements  #########################


##########  Echoing a line

echo This is   a message.        ## Prints: This is   a message.
foo = 'This is   a message.'
echo $foo                        ## Prints: This is   a message.


##########  Printing the values of expressions

print 'This is   a message.'     ## Prints: This is   a message.
print 3+2 3-2                    ## Prints: 5 1    (adds one space btwn nums)
## print 3 + 2                   ## Syntax error: spaces not allowed in exprs
print (3 + 2)                    ## Prints: 5      (parens enclose spaces)


##########  Formatting expressions (see also Expander's "$" formats)

print pi                ## Prints: 3.141592
print '*' pi:5 '*'      ## Prints: *3.142*      (set width)
print '*' 16:5 '*'      ## Prints: *   16*      (numbers padded on left)
print '*' pi::5 '*'     ## Prints: *3.14159*    (set decimal places)
print '*' pi:6:2 '*'    ## Prints: *  3.14*     (set width + digits)

name = 'Joe'
print '*' name:5 '*'      ## Prints: *Joe  *    (strings padded on right)
print '*' ${1+2:q}:5 '*'  ## Prints: *3    *    (trick for right-padded nums)



##########  Reading numbers

readnum x y z                 ## Gets three numbers from keyboard.
                              ## User may enter any three values or
                              ## expressions separated by commas or spaces.

readnum x y : Position?       ## Prompt string for input

readnum [opt] x y             ## Optional input: if user enters a blank
                              ## line, variables are left unchanged (rather
                              ## than asking again).

readnum [exp] x y             ## Do "$" expansions on input line



##########  Reading strings

readln foo                    ## Gets a line and stores in variable foo

readln foo : What is your name?     ## Prompt string

readln [opt] foo              ## If user enters a blank line, variable is
                              ## left unchanged (rather than made blank).

readln [exp] foo              ## Do "$" expansions on input line





#####################  Defining Your Own Commands  ########################


## Define a command to list all curves whose names begin with 'z':

define listz
   echo Curves beginning with z:
   ls z*
enddef



## Command to increment a variable

define incr var
   $var = $var + 1
enddef



## Command to print "hello" a certain number of times

define hello n
   local i
   for i = 1 : $n    ## Note "$" because arguments are passed as strings
      print 'Hello'
   endfor
enddef



## Command to make an exponential basis

define ebasis curve = min : max
   local temp
   basis temp = log($min) : log($max)
   temp = 10^temp
   splice $curve = temp : temp
enddef



## Define an alternate syntax for EBASIS command

define [after] ebasis curve = max   ## [after] = add this defn after old one
   ebasis $curve = 1 : $max         ## Can define the command in terms of
enddef                              ##   a different form it itself!



## Add exponential bases as an option to normal BASIS command

define [before] basis "[exp]" curve = min : max
   ebasis $curve = $min : $max
enddef

basis linb = 1:10                   ## This will use built-in definition
basis [exp] logb = 1:10             ## This will use new definition



## Command to reverse a curve (from front to back)

define reverse newcurve = curve
   local i len                ## Local variables
   local xc = ${curve}_x      ## Local variables with initialization
   local yc = $curve
   len = cvlen(curve)         ## No "$", since cvlen wants a string
   for i = 1 : len
      poke yc @ i = cvidx(curve,      len-i+1)
      poke xc @ i = cvidx(curve+"_x", len-i+1)
   endfor
   splice ${newcurve} = xc : yc
enddef

define [after] reverse curve
   reverse $curve = $curve    ## Default is to reverse the curve in-place
enddef



## Command to exchange the x- and y-values of a curve

define swapxy newcurve = curve
   local xvalues
   xvalues = ${curve}_x
   splice $newcurve = $curve : xvalues
enddef

define [after] swapxy curve ;; swapxy $curve = $curve ;; enddef



## Command to adjust constants in a curve using PLOT-mode "c" command

define tweak {curves} : {vars}      ## { } matches multiple words
   tweak_cvs = curves               ## Save names to use as defaults later
   tweak_vrs = vars
   typeahead c ${vars}\n            ## Put text + newline into typeahead buffer
   plot $curves                     ##   so that the PLOT command will see it
enddef

define [after] tweak {vars}         ## Must be [after], not [before]
   tweak $tweak_cvs : $vars         ##   since this template will match
enddef                              ##   "x:y" as well as "x".  In fact,
                                    ##   "{vars}" will match any arguments!

define [before] tweak               ## This must be [before] so that it is
   tweak $tweak_cvs : $tweak_vrs    ##   checked before "{vars}".
enddef



## Command to convolve a curve against a simple box filter

define boxfilter newcurve = curve
   $newcurve = ($curve + cvrelidx(curve,1) + cvrelidx(curve,-1))/3
enddef

define [after] boxfilter curve
   boxfilter $curve = $curve        ## Convolve the curve in-place
enddef



## Command to convolve a curve against a variable-width box filter

define filter newcurve = curve : width
   local i expr
   expr = curve
   for i = 1 : $width
      expr = expr + "+cvrelidx(curve,$i)+cvrelidx(curve,-$i)"
   endfor
   $newcurve = ($expr)/(1+2*($width))
enddef

## For example, in "filter a=b:2" the final assignment looks like:
##   a=b+(cvrelidx(curve,1)+cvrelidx(curve,-1)+   \\
##        cvrelidx(curve,2)+cvrelidx(curve,-2))/(1+2*(2))

## Beware: View strings can only grow to 255 characters; if "expr" gets
##   too large you must resort to drastic kludgery.

define [after] filter newcurve = curve
   filter $newcurve = $curve : 3
enddef

define [after] filter curve : width
   filter $curve = $curve : $width
enddef

define [after] filter curve
   filter $curve = $curve
enddef





####################  Defining Your Own Functions  ########################


## Compute the average of two numbers
avg(x,y) = (x+y)/2
print avg(3,5)          ## Prints: 4


## Define factorials using the built-in gamma function
factorial(x) = gamma(x+1)


## Step function: 0 for x<0, 1 for x>=0
step(x) = x>=0 ? 1 : 0                 ## Using if-then-else operator


## Another step function: 0 for x<0, 1 for x>0, 0.5 exactly at 0
step2(x) = x>0 ? 1 : x<0 ? 0 : 0.5     ## Two if-then-else operators


## Smooth step function between 0 and 1, this time using a tanh
gain = 10
smstep(x) = (tanh($gain*x)+1)/2        ## Use value of "gain" that is current
                                       ##   when the function is defined
smstep(x) = (tanh(gain*x)+1)/2         ## Use value of "gain" that is current
                                       ##   when the function is used


## Function that returns a random lower-case letter
letters = 'abcdefghijklmnopqrstuvwxyz'
rletter() = strsub(letters, irand(1,26))
print rletter()         ## Prints, e.g.: j
print rletter           ## Alternate form for zero-argument functions






############################  Fun Examples  ###############################


## This section is open for contributions!























## End.


