r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[I'm new] Ask any question, and a helpful person will try to answer.

Oldes
4-May-2009
[2118x4]
and or you can use:
get-ips2: func[str /local ips ip][
	str: parse str none
	ips: copy []
	while [not tail? str] [

		error? try [
			ip: to-tuple str/1
			if 4 = length? ip [append ips ip]
		]
		
		str: next str
	]
	ips
]
BUT in the second version there is problem with cases like:
get-ips2 {"this is invisible IP 0.0.0.0" 255.0.0.0}
Also it fails with:
get-ips2 {this is NOT an IP 255.0.0.}
So the result is.. if you want to be sure, use the string based parsing.
mhinson
4-May-2009
[2122]
I suppose it depends where the data comes from. looking at configs 
from routers should mean the IP addresses & masks etc are already 
propperly formatted. Thanks.
Pekr
5-May-2009
[2123]
you could also probably enhance it by stati 1 to 3 digitis, dot ...
mhinson
7-May-2009
[2124]
Hi, I have been working on a bit of code for some time & it now does 
something usefull for me, but to use it I am coding the output file 
into the code & running it repeatedly against every file in a directory. 
  I thought it would be nice for it to have a very simple GUI to 
navigate to the input directory & output file & perhaps display some 
indicator of progress. 

Is this something a beginner might hope to add to existing code, 
or should I start from scratch again with the GUI part, then try 
to recreate my code in the view Layout part? Thanks.
Henrik
7-May-2009
[2125]
you can create a prototype of the GUI first, by just creating a layout 
with the placement of the styles you want. afterwards you can make 
it work as you want using SET-FACE, GET-FACE, etc.
mhinson
7-May-2009
[2126]
I will have a fiddle & see if I can understand that. Thanks very 
much Henrik
Henrik
7-May-2009
[2127]
It's very easy to create prototypes and VID is excellent for that:

view layout [
	across space 2
	box blue 300x300 "List View"
	box yellow 100x300 "Buttons"
	return
	box red 402x24 "OK/Cancel Panel"
]
mhinson
7-May-2009
[2128x2]
Thanks, I started looking at this before & got confused with how 
I extract the information I can see on the screen & use it in the 
context of another block of code. With VB I think event handelers 
pop up everywhere? not sure but I think it is something like that. 
I couldnt work out how the same sort of thing is done in Rebol.
if I have 
view layout [box green 400x400 field]


the interpreter wont even load any more lines of script while the 
box is on the screen, so I am guessing I have to call the rest of 
my code from within the view layout block?
Henrik
7-May-2009
[2130x3]
Here's some learning by doing:


With the above line of code, activate the console and press escape. 
The event handler is returned to the console.

Now you can control the window interactively. Type UNVIEW.
Then try this line:

view layout [b: box green 400x400 f: field]

Go back to console and escape.

b/color: yellow
show b

set-face f "hello"
get-face f
hide f
show f

That's how you access UI parts.
If you want to return the event handler to the UI, type DO-EVENTS.
mhinson
7-May-2009
[2133]
Unview!   wow, that will save me exiting the console a hundred times 
a day!!  That is a top tip & should be in a prominate place for newbies.
Henrik
7-May-2009
[2134]
If you want to show a window and return to console immediately, use 
VIEW/NEW instead.
mhinson
7-May-2009
[2135x2]
This might be doable even for me. Thanks for these tips, I have read 
so much about Rebol, but I never seem to take it in properly.

One of the great things with rebol is how I can test even the smallest 
fragment of code in the console, this makes it very friendly. Thanks 
for your help.
I have been looking at the library examples & noticed that some of 
them start off with something like
navigator: make object! [

The ones like this dont do anything so I am guessing I need to use 
this code in a way I have not come across yet. I have been madley 
trying things like

make a: navigator  and looking up make in the documentation, but 
not understanding the answers.
Henrik
7-May-2009
[2137]
make object! is the same as making a context. If you see an entire 
script wrapped in make object! [] or context [], it is because it 
was desired to use this script with other scripts without polluting 
the global namespace.
mhinson
7-May-2009
[2138]
Oh, I see, the actual functions are inside the object.
Henrik
7-May-2009
[2139]
Try this:

context [
	a: 2
	set 'b 3
	set 'c does [return a]
]

>> a
>> b
>> c

A simple way to control what's private and public.
mhinson
7-May-2009
[2140]
I see, that is good.    I have seen the 'b   syntax used but not 
understood it yet.  I see in your example the set 'b 3 seems like 
b: 3 in the global context.  Thanks very much for your tips, they 
are a great help.
Sunanda
7-May-2009
[2141]
On the other hand, if you want 'a, 'b, 'c to be local to the context 
-- so other parts of your application can also have their own 'a. 
'b and 'c without overwriting each other:

    my-api: context [
        a: 2
        b: 3
        c: does [return a + b]
    ]

my-api/a: 5   ;; override default value
print my-api/c  ;; executes function in context
mhinson
7-May-2009
[2142]
I wondered how the xxx/xxx/xxx paths to data were constructed... 
I was thinking of this sort of thing as a way to refer to valuse 
in a multi demensional array by name rather than number
house: context [
  room1: context [
      items: [bed chair table]
      ]
  room2: context [
      items: [TV sofa HiFi]
      ]
]
Sunanda
7-May-2009
[2143]
That's the way I do it, using 'context / make object!

Some people prefer using blocks rather than objects:
    blk: [a 4 b 5 c 6]
    blk/b
    == 5
   blk/b: 99
   probe blk
    == [a 4 b 99 c 6]

There are advantages and disadvantages to each approach.
mhinson
7-May-2009
[2144]
I used to get the same sort of effect in Pascal by defining ordinal 
types with values that were meaningfull words & use them to index 
my arrays.
Sunanda
7-May-2009
[2145]
:-) ..... You could think of it as a  type of associative array.
mhinson
7-May-2009
[2146]
A question: if I want to provide a dialoge to navigate to a directory 
can I call up the ms windows file open & save dialogs, or do I have 
to do it all in rebol. I cant find any examples of this & dont have 
the skills to create my own...  I like the idea of having a GUI interface, 
but I may have to go back to command line if it is too hard for me 
:-)
Sunanda
7-May-2009
[2147]
File open dialog is simple.
  source request-file
