-
Notifications
You must be signed in to change notification settings - Fork 12
/
bivi.red
159 lines (155 loc) · 4.34 KB
/
bivi.red
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
Red[
Name: "BiVi - binary viewer"
Author: "Boleslav Březovský"
To-Do: [
"Clear internal console history on exit"
]
]
;do https://rebolek.com/redquire
;redquire 'ansi-seq
bivi!: context [
data: none
lines-per-page: 8 ; how many lines per page
line: 0
addout: []
mark-start: 0
mark-end: 0
last-match: none
pattern: none
numbers: charset "1234567890"
hex: charset "1234567890abcdefABCDEF"
trim-zeroes: func [value][first parse value [collect [some #"0" keep to end]]]
print-page: func [
line
/local value ret count infoline length
][
length: length? data
infoline: reduce [
'cls
'at 1x1 "Data length: "
'bold form length " (" trim-zeroes form to-hex length ")" 'reset
" | Page: " form line / lines-per-page "/" form length / lines-per-page / 16 - 1 space
]
append infoline addout
append infoline "^/"
ansi/do infoline
repeat j lines-per-page [
ansi/do print-line data line - 1 + j * 16
]
ret: line
count: 1
count-rule: [
(count: 1 value: none)
copy value any numbers
(unless empty? value [count: to integer! value])
]
main-rule: [
#"q" (ret: none)
| #"e" count-rule (ret: line + count) ; NEXT LINE ; TODO - check max value
| #"y" count-rule (ret: max 0 line - count) ; PREV LINE
| #"f" count-rule (ret: lines-per-page * count + line) ; TODO: limit at maximum ; NEXT PAGE - default action
| #"b" count-rule (ret: max 0 line - (count * lines-per-page)) ; PREV PAGE - line was already updated, so subtract it twice
| #"/" copy pattern to end (last-match: none ret: find-pattern) ; FIND <pattern>
| #"n" (ret: find-pattern) ; FIND NEXT
| #"l" copy value some numbers (lines-per-page: to integer! value) ; SET LINES PER PAGE
| copy value 4 hex (ret: (to integer! debase/base value 16) / 16)
| #"h" (print-help)
| (ret: lines-per-page * count + line)
]
parse ask ":" main-rule
if ret [ret: min ret length / 16 - 8]
ret
]
print-line: func [
"return line of 16 values"
data position
/local line hilite?
][
hilite?: false
line: copy/part at data position 16
bin-part: copy []
char-part: copy []
repeat i 16 [
char: to integer! line/:i
; -- highlight mark
if all [
not zero? mark-start
(position + i - 1) >= mark-start
(position + i - 1) <= mark-end
][
; TODO: turn on hilite only on mark start
hilite?: true
append bin-part 'inverse
append char-part 'inverse
]
; -- add character
append bin-part rejoin [form to-hex/size char 2 space]
append char-part case [
all [char > 31 char < 128][form to char! char]
any [char = 10 char = 13]["↵"]
char = 9 ["⇥"]
'default [dot]
]
; -- end highlighting
if hilite? [
; TODO: turn off hilite only after mark end
append bin-part 'reset
append char-part 'reset
hilite?: false
]
if i = 8 [
append bin-part space
append char-part space
]
]
compose [(form to-hex/size position 4) " | " (bin-part) "| " (char-part)]
]
find-pattern: func [
][
index: line + 1
unless last-match [last-match: data]
either mark: find last-match pattern [
last-match: next mark
mark-start: index? mark
mark-end: -1 + (index? mark) + length? pattern
print "in find"
index: (index? mark) / 16
addout: reduce ['bold pattern 'reset space "found at line" space 'bold form index 'reset]
][
index: line
if pattern [addout: reduce ['bold pattern 'reset space "not found." 'reset]]
]
index
]
print-help: does [
ansi/do [
cls
at 1x1
bold "^-NAVIGATION^/^/" reset
"Navigation commands can be followed by numbers to skip more lines/pages.^/^/"
bold "f^-ENTER" reset "^-next page^/"
bold "b" reset "^-^-previous page^/"
bold "e" reset "^-^-next line^/"
bold "y" reset "^-^-previous line^/^/"
bold "/" reset "<pattern>" "^-search for <pattern>^/"
bold "n" reset "^-^-repeat previous search^/^/"
bold "XXXX " reset italic "hex chars" reset "^-go to given offset^/"
"^/^/Press ENTER to continue^/"
]
input
]
history-mark: none
set 'bivi func [file][
history-mark: length? system/console/history
line: 0
data: file
if file? data [data: read/binary data] ; TODO: support url! also?
pages: (length? data) / lines-per-page
unless zero? (length? data) // lines-per-page [pages: pages + 1]
until [
none? line: print-page line
]
remove/part system/console/history (length? system/console/history) - history-mark
true
]
]