REBOL [
    Title: "Dir-map explorer"
    Date: 18-Jul-2001/10:09:09+2:00
    Version: 0.1.2
    File: %dir-map-explorer.r
    Author: "Oldes"
    Usage: {
^-^-dir-map-explorer/load-map %path_to_map_file
^-^-dir-map-explorer/search-changes/since 10-7-2001
^-^-dir-map-explorer/statistics ["html" "r"] ;to count number of .htmt and .r files
^-^-dir-map-explorer/search "*reb*" ;search all files or dirs with query string *reb*
^-^-dir-map-explorer/show-dir-tree ;displays all directories
^-^-dir-map-explorer/show-dir-tree/with-files ;with files as well :)
^-^-
^-^-using the actions object you can create your own functions
^-}
    Purpose: {to work with directory maps generated by %dir-mapper.r script
}
    Comment: {This script works with recursive dir-map structure that is not so good for large and deep directories. So I'll probably do better non-recursive structure soon.}
    History: [
    0.1.2 18-Jul-2001 "Some improvements + new functions" 
    0.1.0 13-Jul-2001 "first version"
]
    Email: oldes@bigfoot.com
    mail: oldes@bigfoot.com
    library: [
        level: 'advanced 
        platform: none 
        type: 'tool 
        domain: [file-handling DB] 
        tested-under: none 
        support: none 
        license: none 
        see-also: none
    ]
]

dir-map-explorer: make object! [
    map: copy []
    map-file: none
    full-path: none
    cur-depth: -1
    cur-filename: none
    since-date: 1-1-1900
    actions: make object! [
        dir: []
        file: []
    ]
    
            
    load-map: func[file [file! url! block!] "path to map-file"][
        not error? try [
            either block? file [
                map: file
                map-file: none
            ][
                map-file: copy file
                map: load map-file
            ]
        ]
    ] 

    init: does [
        cur-depth: -1
        cur-filename: none
        full-path:  to-file ""
        actions: make object! [
            dir: []
            file: []
        ]
    ]
    show-dir-tree: func[
        "Displays all directories in the dir map"
        /with-files "displays the files as well"
    ][
        init
        actions/dir: [
            pad: copy ""
            prin head insert/dup pad "-" (-1 - cur-depth)
            probe cur-filename
        ]
        
        if with-files [actions/file: actions/dir]
        go-thru-map map
    ]
    search-changes: func [/since sinc][
        init
        if since [since-date: sinc]
        actions/dir: [
            if cur-data/2 > since-date [
                pad: copy ""
                prin head insert/dup pad "-" (-1 - cur-depth)
                print [mold cur-filename cur-data/2]
                print mold full-path
                probe dir-mapper/Get-item-info full-path
            ]       
            ;print mold full-path
        ] 
        go-thru-map map
    ]
    
    Get-file-types: func[ /local f][
        result: copy []
        actions/file: [
            if found? f: find/last cur-filename "." [
                file-type: copy skip cur-filename index? f
                if not found? find result file-type [append result file-type]
            ]
        ]
        go-thru-map map
        result
    ]
    search: func[query-str /local f][
        init
        result: copy []
        actions/file: actions/dir: [
            if found? find/any (f: join full-path cur-filename) query-str [
                append result f
                probe f
            ]
        ]
        go-thru-map map
        result
    ]
    statistics: func[stat-map [block!]][
        init
        ;stat-map: [["html" "htm"] "css" "js"]
        counters: copy []
        sizes: copy []
        insert/dup counters 0 (length? stat-map)
        insert/dup sizes make decimal! 0 (length? stat-map)
        total-files: 0
        ;actions/dir: [print mold full-path]
        actions/file: [
            total-files: total-files + 1
            counted?: false
            while [all [not tail? stat-map not counted?]][
                i: index? stat-map
                file-types: stat-map/1
                if not block? file-types [file-types: append copy [] file-types]
                forall file-types [
                    if (found? find cur-filename join "." file-types/1) and (not counted?) [
                        ;print cur-filename
                        poke counters i counters/:i + 1
                        if integer? cur-data/1 [
                            poke sizes i sizes/:i + cur-data/1 
                        ]
                        counted?: true
                    ]
                ]
                stat-map: next stat-map
            ]
            stat-map: head stat-map
        ]
        go-thru-map map
        reduce [counters sizes]
    ]
    
    parent-dir-path: func[dir /local f][
        if #"/" = last dir [remove back tail dir]
        either found? f: find/last dir "/" [
            copy/part dir index? f
        ][  join dir #"/" ]
    ] 
    go-thru-map: func[
        m   [block!]    "Map block"
        /depth d
    ][
        d: either all [depth integer? d] [d - 1 ][-1]
        while [not tail? m][
            cur-depth: d
            cur-filename: copy m/1
            cur-data: copy m/2
            m: either #"/" = last m/1 [
                full-path: join full-path cur-filename
                do actions/dir
                go-thru-map/depth m/3 d 
                full-path: parent-dir-path full-path
                skip m 3
            ][
                do actions/file
                skip m 2
            ]
        ]
    ]
]