I’ve been looking for a simple free ftp editor. There is one here but it isn’t free. That’s why I decided to craft this poor-man ftp editor. Of course I’m too lazy to craft it from scratch. So I will use the hidden source editor included with Rebol!
Yes, Rebol has an small editor that you can launch by typing:
editor none

To get the source of the Editor, type this:
write clipboard:// mold :editor
Paste it into notepad, you should get this:
func [file /app app-word /local tmp][
either link? [
if block? ctx-edit [
ctx-edit: context either all [
value? 'fileset-files?
tmp: fileset-files? 'desktop
find tmp %desktop/edit.r
tmp: load/header link-root/desktop/edit.r
] [next tmp] [ctx-edit]
]
either app [ctx-edit/view-file/app file app-word] [ctx-edit/view-file file]
] [
either exists? tmp: view-root/desktop/scripts/edit.r [do/args tmp file] [
if block? ctx-edit [ctx-edit: context ctx-edit]
ctx-edit/view-file file
]
]
]
The source above shows that it is a wrapper for ctx-edit, so let’s get the source of ctx-edit by typing:
write clipboard:// mold :ctx-edit
which gives this block of code for the core implementation:
[
prefs: either link? [link-root/edit-prefs.r] [view-root/edit-prefs.r]
dirty-edit: false
this-file: none
this-app: none
t1: s1: h1: f1: none
edit-prefs: context [
offset: 40x40
size: 640x480
wrap: on
]
ed-lo: layout/offset [
style tx vtext bold 40x22 font [colors: [0.0.0 200.200.200]] middle center
size 640x320 origin 0 space 0 across
tx "Open" [open-as]
tx "New" [new-file]
tx "Find" [find-text]
tx "Save" [save-file]
tx "Save-As" 60 [save-as]
tx "Help" [show-help]
tx "Quit" [quit-edit]
pad 8
text "File:" bold black right middle 30x22
h1: at
f1: info 300x22 base-color + 40.40.40
return
t1: area 624x320 font [name: font-fixed] para [tabs: 28 origin: 4x4]
[dirty-edit: any [dirty-edit face/dirty?]]
with [color: snow feel: make feel [redraw: none]]
s1: scroller 16x320 [scroll-para t1 s1]
] 0x0
ed-lo/color: base-color
t1/flags: []
save-lo: layout [
origin 10x10 space 8x4
backeffect base-effect
style btn btn 140
text bold "Save your changes?" 140 center
pad 0x4
btn-enter 140 "Save" #"s" [hide-popup result: save-file]
btn green "Save As..." [hide-popup result: save-as]
btn red + 50 "Quit - No Save" [hide-popup quit-now]
btn-cancel 140 "Cancel" [hide-popup]
]
save-lo/color: base-color
ff: fb: fc: fp: none
find-lo: layout [
space 4x4 across
origin 16x16
backeffect base-effect
lab 32 "Find:"
ff: field [search ff/text fc/data false]
pad 4
fb: btn-enter 80 "Find" [search ff/text fc/data false]
return
at ff/offset + 0x32
fc: check text "Match case"
at fb/offset + 0x32
btn-cancel 80 "Cancel" [unview/only find-lo]
return
pad 32 vtext bold "Hint: Use Ctrl-G to find next."
]
find-lo/color: base-color
deflag-face ff tabbed
resize: func [size] [
ed-lo/size: size
t1/size: size - (s1/size * 1x0) - (f1/size * 0x1)
s1/offset/x: t1/offset/x + t1/size/x
s1/resize/y t1/size/y
f1/size/x: size/x - h1/x
t1/line-list: none
]
refresh: does [
show ed-lo
s1/redrag t1/size/y / max 1 second size-text t1
show s1
]
save-prefs: has [str] [
str: copy ""
edit-prefs/offset: ed-lo/offset
edit-prefs/size: ed-lo/size
foreach w next first edit-prefs [
append str rejoin [w ": " edit-prefs/:w newline]
]
write prefs str
]
open-as: has [file] [
if not save-edit [exit]
file: request-file/keep/file/title this-file "Select a file to open:" "Open"
if not all [file file: pick file 1] [return false]
open-file file
]
new-file: does [
if not save-edit [exit]
open-file none
]
save-as: has [file] [
file: any [this-file %temp.txt]
file: request-file/keep/file/title/save file "Save file as:" "Save"
if not all [file file: pick file 1] [return false]
this-file: file
save-file
true
]
save-file: has [file] [
if not this-file [return save-as]
f1/text: this-file
f1/color: gold show f1
write this-file t1/text
wait 0.2
f1/color: base-color + 40.40.40 show f1
dirty-edit: t1/dirty?: false
if all [
link?
value? 'send-server
this-app
link-sync-connected?
file: fileset-files? this-app
find file link-relative-path this-file
request/confirm "Upload the modified file back to the server?"
] [up-file]
true
]
up-file: does [
if all [link? value? 'add-file this-app] [
add-file this-app link-relative-path this-file
]
]
open-file: func [file /local txt] [
if file = 'same [file: this-file]
f1/text: this-file: none
txt: copy ""
case [
none? file []
any [file? file url? file] [
f1/text: this-file: file
either error? try [txt: read file] [
request/ok reform ["Cannot read file:" file]
] [
f1/text: this-file: file
]
]
any-string? file [txt: form file]
true [txt: mold file]
]
ed-lo/changes: [activate text]
ed-lo/text: form-title file
show ed-lo
dirty-edit: false
t1/dirty?: false
s1/data: 0
t1/para/scroll: 0x0
t1/text: t1/data: copy txt
t1/line-list: none
unfocus
refresh
focus t1
]
result: none
ask-save: does [result: none inform save-lo result]
save-edit: does [either any [dirty-edit t1/dirty?] [ask-save] [true]]
do-file: does [
save-file
either link? [start-app/method this-file 'doer] [
if any [file? this-file url? this-file] [launch/secure-cmd this-file]
]
]
quit-edit: does [if save-edit [quit-now]]
quit-now: does [
if viewed? find-lo [unview/only find-lo]
unview/only ed-lo
dirty-edit: false
t1/dirty?: false
]
caret: none
start: none
last-str: last-case: last-pat: none
find-text: does [
caret: system/view/caret
view/new/title find-lo "Find"
find-lo/changes: 'activate
show find-lo
focus ff
]
search: func [str case pat] [
unview/only find-lo
start: any [caret t1/text]
last-str: str
last-case: case
last-pat: pat
find-str str case pat
]
find-str: func [str case pat] [
if not find-next str case pat [
start: none
if not find-next str case pat [system/view/caret: caret]
]
]
find-again: does [
start: any [system/view/caret t1/text]
if last-str [find-str last-str last-case last-pat]
]
find-next: func [str case pat /local txt] [
if txt: find' any [start t1/text] str case pat none [
focus t1
system/view/caret: txt
if not pat [
system/view/highlight-start: txt
system/view/caret:
system/view/highlight-end: start: find' txt str case pat true
]
scroll-to txt
true
]
]
find': func [txt str case pat tal /local code p] [
code: copy [find txt str]
if any [case pat tal] [
change/only code p: make path! [find]
if case [insert tail :p 'case]
if pat [insert tail :p 'any]
if tal [insert tail :p 'tail]
]
do code
]
scroll-to: func [txt /local xy] [
xy: (caret-to-offset t1 txt) - t1/para/scroll
t1/para/scroll: min 0x0 t1/size / 2 - xy
s1/data: (second xy) / max 1 second size-text t1
show [s1 t1]
]
show-help: does [
view/new/title center-face layout [
origin 10
backeffect base-effect
h2 "Editor Shortcuts:"
text as-is help-text black snow edge [size: 1x1 color: coal] para [origin: margin: 10x10]
indent 50
btn-cancel 72 "Close" [unview/only face/parent-face]
]
"Editor Help"
]
help-text: trim/auto {
^-^-Ctrl-A - select all text
^-^-Ctrl-C - copy text
^-^-Ctrl-X - cut text / cut all
^-^-Ctrl-V - paste text
^-^-Ctrl-Q - to quit
^-^-Ctrl-S - to save changes
^-^-Ctrl-O - to open a file
^-^-Ctrl-N - to create a new file
^-^-Ctrl-T - Trim line to end
^-^-Ctrl-E (F5) - to execute (do)
^-^-Ctrl-F (F3) - to find text
^-^-Ctrl-G - to find next text}
keymap: [
#"^S" [save-file]
#"^W" [quit-edit]
#"^Q" [quit-edit]
#"^O" [open-as]
#"^N" [new-file]
#"^E" [do-file]
#"^F" [find-text]
#"^G" [find-again]
F3 [find-text]
F5 [do-file]
page-up [scroll-edit true -1]
page-down [scroll-edit true 1]
]
scroll-edit: func [page n] [
s1/data: s1/data + (n *
(either page [t1/size/y] [t1/font/size]) / max 1 second size-text t1
)
show s1
scroll-para t1 s1
]
init: does [
ed-lo/feel: make ed-lo/feel [
detect: func [face event] [
switch event/type [
offset [save-prefs]
scroll-line [scroll-edit false event/offset/y]
scroll-page [scroll-edit true event/offset/y]
resize [
resize max 100x64 ed-lo/size
refresh
save-prefs
return true
]
key [switch event/key keymap]
close [quit-edit]
]
event
]
]
]
form-title: func [val] [
val: if any [file? val url? val] [second split-path val]
reform ["Edit:" any [val "new"]]
]
view-file: func [file /app app-word] [
if not save-edit [exit]
if app [this-app: app-word]
t1/text: none
t1/line-list: none
if not viewed? ed-lo [
if exists? prefs [edit-prefs: make edit-prefs load/all prefs]
t1/para/wrap?: edit-prefs/wrap
ed-lo/offset: edit-prefs/offset
if outside? system/view/screen-face/size ed-lo/offset + 20x20 [
ed-lo/offset: 40x40
save-prefs
]
resize edit-prefs/size
ed-lo/text: form-title file
view/new/options ed-lo [resize]
init
center-face/with find-lo ed-lo
if not overlap? find-lo system/view/screen-face [find-lo/offset: ed-lo/offset + 20]
]
open-file file
if 1 = length? system/view/screen-face/pane [do-events]
]
]
Under line:
tx "Save-As" 60 [save-as]
Add this line:
tx "Save-As-Ftp" 80 [save-as-ftp]
Under
save-as: has [file] [
file: any [this-file %temp.txt]
file: request-file/keep/file/title/save file "Save file as:" "Save"
if not all [file file: pick file 1] [return false]
this-file: file
save-file
true
]
Add
save-as-ftp: has [file][
print "to do"
]
On the very beginning of the first line add this line
ctx-edit: make Object!
just before the opening bracket to get this:
ctx-edit: make Object! [
prefs: either link? [link-root/edit-prefs.r] [view-root/edit-prefs.r]
dirty-edit: false
this-file: none
this-app: none
t1: s1: h1: f1: none
edit-prefs: context [
offset: 40x40
size: 640x480
wrap: on
]
Then copy and paste all into Rebol Console, validate and test by typing once again
editor none
You should see the new menu appear:

In future lesson, we’ll see how to implement it using what we already learned in “FTP Tutorial”. In this implementation we will ask for FTP parameters using a Visual GUI and persist them in a configuration file so as to avoid the User to remember and type them once again.
















No comments yet.