:-)
mhinson
7-May-2009
[2148]
oh, that was simpler than expected. Thanks very much.  I must say 
I dont think Rebol is very easy to learn, but once all these tricks 
are known it must be very easy to write things quickly.  Perl is 
like a tool shop & a tree for wood, while Rebol is like a high street 
full of all sorts of shops as well as tools.
Sunanda
7-May-2009
[2149]
And unexpected pot holes :-)
mhinson
7-May-2009
[2150]
There is a request-dir too, but it is a bit of a joke. Looks like 
the way to go is to use the request-file then extract the directory. 
 Why would request-dir even exist in such a feeble state? Sorry, 
I hope I am  not speaking out of turn, but if anyone had that pop 
up they would think it was a bit odd.
Sunanda
7-May-2009
[2151]
No, request-dir is pretty low standard.
Henrik
7-May-2009
[2152x2]
some parts are sub-par, like request-color as well. fortunately it's 
possible to rewrite them.
large parts of the GUI system was written in a very short time by 
Carl alone back early in this decade and has not been officially 
upgraded.
mhinson
7-May-2009
[2154]
Excuseme please, but can someone pull me out of the mud here please?

filenames: request-file/title/filter/path {Select all files to read} 
[*.txt] %/D/Rebol/X/!conf/   

What have I not understood this time?  Why does the documentation 
have no examples I can find?  Sorry to be always asking :-(
Henrik
7-May-2009
[2155]
two arguments are necessary for the /TITLE refinement.
mhinson
7-May-2009
[2156x2]
I added an extra string for the title and now get this similar failure

>> filenames: request-file/title/filter/path {Select all files to 
read} {x} [*.txt] %/D/Rebol/X/!conf/

** Script Error: Invalid argument: *.txt * *.r *.reb *.rip *.txt 
*.jpg *.gif *.bmp *.png
** Where: request-file
** Near: done: local-request-file data: reduce

[tt/text ob/text clean-path where picked filt-names filt-values found? 
any [only]...
AH a string "*.txt" for the filter works   Thanks for your help
Gregg
11-May-2009
[2158x2]
Large message coming, with examples of showing progress. Note that 
it uses INCLUDE and FILE-LIST, so adapt accordingly, and let me know 
if I left any other dependencies in it that cause it not to work. 
It was quickly hacked from existing code.
REBOL []

do %include.r
include %file-list.r


flash-wnd: flash "Finding test files..."

if file: request-file/only [
    files: read first split-path file
]
if none? file [halt]

items: collect/only item [
    foreach file files [item: reduce [file none]]
]

unview/only flash-wnd



;-------------------------------------------------------------------------------
;-- Generic functions

call*: func [cmd] [
    either find first :call /show [call/show cmd] [call cmd]
]

change-each: func [
    [throw]

    "Change each value in the series by applying a function to it"

    'word   [word!] "Word or block of words to set each time (will be 
    local)"
    series  [series!] "The series to traverse"

    body    [block!] "Block to evaluate. Return value to change current 
    item to."
    /local do-body
][
    do-body: func reduce [[throw] word] body
    forall series [change/only series do-body series/1]

    ; The newer FORALL doesn't return the series at the tail like the 
    old one

    ; did, but it will return the result of the block, which is CHANGE's 
    result,
    ; so we need to explicitly return the series here.
    series
]

collect: func [
    "Collects block evaluations." [throw]
    'word
    block [block!] "Block to evaluate."
    /into dest [block!] "Where to append results"
    /only "Insert series results as series"

    /local fn code marker at-marker? marker* mark replace-marker rules
][
    block: copy/deep block
    dest: any [dest make block! []]

    fn: func [val] compose [(pick [insert insert/only] not only) tail 
    dest get/any 'val

        get/any 'val
    ]
    code: 'fn
    marker: to set-word! word
    at-marker?: does [mark/1 = marker]
    replace-marker: does [change/part mark code 1]
    marker*: [mark: set-word! (if at-marker? [replace-marker])]
    parse block rules: [any [marker* | into rules | skip]]
    do block
    head :dest
]

edit-file: func [file] [
    ;print mold file

    call* join "notepad.exe " to-local-file file ;join test-file-dir 
    file
]

flatten: func [block [any-block!]][
    parse block [

        any [block: any-block! (change/part block first block 1) :block | 
        skip]
    ]
    head block
]

logic-to-words: func [block] [

    change-each val block [either logic? val [to word! form val] [:val]]
]

standardize: func [

    "Make sure a block contains standard key-value pairs, using a template 
    block"
    block    [block!] "Block to standardize"
    template [block!] "Key value template pairs"
][
    foreach [key val] template [
        if not found? find/skip block key 2 [
            repend block [key val]
        ]
    ]
]

tally: func [

    "Counts values in the series; returns a block of [value count] sub-blocks."
    series [series!]
    /local result blk
][
    result: make block! length? unique series

    foreach value unique series [repend result [value reduce [value 0]]]
    foreach value series [
        blk: first next find/skip result value 2
        blk/2: blk/2 + 1
    ]
    extract next result 2
]


;-------------------------------------------------------------------------------

counts: none

refresh: has [i] [
    reset-counts
    i: 0
    foreach item items [
        i: i + 1
        set-status reform ["Testing" mold item/1]
        item/2: random/only reduce [true false]
        show main-lst
        set-face f-prog i / length? items
        wait .25
    ]
    update-counts
    set-status mold counts
]

reset-counts: does [counts: copy [total 0 passed 0 failed 0]]

set-status: func [value] [set-face status form value]

update-counts: has [pass-fail] [
    counts/total: length? items

    pass-fail: logic-to-words flatten tally collect res [foreach item 
    items [res: item/2]]
    ;result (e.g.): [true 2012 false 232]
    standardize pass-fail [true 0 false 0]
    counts/passed: pass-fail/true
    counts/failed: pass-fail/false
]

;---------------------------------------------------------------


main-lst: sld: ; The list and slider faces
c-1:           ; A face we use for some sizing calculations
    none
ml-cnt:        ; Used to track the result list slider value.
visible-rows:  ; How many result items are visible at one time.
    0

lay: layout [
    origin 5x5
    space 1x0
    across

    style col-hdr text 100 center black mint - 20

    text 600 navy bold {

        This is a sample using file-list and updating progress as files are
        processed. 
    }
    return
    pad 0x10

    col-hdr "Result"  col-hdr 400 "File" col-hdr 100
    return
    pad -2x0

    ; The first block for a LIST specifies the sub-layout of a "row",

    ; which can be any valid layout, not just a simple "line" of data.

    ; The SUPPLY block for a list is the code that gets called to display

    ; data, in this case as the list is scrolled. Here COUNT tells us

    ; which ~visible~ row data is being requested for. We add that to 
    the

    ; offset (ML-CNT) set as the slider is moved. INDEX tells us which
    ; ~face~ in the sub-layout the data is going to.

    ; COUNT is defined in the list style itself, as a local variable 
    in
    ; the 'pane function.
    main-lst: list 607x300 [
        across space 1x0 origin 0x0
        style cell text 100x20 black mint + 25 center middle
        c-1: cell  cell 400 left   cell [edit-file item/1]
    ] supply [
        count: count + ml-cnt
        item: pick items count
        face/text: either item [
            switch index [
                1 [

                    face/color: switch item/2 reduce [none [gray] false [red] true [green]]
                    item/2
                ]
                2 [mold item/1]
                3 ["Edit"]
            ]
        ] [none]
    ]

    sld: scroller 16x298 [ ; use SLIDER for older versions of View

        if ml-cnt <> (val: to-integer value * subtract length? items visible-rows) 
        [
            ml-cnt: val
            show main-lst
        ]
    ]
    return
    pad 0x20
    f-prog: progress 600x16
    return
    status: text 500 return
    button 200 "Run" [refresh  show lay]
    pad 200
    button "Quit" #"^q" [quit]
]

visible-rows: to integer! (main-lst/size/y / c-1/size/y)

either visible-rows >= length? items [
    sld/step: 0
    sld/redrag 1
][
    sld/step: 1 / ((length? items) - visible-rows)
    sld/redrag (max 1 visible-rows) / length? items
]

view lay
mhinson
12-May-2009
[2160]
Hi, I am trying to reduce the number of global variables I use in 
functions & so my functions return blocks, but I have not discovered 
any simple way to dereference the information in the variables, within 
the blocks..  I have written a function to do it, but I guess there 
is a built in function if I could find it. Or at least something 
a bit more elegant than this: "return_value_of_block_component" function. 
  Any tips most welcome please.

f1: func [a] [
	b: join a "-Bee"
	c: join a "-Cee"
	return [b c]
]

d: f1 {Hi}

return_value_of_block_component: func [block component] [
	foreach element block [
	if element = component [return reduce [element]]
	]
]

H: return_value_of_block_component d 'b
I: return_value_of_block_component d 'c

print H
print I
BrianH
12-May-2009
[2161]
For f1, reduce the block before you return it. Then use set [a b] 
f1 "blah" to get the values.
Henrik
12-May-2009
[2162]
about returning complex values: generally it's easier to just pass 
objects around.
mhinson
12-May-2009
[2163]
Brian if I reduce the block I cant reference the values in the block 
by name (b & c in my example). or perhaps I dont know how to?
BrianH
12-May-2009
[2164]
If you need the names, create an object and return that like Henrik 
says. If you need the values, my method will work.
Henrik
12-May-2009
[2165]
vars: make object! [
	b: c: none
]

f1: func [a] [
	vars/b: join a "-Bee"
	vars/c: join b "-Cee"
	vars
]
mhinson
12-May-2009
[2166]
I see, it looks as if both techniques will help me in different cases
Henrik
12-May-2009
[2167]
when using objects, you will have less maintenance and you have one 
place where your object contents is defined. imagine if you have 
10 different functions that would return blocks (10 block definitions) 
versus 10 functions that return objects (1 object definition).