Config file and CLI arg parser.

This commit is contained in:
Simon Forman 2018-07-21 17:56:53 -07:00
parent ca06c626e1
commit 33a952ff71
9 changed files with 428 additions and 47 deletions

View File

@ -0,0 +1,17 @@
see_stack == good_viewer_location open_stack
see_resources == list_resources good_viewer_location open_viewer
open_resource_at_good_location == good_viewer_location open_resource
see_log == "log.txt" open_resource_at_good_location
see_definitions == "definitions.txt" open_resource_at_good_location
round_to_cents == 100 * ++ floor 100 /
reset_log == "del log.lines[1:] ; log.at_line = 0" evaluate
see_menu == "menu.txt" good_viewer_location open_resource
# Ordered Binary Tree datastructure functions.
BTree-new == swap [[] []] cons cons
_BTree-P == over [popop popop first] nullary
_BTree-T> == [cons cons dipdd] cons cons cons infra
_BTree-T< == [cons cons dipd] cons cons cons infra
_BTree-E == pop swap roll< rest rest cons cons
_BTree-recur == _BTree-P [_BTree-T>] [_BTree-E] [_BTree-T<] cmp
BTree-add == [popop not] [[pop] dipd BTree-new] [] [_BTree-recur] genrec

View File

@ -0,0 +1,4 @@
Joypy - Copyright © 2018 Simon Forman
This program comes with ABSOLUTELY NO WARRANTY; for details right-click "warranty". This is free software, and you are welcome to redistribute it under certain conditions; right-click "sharing" for details. Right-click on these commands to see docs on UI commands: key_bindings mouse_bindings
<-

View File

@ -0,0 +1,120 @@
reset_log words mouse_bindings key_bindings
Stack Chatter
dup dupd dupdd over tuck
pop popd popdd popop popopd popopdd
swap roll< roll> rolldown rollup
unit clear
Math
add + sub - mul * truediv / mod %
div divmod floor pm
abs sqr sqrt neg pow
max min sum average product
pred -- succ ++ lshift << rshift >>
Logic
ge gt eq le lt ne
< <= = >= > != <>
and & or not xor ^
bool truthy ?
Combinators
i x b infra dip dipd dipdd dupdip dupdipd
cleave fork app1 app2 app3 map pam
nullary unary binary ternary
Control Flow
branch cond ifte choice
loop while genrec primrec
make_generator
List Manipulation
enstacken disenstacken stack unstack
first first_two second third fourth rest rrest
flatten drop take reverse select zip
size sort shunt getitem
step step_zero times
cons ccons uncons swons unswons
concat unique
remove
at of pick
unquoted quoted
Misc
down_to_zero cmp gcd help id
least_fraction parse quoted
range range_to_zero
reset_log show_log
run
stuncons stununcons
swaack
void
[ ] Add logging?
[ ] INI file?
[ ] definitions.txt
[ ] Integrate inference
[ ] command to (re-)run with trace
[ ] Backtime button?
------------------------------------------
[23 18] [unit i]
sqr foo == uncons mul
swaack
over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
5 sqrt 2 / 0.5 +
5 sqrt 1 + 2 /
phi == 5 sqrt ++ 2 /
phi == 1.618033988749895
(But this is Lambda Abstaction sneaking in the back door.)
=
clear
(n1 n2 -- ☯)
2018 20 18 20 23 0.5
472 83 / -7
100
100 * floor 100 / show_log
[2 3] [swap truediv] infra
dup infra key_bindings divmod
1 [dup 1 <<] make_generator 23 [x popd] times first
mcc91 == [100 >] [10 -] [11 + mcc91 mcc91] ifte
== [100 >] [10 -] [11 + [mcc91] [mcc91] b] ifte
== [100 >] [10 -] [11 + [mcc91] dup b] ifte
mcc91 == [100 >] [10 -] [11 +] [dup b] genrec
279841 20 20 20 202318 279841 279841 27984127984120202318
inscribe
round_to_cents == 100 * ++ floor 100 /
[12 18] [[pm] infra] make_generator
[12 18] [[[+] [3 /] fork popopdd] infra] make_generator
[stack] [pop] while

View File

