7
7
8
8
config_path = os .path .join (os .path .expanduser ('~' ), '.coreapi' )
9
9
10
- store_path = os .path .join (config_path , 'document.json' )
10
+ document_path = os .path .join (config_path , 'document.json' )
11
+ history_path = os .path .join (config_path , 'history.json' )
11
12
credentials_path = os .path .join (config_path , 'credentials.json' )
12
13
headers_path = os .path .join (config_path , 'headers.json' )
13
14
bookmarks_path = os .path .join (config_path , 'bookmarks.json' )
@@ -46,23 +47,23 @@ def get_session():
46
47
return coreapi .get_session (credentials , headers )
47
48
48
49
49
- def read_from_store ():
50
- if not os .path .exists (store_path ):
50
+ def get_document ():
51
+ if not os .path .exists (document_path ):
51
52
return None
52
- store = open (store_path , 'rb' )
53
+ store = open (document_path , 'rb' )
53
54
content = store .read ()
54
55
store .close ()
55
56
return coreapi .load (content )
56
57
57
58
58
- def write_to_store (doc ):
59
+ def set_document (doc ):
59
60
content_type , content = coreapi .dump (doc )
60
- store = open (store_path , 'wb' )
61
+ store = open (document_path , 'wb' )
61
62
store .write (content )
62
63
store .close ()
63
64
64
65
65
- def dump_to_console (doc ):
66
+ def display (doc ):
66
67
codec = coreapi .codecs .PlainTextCodec ()
67
68
return codec .dump (doc , colorize = True )
68
69
@@ -91,24 +92,33 @@ def client(ctx, version):
91
92
@click .argument ('url' )
92
93
def get (url ):
93
94
session = get_session ()
95
+ history = get_history ()
94
96
doc = session .get (url )
95
- click .echo (dump_to_console (doc ))
96
- write_to_store (doc )
97
+ history = history .add (doc )
98
+ click .echo (display (doc ))
99
+ set_document (doc )
100
+ set_history (history )
97
101
98
102
99
- @click .command (help = 'Remove the current document, and any stored credentials.' )
103
+ @click .command (help = 'Clear the active document and other state. \n \n This includes the current document, history, credentials, headers and bookmarks .' )
100
104
def clear ():
101
- if os .path .exists (store_path ):
102
- os .remove (store_path )
103
- if os .path .exists (credentials_path ):
104
- os .remove (credentials_path )
105
+ for path in [
106
+ document_path ,
107
+ history_path ,
108
+ credentials_path ,
109
+ headers_path ,
110
+ bookmarks_path
111
+ ]:
112
+ if os .path .exists (path ):
113
+ os .remove (path )
114
+
105
115
click .echo ('Cleared.' )
106
116
107
117
108
- @click .command (help = 'Display the current document, or element at the given PATH.' )
118
+ @click .command (help = 'Display the current document. \n \n Optionally display just the element at the given PATH.' )
109
119
@click .argument ('path' , nargs = - 1 )
110
120
def show (path ):
111
- doc = read_from_store ()
121
+ doc = get_document ()
112
122
if doc is None :
113
123
click .echo ('No current document. Use `coreapi get` to fetch a document first.' )
114
124
return
@@ -119,13 +129,13 @@ def show(path):
119
129
doc = doc [key ]
120
130
if isinstance (doc , (bool , type (None ))):
121
131
doc = {True : 'true' , False : 'false' , None : 'null' }[doc ]
122
- click .echo (dump_to_console (doc ))
132
+ click .echo (display (doc ))
123
133
124
134
125
135
def validate_params (ctx , param , value ):
126
136
if any (['=' not in item for item in value ]):
127
137
raise click .BadParameter ('Parameters need to be in format <field name>=<value>' )
128
- return value
138
+ return dict ([ tuple ( item . split ( '=' , 1 )) for item in param ])
129
139
130
140
131
141
def validate_inplace (ctx , param , value ):
@@ -136,7 +146,7 @@ def validate_inplace(ctx, param, value):
136
146
return value .lower () == 'true'
137
147
138
148
139
- @click .command (help = 'Interact with the current document, given a PATH to a link.' )
149
+ @click .command (help = 'Interact with the active document. \n \n Requires a PATH to a link in the document .' )
140
150
@click .argument ('path' , nargs = - 1 )
141
151
@click .option ('--param' , '-p' , multiple = True , callback = validate_params , help = 'Parameter in the form <field name>=<value>.' )
142
152
@click .option ('--action' , '-a' , help = 'Set the link action explicitly.' , default = None )
@@ -146,18 +156,35 @@ def action(path, param, action, inplace):
146
156
click .echo ('Missing PATH to a link in the document.' )
147
157
sys .exit (1 )
148
158
149
- params = dict ([tuple (item .split ('=' , 1 )) for item in param ])
150
-
151
- doc = read_from_store ()
159
+ doc = get_document ()
152
160
if doc is None :
153
161
click .echo ('No current document. Use `coreapi get` to fetch a document first.' )
154
162
return
155
163
156
164
session = get_session ()
165
+ history = get_history ()
157
166
keys = coerce_key_types (doc , path )
158
- doc = session .action (doc , keys , params = params , action = action , inplace = inplace )
159
- click .echo (dump_to_console (doc ))
160
- write_to_store (doc )
167
+ doc = session .action (doc , keys , params = param , action = action , inplace = inplace )
168
+ history = history .add (doc )
169
+ click .echo (display (doc ))
170
+ set_document (doc )
171
+ set_history (history )
172
+
173
+
174
+ @click .command (help = 'Reload the current document.' )
175
+ def reload_document ():
176
+ doc = get_document ()
177
+ if doc is None :
178
+ click .echo ('No current document. Use `coreapi get` to fetch a document first.' )
179
+ return
180
+
181
+ session = get_session ()
182
+ history = get_history ()
183
+ doc = session .reload (doc )
184
+ history = history .add (doc )
185
+ click .echo (display (doc ))
186
+ set_document (doc )
187
+ set_history (history )
161
188
162
189
163
190
# Credentials
@@ -177,7 +204,7 @@ def set_credentials(credentials):
177
204
store .close
178
205
179
206
180
- @click .group (help = 'Configure credentials using in request "Authorization:" headers.' )
207
+ @click .group (help = 'Configure request credentials. Request credentials are associated with a given domain, and used in request "Authorization:" headers.' )
181
208
def credentials ():
182
209
pass
183
210
@@ -309,13 +336,13 @@ def bookmarks_show():
309
336
310
337
click .echo (click .style ('Bookmarks' , bold = True ))
311
338
for key , value in sorted (bookmarks .items ()):
312
- click .echo (fmt .format (name = key , title = value ['title' ] or 'Document' , url = value ['url' ]))
339
+ click .echo (fmt .format (name = key , title = value ['title' ] or 'Document' , url = json . dumps ( value ['url' ]) ))
313
340
314
341
315
342
@click .command (help = "Add the current document to the bookmarks, with the given NAME." )
316
343
@click .argument ('name' , nargs = 1 )
317
344
def bookmarks_add (name ):
318
- doc = read_from_store ()
345
+ doc = get_document ()
319
346
if doc is None :
320
347
click .echo ('No current document.' )
321
348
return
@@ -349,14 +376,80 @@ def bookmarks_get(name):
349
376
return
350
377
351
378
session = get_session ()
379
+ history = get_history ()
352
380
doc = session .get (bookmark ['url' ])
353
- click .echo (dump_to_console (doc ))
354
- write_to_store (doc )
381
+ history = history .add (doc )
382
+ click .echo (display (doc ))
383
+ set_document (doc )
384
+ set_history (history )
385
+
386
+
387
+ # History
388
+
389
+ def get_history ():
390
+ if not os .path .isfile (history_path ):
391
+ return coreapi .History (max_items = 20 )
392
+ history_file = open (history_path , 'rb' )
393
+ bytestring = history_file .read ()
394
+ history_file .close ()
395
+ return coreapi .history .load_history (bytestring )
396
+
397
+
398
+ def set_history (history ):
399
+ bytestring = coreapi .history .dump_history (history )
400
+ history_file = open (history_path , 'wb' )
401
+ history_file .write (bytestring )
402
+ history_file .close ()
403
+
404
+
405
+ @click .group (help = "Navigate the browser history." )
406
+ def history ():
407
+ pass
408
+
409
+
410
+ @click .command (help = "List the browser history." )
411
+ def history_show ():
412
+ history = get_history ()
413
+
414
+ click .echo (click .style ('History' , bold = True ))
415
+ for is_active , doc in history .get_items ():
416
+ prefix = '[*] ' if is_active else '[ ] '
417
+ document = 'blank' if (doc is None ) else '<%s %s>' % (doc .title , json .dumps (doc .url ))
418
+ click .echo (prefix + document )
419
+
420
+
421
+ @click .command (help = "Navigate back through the browser history." )
422
+ def history_back ():
423
+ session = get_session ()
424
+ history = get_history ()
425
+ if history .is_at_oldest :
426
+ click .echo ("Currently at oldest point in history. Cannot navigate back." )
427
+ return
428
+ doc , history = history .back ()
429
+ doc = session .reload (doc )
430
+ click .echo (display (doc ))
431
+ set_history (history )
432
+ set_document (doc )
433
+
434
+
435
+ @click .command (help = "Navigate forward through the browser history." )
436
+ def history_forward ():
437
+ session = get_session ()
438
+ history = get_history ()
439
+ if history .is_at_most_recent :
440
+ click .echo ("Currently at most recent point in history. Cannot navigate forward." )
441
+ return
442
+ doc , history = history .forward ()
443
+ doc = session .reload (doc )
444
+ click .echo (display (doc ))
445
+ set_history (history )
446
+ set_document (doc )
355
447
356
448
357
449
client .add_command (get )
358
450
client .add_command (show )
359
451
client .add_command (action )
452
+ client .add_command (reload_document , name = 'reload' )
360
453
client .add_command (clear )
361
454
362
455
client .add_command (credentials )
@@ -375,6 +468,11 @@ def bookmarks_get(name):
375
468
bookmarks .add_command (bookmarks_remove , name = 'remove' )
376
469
bookmarks .add_command (bookmarks_show , name = 'show' )
377
470
471
+ client .add_command (history )
472
+ history .add_command (history_back , name = 'back' )
473
+ history .add_command (history_forward , name = 'forward' )
474
+ history .add_command (history_show , name = 'show' )
475
+
378
476
379
477
if __name__ == '__main__' :
380
478
client ()
0 commit comments