3737if server [- 1 ] != '/' : server += "/"
3838if not server .endswith ("/v1/" ): server += "/v1/"
3939
40- def get_keys ():
41- content = open (args .tex ).read ()
40+ def get_keys (filename , import_base = None ):
41+ content = open (filename ).read ()
42+
43+ # extract cites
4244 keys = set ()
4345 cites = re .findall ("\\ \\ citeA?\\ {([^\\ }]+)\\ }" , content )
4446 for key in cites :
4547 keys |= set (key .split ("," ))
4648
49+ # find inputs and recursively parse them
50+ inputs = re .findall ("\\ \\ input\\ {([^\\ }]+)\\ }" , content )
51+ for f in inputs :
52+ if import_base is not None :
53+ f = os .path .join (import_base , f )
54+ keys |= set (get_keys (f ))
55+
56+ # find subimports and recursively parse them
57+ subimports = re .findall ("\\ \\ subimport\*?\\ {(.*)\\ }\\ {(.*)\\ }" , content )
58+ for f in subimports :
59+ filepath = os .path .join (f [0 ], f [1 ])
60+ keys |= set (get_keys (filepath , import_base = f [0 ]))
61+
4762 keys = sorted (list ([k .strip () for k in keys ]))
4863 return keys
4964
@@ -71,8 +86,8 @@ def bib_has_changed(bib):
7186 pass
7287 save_bib_hash ()
7388 return (new_bib != old_bib )
74-
75-
89+
90+
7691def entry_by_key (key ):
7792 for entry in bib_database .entries :
7893 if entry ["ID" ] == key :
@@ -84,8 +99,8 @@ def entry_to_bibtex(entry):
8499 newdb = bibtexparser .bibdatabase .BibDatabase ()
85100 newdb .entries = [ entry ]
86101 return bibtexparser .dumps (newdb )
87-
88-
102+
103+
89104def inline_diff (a , b ):
90105 matcher = difflib .SequenceMatcher (None , a , b )
91106 def process_tag (tag , i1 , i2 , j1 , j2 ):
@@ -136,51 +151,51 @@ def update_local_bib(key, new_entry):
136151 if entry ["ID" ] == key :
137152 bib_database .entries [idx ] = new_entry
138153 break
139-
140-
154+
155+
141156def update_remote_bib (key , new_entry ):
142157 response = requests .put (server + "entry/%s" % key , json = {"entry" : new_entry , "token" : token })
143158 if "success" in response .json () and not response .json ()["success" ]:
144159 show_error (response .json ())
145160
146- def add_remote_bib (key , entry ):
161+ def add_remote_bib (key , entry ):
147162 response = requests .post (server + "entry/%s" % key , json = {"entry" : entry , "token" : token })
148163 if "success" in response .json () and not response .json ()["success" ]:
149- show_error (response .json ())
150-
164+ show_error (response .json ())
165+
151166def remove_remote_bib (key ):
152167 response = requests .delete (server + "entry/%s%s" % (key , "/%s" % token if token else "" ))
153168 if "success" in response .json () and not response .json ()["success" ]:
154169 show_error (response .json ())
155-
170+
156171
157172def remove_local_bib (key ):
158173 for (idx , entry ) in enumerate (bib_database .entries ):
159174 if entry ["ID" ] == key :
160175 del bib_database .entries [idx ]
161176 save_bib ()
162-
177+
163178
164179def save_bib_hash ():
165180 try :
166181 bib = open ("main.bib" ).read ()
167182 open ("main.bib.sha" , "w" ).write (hashlib .sha256 (bib .strip ().encode ("utf-8" )).hexdigest ())
168- except :
183+ except :
169184 pass
170185
171-
186+
172187def save_bib ():
173188 with open ('main.bib' , 'w' ) as bibtex_file :
174189 bibtexparser .dump (bib_database , bibtex_file )
175190 save_bib_hash ()
176-
191+
177192
178193def show_error (obj ):
179194 if "reason" in obj :
180195 if obj ["reason" ] == "access_denied" :
181196 print ("[!] Access denied! Your token is not valid for this operation. Verify whether the file '%s' contains a valid token." % args .token_file )
182-
183-
197+
198+
184199action = args .action
185200
186201parser = BibTexParser (common_strings = True )
@@ -208,29 +223,29 @@ def show_error(obj):
208223 sc .write (script .text )
209224 print ("Restarting..." )
210225 os .execl (sys .executable , * ([sys .executable ]+ sys .argv ))
211-
226+
212227
213228if action == "search" :
214229 if len (args .query ) < 3 :
215230 print ("Usage: %s search --query <query>" % sys .argv [0 ])
216231 sys .exit (1 )
217232 response = requests .get (server + "search/" + args .query + ("/%s" % token if token else "" ))
218233 print (response .text )
219-
234+
220235elif action == "sync" :
221236 response = requests .get (server + "sync" )
222237 print (response .text )
223238
224239elif action == "get" :
225- keys = get_keys ()
240+ keys = get_keys (args . tex )
226241 fetch = keys_have_changed (keys )
227242 try :
228243 current_bib = open ("main.bib" ).read ()
229244 update = bib_has_changed (current_bib )
230245 except :
231246 update = False
232247 fetch = True
233-
248+
234249 if update :
235250 fetch = True
236251 if not limit_traffic :
@@ -255,7 +270,7 @@ def show_error(obj):
255270 print (remote )
256271 print ("- Diff - " )
257272 print (inline_diff (remote , local ))
258-
273+
259274 if dup [1 ] != dup [2 ]["ID" ]:
260275 # different key, similar entry
261276 action = resolve_duplicate ()
@@ -283,7 +298,7 @@ def show_error(obj):
283298 update_remote_bib (dup [2 ]["ID" ], entry_by_key (dup [1 ]))
284299 else :
285300 show_error (result )
286-
301+
287302 if fetch :
288303 response = requests .post (server + "get_json" , json = {"entries" : keys , "token" : token })
289304 bib = response .json ()
@@ -295,7 +310,7 @@ def show_error(obj):
295310 if entry and "ID" in entry and not entry_by_key (entry ["ID" ]):
296311 bib_database .entries .append (entry )
297312 save_bib ()
298-
313+
299314 # suggest keys for unresolved keys
300315 for key in keys :
301316 if not entry_by_key (key ):
0 commit comments