@@ -40,6 +40,7 @@ def __init__(self):
4040 self .windows_path = repr ("c:\\ Users\\ {}\\ My Documents" .format (os .getenv ('USERNAME' )))
4141 self .unix_path = "." # Add mac support here
4242 self .file_name = 'dynamic_playbook.json'
43+ self .log = open ('logplaybook.txt' , 'w' )
4344
4445 @property
4546 def playbook_path (self ):
@@ -48,56 +49,101 @@ def playbook_path(self):
4849 elif (sys .platform == 'win32' ):
4950 return os .path .join (self .windows_path , self .file_name )
5051
52+ @property
53+ def playbook_template (self ):
54+ # Basic template and fields of playbook
55+ return {"time_of_update" : time .time (),"items_stackoverflow" :[]}
56+
5157 @property
5258 def playbook_content (self ):
59+ # Reads playbook data from local storage and returns it
5360 try :
5461 with open (self .playbook_path , 'r' ) as playbook :
5562 return json .load (playbook )
5663 except FileNotFoundError :
5764 os .makedirs (os .path .dirname (self .playbook_path ), exist_ok = True )
5865 with open (self .playbook_path , 'w' ) as playbook :
59- playbook . write ( '[]' )
66+ json . dump ( self . playbook_template , playbook , ensure_ascii = False )
6067 return self .playbook_content
6168
6269 @playbook_content .setter
6370 def playbook_content (self , value ):
6471 """
6572 Saves playbook in the following format
66- [
67- {
68- time: unix timestamp
69- question_id: 123456,
70- question_title: 'question_title',
71- question_link: 'link',
72- answer_body: 'body of the answer'
73- },
74- ...
75- ]
73+ {
74+ time_of_update: unix,
75+ items_stackoverflow:
76+ [
77+ {
78+ time: unix timestamp
79+ question_id: 123456,
80+ question_title: 'question_title',
81+ question_link: 'link',
82+ answer_body: 'body of the answer'
83+ },
84+ ...
85+ ]
86+ }
7687 """
77- if type (value ) == list :
88+ if type (value ) == dict :
7889 with open (self .playbook_path , 'w' ) as playbook :
7990 json .dump (value , playbook , ensure_ascii = False )
8091 pass
8192 else :
82- raise ValueError ("value should be of type list" )
83-
93+ raise ValueError ("value should be of type dict" )
94+
95+ def is_question_in_playbook (self , question_id ):
96+ content = self .playbook_content
97+ for entry in content ['items_stackoverflow' ]:
98+ if int (entry ['question_id' ]) == int (question_id ):
99+ return True
100+ return False
101+
84102 def add_to_playbook (self , stackoverflow_object , question_id ):
85103 """
86104 Receives a QuestionsPanelStackoverflow object and
87105 saves data of a particular question into playbook
88106 """
107+ if self .is_question_in_playbook (question_id ):
108+ SearchError ("Question is already in the playbook" , "No need to add" )
109+ sys .exit ()
89110 for question in stackoverflow_object .questions_data :
90111 if (int (question [1 ])== int (question_id )):
91112 content = self .playbook_content
92- content .append ({
93- 'time_of_creation' : time .time (),
113+ now = time .time ()
114+ content ['time_of_update' ] = now
115+ content ['items_stackoverflow' ].append ({
116+ 'time_of_creation' : now ,
94117 'question_id' : int (question_id ),
95118 'question_title' : question [0 ],
96119 'question_link' : question [2 ],
97120 'answer_body' : stackoverflow_object .answer_data [int (question_id )]
98121 })
99122 self .playbook_content = content
100123
124+ def delete_from_playbook (self , stackoverflow_object , question_id ):
125+ content = self .playbook_content
126+ self .log .write (str (len (content ["items_stackoverflow" ])))
127+ for i in range (len (content ["items_stackoverflow" ])):
128+ if content ["items_stackoverflow" ][i ]["question_id" ] == question_id :
129+ del content ["items_stackoverflow" ][i ]
130+ break
131+ self .playbook_content = content
132+ os .system ('cls' if os .name == 'nt' else 'clear' )
133+ self = Playbook ()
134+ self .display_panel ()
135+
136+ def display_panel (self ):
137+ playbook_data = self .playbook_content
138+ if (len (playbook_data ['items_stackoverflow' ]) == 0 ):
139+ SearchError ("You have no entries in the playbook" , "Browse and save entries in playbook with 'p' key" )
140+ sys .exit ()
141+ question_panel = QuestionsPanelStackoverflow ()
142+ for item in playbook_data ['items_stackoverflow' ]:
143+ question_panel .questions_data .append ( [item ['question_title' ], item ['question_id' ], item ['question_link' ]] )
144+ question_panel .answer_data [item ['question_id' ]] = item ['answer_body' ]
145+ question_panel .display_panel (playbook = True )
146+
101147class QuestionsPanelStackoverflow ():
102148 def __init__ (self ):
103149 self .questions_data = [] # list( list( question_title, question_id, question_link )... )
@@ -151,7 +197,7 @@ def populate_answer_data(self, questions_list):
151197 self .populate_answer_data (failed_ques_id )
152198
153199 def return_formatted_ans (self , ques_id ):
154- # This function uses pygments lexers ad formatters to format the content in the preview screen
200+ # This function uses uses Rich Markdown to format answers body.
155201 body_markdown = self .answer_data [int (ques_id )]
156202 body_markdown = str (body_markdown )
157203 xml_markup_replacement = [("&" , "&" ), ("<" , "<" ), (">" , ">" ), (""" , "\" " ), ("'" , "\' " ), ("'" , "\' " )]
@@ -168,31 +214,37 @@ def return_formatted_ans(self, ques_id):
168214 highlighted = highlighted .replace (convert_from , convert_to )
169215 return highlighted
170216
171- def navigate_questions_panel (self ):
217+ def navigate_questions_panel (self , playbook = False ):
172218 # Code for navigating through the question panel
173- console .rule ('[bold blue] Relevant Questions' , style = "bold red" )
174- console .print ("[yellow] Use arrow keys to navigate. 'q' or 'Esc' to quit. 'Enter' to open in a browser" )
219+ (message , instructions , keys ) = ('Playbook Questions' , ". Press 'd' to delete from playbook" , ('enter' , 'd' )) if (playbook ) else ('Relevant Questions' , ". Press 'p' to save in playbook" , ('p' , 'enter' ))
220+ console .rule ('[bold blue] {}' .format (message ), style = "bold red" )
221+ console .print ("[yellow] Use arrow keys to navigate. 'q' or 'Esc' to quit. 'Enter' to open in a browser" + instructions )
175222 console .print ()
176223 options = ["|" .join (map (str , question )) for question in self .questions_data ]
177- question_menu = TerminalMenu (options , preview_command = self .return_formatted_ans , preview_size = 0.75 , accept_keys = ( 'p' , 'enter' ) )
224+ question_menu = TerminalMenu (options , preview_command = self .return_formatted_ans , preview_size = 0.75 , accept_keys = keys )
178225 quitting = False
179226 while not (quitting ):
180227 options_index = question_menu .show ()
181228 try :
182229 question_link = self .questions_data [options_index ][2 ]
183230 except Exception :
184- return
231+ if (playbook ):
232+ sys .exit ()
233+ else :
234+ return
185235 else :
186236 if (question_menu .chosen_accept_key == 'enter' ):
187237 webbrowser .open (question_link )
188238 elif (question_menu .chosen_accept_key == 'p' ):
189239 self .playbook .add_to_playbook (self , self .questions_data [options_index ][1 ])
190- pass
240+ elif (question_menu .chosen_accept_key == 'd' and playbook ):
241+ self .playbook .delete_from_playbook (self , self .questions_data [options_index ][1 ])
191242
192- def display_panel (self , questions_list ):
193- self .populate_question_data (questions_list )
194- self .populate_answer_data (questions_list )
195- self .navigate_questions_panel ()
243+ def display_panel (self , questions_list = [], playbook = False ):
244+ if len (questions_list ) != 0 :
245+ self .populate_question_data (questions_list )
246+ self .populate_answer_data (questions_list )
247+ self .navigate_questions_panel (playbook = playbook )
196248
197249class Utility ():
198250 def __init__ (self ):
@@ -262,6 +314,10 @@ def get_ans(self, questions_list):
262314 stackoverflow_panel .display_panel (questions_list )
263315 # Support for reddit searching can also be implemented from here
264316
317+ def display_playbook (self ):
318+ playbook = Playbook ()
319+ playbook .display_panel ()
320+
265321 # Get an access token and extract to a JSON file "access_token.json"
266322 @classmethod
267323 def setCustomKey (self ):
0 commit comments