@ -0,0 +1 @@
(t.

View File

@ -0,0 +1,53 @@
[key bindings]
<F5> = swap
<F6> = dup
<Shift-F5> = roll<
<Shift-F6> = roll>
<F7> = over
<Shift-F7> = tuck
<F8> = parse
<F12> = words
<F1> = reset_log show_log
<Escape> = clear reset_log show_log
<Control-Delete> = pop
<Control-i> = i
[Definitions]
of = swap at
product = 1 swap [*] step
flatten = [] swap [concat] step
quoted = [unit] dip
unquoted = [i] dip
enstacken = stack [clear] dip
? = dup truthy
disenstacken = ? [uncons ?] loop pop
dinfrirst = dip infra first
nullary = [stack] dinfrirst
unary = nullary popd
binary = nullary [popop] dip
ternary = unary [popop] dip
pam = [i] map
run = [] swap infra
sqr = dup mul
size = 0 swap [pop ++] step
fork = [i] app2
cleave = fork [popd] dip
average = [sum 1.0 *] [size] cleave /
gcd = 1 [tuck modulus dup 0 >] loop pop
least_fraction = dup [gcd] infra [div] concat map
*fraction = [uncons] dip uncons [swap] dip concat [*] infra [*] dip cons
*fraction0 = concat [[swap] dip * [*] dip] infra
down_to_zero = [0 >] [dup --] while
range_to_zero = unit [down_to_zero] infra
anamorphism = [pop []] swap [dip swons] genrec
range = [0 <=] [1 - dup] anamorphism
while = swap [nullary] cons dup dipd concat loop
dupdipd = dup dipd
primrec = [i] genrec
step_zero = 0 roll> step
codireco = cons dip rest cons
make_generator = [codireco] ccons
ifte = [nullary not] dipd branch

124
joy/gui/init_joy_home.py Normal file
View File

@ -0,0 +1,124 @@
'''
Utility module to help with setting up the initial contents of the
JOY_HOME directory.
These contents are kept in this Python module as a base64-encoded zip
file, so you can just do, e.g.:
import init_joy_home
init_joy_home.initialize(JOY_HOME)
'''
import base64, os, StringIO, zipfile
def initialize(joy_home):
Z.extractall(joy_home)
def create_data(from_dir='./default_joy_home'):
f = StringIO.StringIO()
z = zipfile.ZipFile(f, mode='w')
for fn in os.listdir(from_dir):
from_fn = os.path.join(from_dir, fn)
z.write(from_fn, fn)
z.close()
return base64.encodestring(f.getvalue())
Z = zipfile.ZipFile(StringIO.StringIO(base64.decodestring('''\
UEsDBBQAAAAAAKW29EyLEfLTUQgAAFEIAAALAAAAc2NyYXRjaC50eHRyZXNldF9sb2cgd29yZHMg
bW91c2VfYmluZGluZ3Mga2V5X2JpbmRpbmdzCgpTdGFjayBDaGF0dGVyCgogZHVwIGR1cGQgZHVw
ZGQgb3ZlciB0dWNrCiBwb3AgcG9wZCBwb3BkZCBwb3BvcCBwb3BvcGQgcG9wb3BkZAogc3dhcCBy
b2xsPCByb2xsPiByb2xsZG93biByb2xsdXAgCiB1bml0IGNsZWFyCgpNYXRoCgogYWRkICsgc3Vi
IC0gbXVsICogdHJ1ZWRpdiAvIG1vZCAlCiBkaXYgZGl2bW9kIGZsb29yIHBtCiBhYnMgc3FyIHNx
cnQgbmVnIHBvdwogbWF4IG1pbiBzdW0gYXZlcmFnZSBwcm9kdWN0CiBwcmVkIC0tIHN1Y2MgKysg
bHNoaWZ0IDw8IHJzaGlmdCA+PgoKTG9naWMKCiBnZSBndCBlcSBsZSBsdCBuZQogIDwgPD0gPSAg
Pj0gPiAgIT0gPD4KIGFuZCAmIG9yIG5vdCB4b3IgXgogYm9vbCB0cnV0aHkgPwoKQ29tYmluYXRv
cnMKCiBpIHggYiBpbmZyYSBkaXAgZGlwZCBkaXBkZCBkdXBkaXAgZHVwZGlwZAogY2xlYXZlIGZv
cmsgYXBwMSBhcHAyIGFwcDMgbWFwIHBhbQogbnVsbGFyeSB1bmFyeSBiaW5hcnkgdGVybmFyeSAK
CkNvbnRyb2wgRmxvdwoKIGJyYW5jaCBjb25kIGlmdGUgY2hvaWNlCiBsb29wIHdoaWxlIGdlbnJl
YyBwcmltcmVjCiBtYWtlX2dlbmVyYXRvcgoKTGlzdCBNYW5pcHVsYXRpb24KCiBlbnN0YWNrZW4g
ZGlzZW5zdGFja2VuIHN0YWNrIHVuc3RhY2sKIGZpcnN0IGZpcnN0X3R3byBzZWNvbmQgdGhpcmQg
Zm91cnRoIHJlc3QgcnJlc3QKIGZsYXR0ZW4gZHJvcCB0YWtlIHJldmVyc2Ugc2VsZWN0IHppcAog
c2l6ZSBzb3J0IHNodW50IGdldGl0ZW0KIHN0ZXAgc3RlcF96ZXJvIHRpbWVzIAogY29ucyBjY29u
cyB1bmNvbnMgc3dvbnMgdW5zd29ucwogY29uY2F0IHVuaXF1ZQogcmVtb3ZlCiBhdCBvZiBwaWNr
CiB1bnF1b3RlZCBxdW90ZWQKCk1pc2MKCiBkb3duX3RvX3plcm8gY21wIGdjZCBoZWxwIGlkIAog
bGVhc3RfZnJhY3Rpb24gcGFyc2UgcXVvdGVkCiByYW5nZSByYW5nZV90b196ZXJvCiByZXNldF9s
b2cgIHNob3dfbG9nCiBydW4gCiBzdHVuY29ucyBzdHVudW5jb25zCiBzd2FhY2sgCiB2b2lkICAg
ICAKCgpbIF0gQWRkIGxvZ2dpbmc/ClsgXSBJTkkgZmlsZT8KWyBdIGRlZmluaXRpb25zLnR4dApb
IF0gSW50ZWdyYXRlIGluZmVyZW5jZQpbIF0gY29tbWFuZCB0byAocmUtKXJ1biB3aXRoIHRyYWNl
ClsgXSBCYWNrdGltZSBidXR0b24/CgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tClsyMyAxOF0gICBbdW5pdCBpXQoKc3FyICBmb28gPT0gdW5jb25zIG11bAoKIHN3
YWFjawoKIG92ZXIgW1tbbmVnXSBkdXBkaXAgc3FyIDRdIGRpcGQgKiAqIC0gc3FydCBwbV0gZGlw
IDIgKiBbL10gY29ucyBhcHAyCgo1IHNxcnQgMiAvIDAuNSArCjUgc3FydCAxICsgMiAvCnBoaSA9
PSA1IHNxcnQgKysgMiAvCnBoaSA9PSAxLjYxODAzMzk4ODc0OTg5NQooQnV0IHRoaXMgaXMgTGFt
YmRhIEFic3RhY3Rpb24gc25lYWtpbmcgaW4gdGhlIGJhY2sgZG9vci4pCj0KY2xlYXIKCihuMSBu
MiAtLSDimK8pCgoyMDE4IDIwIDE4IDIwIDIzIDAuNQo0NzIgODMgLyAtNwoxMDAKCjEwMCAqIGZs
b29yIDEwMCAvICBzaG93X2xvZwoKWzIgM10gW3N3YXAgdHJ1ZWRpdl0gaW5mcmEKCmR1cCBpbmZy
YSBrZXlfYmluZGluZ3MgZGl2bW9kCgogIDEgW2R1cCAxIDw8XSBtYWtlX2dlbmVyYXRvciAgIDIz
IFt4IHBvcGRdIHRpbWVzIGZpcnN0CgptY2M5MSA9PSBbMTAwID5dIFsxMCAtXSBbMTEgKyBtY2M5
MSBtY2M5MV0gaWZ0ZQogICAgICA9PSBbMTAwID5dIFsxMCAtXSBbMTEgKyBbbWNjOTFdIFttY2M5
MV0gYl0gaWZ0ZQogICAgICA9PSBbMTAwID5dIFsxMCAtXSBbMTEgKyBbbWNjOTFdIGR1cCBiXSBp
ZnRlCm1jYzkxID09IFsxMDAgPl0gWzEwIC1dIFsxMSArXSBbZHVwIGJdIGdlbnJlYwoKMjc5ODQx
IDIwIDIwIDIwIDIwMjMxOCAyNzk4NDEgMjc5ODQxIDI3OTg0MTI3OTg0MTIwMjAyMzE4CgppbnNj
cmliZQoKcm91bmRfdG9fY2VudHMgPT0gMTAwICogKysgZmxvb3IgMTAwIC8KCgogICAgWzEyIDE4
XSBbW3BtXSBpbmZyYV0gbWFrZV9nZW5lcmF0b3IKCiAgICBbMTIgMThdIFtbWytdIFszIC9dIGZv
cmsgcG9wb3BkZF0gaW5mcmFdIG1ha2VfZ2VuZXJhdG9yCgogICBbc3RhY2tdIFtwb3BdIHdoaWxl
CgoKClBLAwQUAAAAAABAQfVM5+RkR1EBAABRAQAABwAAAGxvZy50eHRKb3lweSAtIENvcHlyaWdo
dCDCqSAyMDE4IFNpbW9uIEZvcm1hbgpUaGlzIHByb2dyYW0gY29tZXMgd2l0aCBBQlNPTFVURUxZ
IE5PIFdBUlJBTlRZOyBmb3IgZGV0YWlscyByaWdodC1jbGljayAid2FycmFudHkiLiBUaGlzIGlz
IGZyZWUgc29mdHdhcmUsIGFuZCB5b3UgYXJlIHdlbGNvbWUgdG8gcmVkaXN0cmlidXRlIGl0IHVu
ZGVyIGNlcnRhaW4gY29uZGl0aW9uczsgcmlnaHQtY2xpY2sgInNoYXJpbmciIGZvciBkZXRhaWxz
LiBSaWdodC1jbGljayBvbiB0aGVzZSBjb21tYW5kcyB0byBzZWUgZG9jcyBvbiBVSSBjb21tYW5k
czoga2V5X2JpbmRpbmdzIG1vdXNlX2JpbmRpbmdzCgogPC0KUEsDBBQAAAAAAEFB9Ux3f5peAwAA
AAMAAAAMAAAAc3RhY2sucGlja2xlKHQuUEsDBBQAAAAAAHy09ExY7AlUJgUAACYFAAALAAAAdGh1
bi5jb25maWcKW2tleSBiaW5kaW5nc10KPEY1PiA9IHN3YXAKPEY2PiA9IGR1cAo8U2hpZnQtRjU+
ID0gcm9sbDwKPFNoaWZ0LUY2PiA9IHJvbGw+CjxGNz4gPSBvdmVyCjxTaGlmdC1GNz4gPSB0dWNr
CjxGOD4gPSBwYXJzZQo8RjEyPiA9IHdvcmRzCjxGMT4gPSByZXNldF9sb2cgc2hvd19sb2cKPEVz
Y2FwZT4gPSBjbGVhciByZXNldF9sb2cgc2hvd19sb2cKPENvbnRyb2wtRGVsZXRlPiA9IHBvcAo8
Q29udHJvbC1pPiA9IGkKCgpbRGVmaW5pdGlvbnNdCm9mID0gc3dhcCBhdApwcm9kdWN0ID0gMSBz
d2FwIFsqXSBzdGVwCmZsYXR0ZW4gPSBbXSBzd2FwIFtjb25jYXRdIHN0ZXAKcXVvdGVkID0gW3Vu
aXRdIGRpcAp1bnF1b3RlZCA9IFtpXSBkaXAKZW5zdGFja2VuID0gc3RhY2sgW2NsZWFyXSBkaXAK
PyA9IGR1cCB0cnV0aHkKZGlzZW5zdGFja2VuID0gPyBbdW5jb25zID9dIGxvb3AgcG9wCmRpbmZy
aXJzdCA9IGRpcCBpbmZyYSBmaXJzdApudWxsYXJ5ID0gW3N0YWNrXSBkaW5mcmlyc3QKdW5hcnkg
PSBudWxsYXJ5IHBvcGQKYmluYXJ5ID0gbnVsbGFyeSBbcG9wb3BdIGRpcAp0ZXJuYXJ5ID0gdW5h
cnkgW3BvcG9wXSBkaXAKcGFtID0gW2ldIG1hcApydW4gPSBbXSBzd2FwIGluZnJhCnNxciA9IGR1
cCBtdWwKc2l6ZSA9IDAgc3dhcCBbcG9wICsrXSBzdGVwCmZvcmsgPSBbaV0gYXBwMgpjbGVhdmUg
PSBmb3JrIFtwb3BkXSBkaXAKYXZlcmFnZSA9IFtzdW0gMS4wICpdIFtzaXplXSBjbGVhdmUgLwpn
Y2QgPSAxIFt0dWNrIG1vZHVsdXMgZHVwIDAgPl0gbG9vcCBwb3AKbGVhc3RfZnJhY3Rpb24gPSBk
dXAgW2djZF0gaW5mcmEgW2Rpdl0gY29uY2F0IG1hcAoqZnJhY3Rpb24gPSBbdW5jb25zXSBkaXAg
dW5jb25zIFtzd2FwXSBkaXAgY29uY2F0IFsqXSBpbmZyYSBbKl0gZGlwIGNvbnMKKmZyYWN0aW9u
MCA9IGNvbmNhdCBbW3N3YXBdIGRpcCAqIFsqXSBkaXBdIGluZnJhCmRvd25fdG9femVybyA9IFsw
ID5dIFtkdXAgLS1dIHdoaWxlCnJhbmdlX3RvX3plcm8gPSB1bml0IFtkb3duX3RvX3plcm9dIGlu
ZnJhCmFuYW1vcnBoaXNtID0gW3BvcCBbXV0gc3dhcCBbZGlwIHN3b25zXSBnZW5yZWMKcmFuZ2Ug
PSBbMCA8PV0gWzEgLSBkdXBdIGFuYW1vcnBoaXNtCndoaWxlID0gc3dhcCBbbnVsbGFyeV0gY29u
cyBkdXAgZGlwZCBjb25jYXQgbG9vcApkdXBkaXBkID0gZHVwIGRpcGQKcHJpbXJlYyA9IFtpXSBn
ZW5yZWMKc3RlcF96ZXJvID0gMCByb2xsPiBzdGVwCmNvZGlyZWNvID0gY29ucyBkaXAgcmVzdCBj
b25zCm1ha2VfZ2VuZXJhdG9yID0gW2NvZGlyZWNvXSBjY29ucwppZnRlID0gW251bGxhcnkgbm90
XSBkaXBkIGJyYW5jaAoKUEsDBBQAAAAAAEK0k0yW6MvDbQMAAG0DAAAPAAAAZGVmaW5pdGlvbnMu
dHh0c2VlX3N0YWNrID09IGdvb2Rfdmlld2VyX2xvY2F0aW9uIG9wZW5fc3RhY2sKc2VlX3Jlc291
cmNlcyA9PSBsaXN0X3Jlc291cmNlcyBnb29kX3ZpZXdlcl9sb2NhdGlvbiBvcGVuX3ZpZXdlcgpv
cGVuX3Jlc291cmNlX2F0X2dvb2RfbG9jYXRpb24gPT0gZ29vZF92aWV3ZXJfbG9jYXRpb24gb3Bl
bl9yZXNvdXJjZQpzZWVfbG9nID09ICJsb2cudHh0IiBvcGVuX3Jlc291cmNlX2F0X2dvb2RfbG9j
YXRpb24Kc2VlX2RlZmluaXRpb25zID09ICJkZWZpbml0aW9ucy50eHQiIG9wZW5fcmVzb3VyY2Vf
YXRfZ29vZF9sb2NhdGlvbgpyb3VuZF90b19jZW50cyA9PSAxMDAgKiArKyBmbG9vciAxMDAgLwpy
ZXNldF9sb2cgPT0gImRlbCBsb2cubGluZXNbMTpdIDsgbG9nLmF0X2xpbmUgPSAwIiBldmFsdWF0
ZQpzZWVfbWVudSA9PSAibWVudS50eHQiIGdvb2Rfdmlld2VyX2xvY2F0aW9uIG9wZW5fcmVzb3Vy
Y2UKCiMgT3JkZXJlZCBCaW5hcnkgVHJlZSBkYXRhc3RydWN0dXJlIGZ1bmN0aW9ucy4KQlRyZWUt
bmV3ID09IHN3YXAgW1tdIFtdXSBjb25zIGNvbnMKIF9CVHJlZS1QID09IG92ZXIgW3BvcG9wIHBv
cG9wIGZpcnN0XSBudWxsYXJ5CiBfQlRyZWUtVD4gPT0gW2NvbnMgY29ucyBkaXBkZF0gY29ucyBj
b25zIGNvbnMgaW5mcmEKIF9CVHJlZS1UPCA9PSBbY29ucyBjb25zIGRpcGRdIGNvbnMgY29ucyBj
b25zIGluZnJhCiBfQlRyZWUtRSA9PSBwb3Agc3dhcCByb2xsPCByZXN0IHJlc3QgY29ucyBjb25z
CiBfQlRyZWUtcmVjdXIgPT0gX0JUcmVlLVAgW19CVHJlZS1UPl0gW19CVHJlZS1FXSBbX0JUcmVl
LVQ8XSBjbXAKQlRyZWUtYWRkID09IFtwb3BvcCBub3RdIFtbcG9wXSBkaXBkIEJUcmVlLW5ld10g
W10gW19CVHJlZS1yZWN1cl0gZ2VucmVjClBLAQIUAxQAAAAAAKW29EyLEfLTUQgAAFEIAAALAAAA
AAAAAAAAAACAgQAAAABzY3JhdGNoLnR4dFBLAQIUAxQAAAAAAEBB9Uzn5GRHUQEAAFEBAAAHAAAA
AAAAAAAAAACAgXoIAABsb2cudHh0UEsBAhQDFAAAAAAAQUH1THd/ml4DAAAAAwAAAAwAAAAAAAAA
AAAAAICB8AkAAHN0YWNrLnBpY2tsZVBLAQIUAxQAAAAAAHy09ExY7AlUJgUAACYFAAALAAAAAAAA
AAAAAAC0gR0KAAB0aHVuLmNvbmZpZ1BLAQIUAxQAAAAAAEK0k0yW6MvDbQMAAG0DAAAPAAAAAAAA
AAAAAAC0gWwPAABkZWZpbml0aW9ucy50eHRQSwUGAAAAAAUABQAeAQAABhMAAAAA''')))
if __name__ == '__main__':
print create_data()

View File

@ -8,15 +8,16 @@ Joypy - Copyright © 2018 Simon Forman
' right-click "sharing" for details.' ' right-click "sharing" for details.'
' Right-click on these commands to see docs on UI commands: key_bindings mouse_bindings') ' Right-click on these commands to see docs on UI commands: key_bindings mouse_bindings')
import logging, os, pickle, sys import logging, os, pickle, sys
from textwrap import dedent
from ConfigParser import RawConfigParser
from joy.gui.utils import init_home, argparser, FileFaker
args = argparser.parse_args()
JOY_HOME = args.joy_home
_log = logging.getLogger(__name__) _log = logging.getLogger(__name__)
from textwrap import dedent
from joy.gui.utils import init_home, FileFaker
JOY_HOME, repo = init_home()
logging.basicConfig( logging.basicConfig(
format='%(asctime)-15s %(levelname)s %(name)s %(message)s', format='%(asctime)-15s %(levelname)s %(name)s %(message)s',
filename=os.path.join(JOY_HOME, 'thun.log'), filename=os.path.join(JOY_HOME, 'thun.log'),
@ -24,12 +25,24 @@ logging.basicConfig(
) )
repo = init_home(JOY_HOME)
from joy.gui.textwidget import TextViewerWidget, tk, get_font, TEXT_BINDINGS from joy.gui.textwidget import TextViewerWidget, tk, get_font, TEXT_BINDINGS
from joy.gui.world import StackDisplayWorld from joy.gui.world import StackDisplayWorld
from joy.library import initialize from joy.library import initialize
from joy.utils.stack import stack_to_string from joy.utils.stack import stack_to_string
cp = RawConfigParser()
cp.optionxform = str # Don't mess with uppercase.
with open(os.path.join(args.joy_home, 'thun.config')) as f:
cp.readfp(f)
GLOBAL_COMMANDS = dict(cp.items('key bindings'))
tb = TEXT_BINDINGS.copy() tb = TEXT_BINDINGS.copy()
tb.update({ tb.update({
'<F3>': lambda tv: tv.copy_selection_to_stack, '<F3>': lambda tv: tv.copy_selection_to_stack,
@ -40,21 +53,6 @@ tb.update({
defaults = dict(text_bindings=tb, width=80, height=25) defaults = dict(text_bindings=tb, width=80, height=25)
GLOBAL_COMMANDS = {
'<F5>': 'swap',
'<F6>': 'dup',
'<Shift-F5>': 'roll<',
'<Shift-F6>': 'roll>',
'<F7>': 'over',
'<Shift-F7>': 'tuck',
'<F8>': 'parse',
'<F12>': 'words',
'<F1>': 'reset_log show_log',
'<Escape>': 'clear reset_log show_log',
'<Control-Delete>': 'pop',
}
def repo_relative_path(path): def repo_relative_path(path):
return os.path.relpath( return os.path.relpath(
path, path,

View File

@ -1,35 +1,81 @@
import os import argparse, os, sys
from os import listdir, mkdir
from os.path import abspath, exists, expanduser, isfile, join
from dulwich.errors import NotGitRepository from dulwich.errors import NotGitRepository
from dulwich.repo import Repo from dulwich.repo import Repo
def init_home(): COMMITTER = 'Joy <auto-commit@example.com>'
''' DEFAULT_JOY_HOME = '~/.joypy'
Find and initialize the Joy home directory and repository.
'''
JOY_HOME = os.environ.get('JOY_HOME')
if JOY_HOME is None:
JOY_HOME = os.path.expanduser('~/.joypy')
if not os.path.isabs(JOY_HOME):
JOY_HOME = os.path.abspath('./JOY_HOME')
#print 'JOY_HOME=' + JOY_HOME
if not os.path.exists(JOY_HOME):
#print 'creating...'
os.makedirs(JOY_HOME, 0700)
#print 'initializing git repository...'
repo = Repo.init(JOY_HOME)
else: # path does exist def home_dir(path):
try: '''Return the absolute path of an existing directory.'''
repo = Repo(JOY_HOME)
except NotGitRepository: fullpath = expanduser(path) if path.startswith('~') else abspath(path)
#print 'initializing git repository...'
repo = Repo.init(JOY_HOME) if not exists(fullpath):
#else: if path == DEFAULT_JOY_HOME:
#print 'opened git repository.' print 'Creating JOY_HOME', repr(fullpath)
return JOY_HOME, repo mkdir(fullpath, 0700)
else:
print >> sys.stderr, repr(fullpath), "doesn't exist."
raise ValueError(path)
return fullpath
def init_home(fullpath):
'''
Open or create the Repo.
If there are contents in the dir but it's not a git repo, quit.
'''
try:
repo = Repo(fullpath)
except NotGitRepository:
print >> sys.stderr, repr(fullpath), "no repository"
if listdir(fullpath):
print >> sys.stderr, repr(fullpath), "has contents\nQUIT."
sys.exit(2)
print 'Initializing repository in', fullpath
repo = init_repo(fullpath)
print 'Using repository in', fullpath
return repo
def init_repo(repo_dir):
'''
Create a repo, load the initial content, and make the first commit.
Return the Repo object.
'''
repo = Repo.init(repo_dir)
import joy.gui.init_joy_home
joy.gui.init_joy_home.initialize(repo_dir)
repo.stage([
fn
for fn in listdir(repo_dir)
if isfile(join(repo_dir, fn))
])
repo.do_commit('Initial commit.', committer=COMMITTER)
return repo
argparser = argparse.ArgumentParser(
description='Experimental Brutalist UI for Joy.',
)
argparser.add_argument(
'-j', '--joy-home',
help='Use a directory other than %s as JOY_HOME' % DEFAULT_JOY_HOME,
default=DEFAULT_JOY_HOME,
dest='joy_home',
type=home_dir,
)
class FileFaker(object): class FileFaker(object):

View File

@ -1,4 +1,22 @@
# -*- coding: utf_8 # -*- coding: utf_8
#
# Copyright © 2018 Simon Forman
#
# This file is part of Thun
#
# Thun 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, either version 3 of the License, or
# (at your option) any later version.
#
# Thun 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 Thun. If not see <http://www.gnu.org/licenses/>.
#
from logging import getLogger, addLevelName from logging import getLogger, addLevelName
_log = getLogger(__name__) _log = getLogger(__name__)