@@ -341,31 +341,51 @@ def resort_ctags(tag_file):
341
341
If not exists, create an empty array and store in the
342
342
dictionary with the file name as key
343
343
Save the line to this list
344
- Create a new ``[ tagfile]_sorted_by_file `` file
344
+ Create a new ``tagfile`` file
345
345
For each key in the sorted dictionary
346
346
For each line in the list indicated by the key
347
347
Split the line on tab character
348
- Remove the prepending ``.\ `` from the ``file_name`` part of
348
+ Remove the prepending ``.`` from the ``file_name`` part of
349
349
the tag
350
350
Join the line again and write the ``sorted_by_file`` file
351
351
352
352
:param tag_file: The location of the tagfile to be sorted
353
353
354
354
:returns: None
355
355
"""
356
- keys = {}
356
+ meta = []
357
+ symbols = []
358
+ tmp_file = tag_file + '.tmp'
357
359
358
360
with codecs .open (tag_file , encoding = 'utf-8' , errors = 'replace' ) as file_ :
359
361
for line in file_ :
360
- keys .setdefault (line .split ('\t ' )[FILENAME ], []).append (line )
362
+ if line .startswith ('!_TAG' ):
363
+ meta .append (line )
364
+ continue
365
+
366
+ # read all valid symbol tags, which contain at least
367
+ # symbol name and containing file and build a list of tuples
368
+ split = line .split ('\t ' )
369
+ if len (split ) > FILENAME :
370
+ symbols .append ((split [FILENAME ], split ))
371
+
372
+ # sort inplace to save some RAM with large .tags files
373
+ meta .sort ()
374
+ symbols .sort ()
361
375
362
- with codecs .open (tag_file + '_sorted_by_file' , 'w' , encoding = 'utf-8' ,
376
+ with codecs .open (tmp_file , 'w' , encoding = 'utf-8' ,
363
377
errors = 'replace' ) as file_ :
364
- for k in sorted (keys ):
365
- for line in keys [k ]:
366
- split = line .split ('\t ' )
367
- split [FILENAME ] = split [FILENAME ].lstrip ('.\\ ' )
368
- file_ .write ('\t ' .join (split ))
378
+
379
+ # write sourted metadata
380
+ file_ .writelines (meta )
381
+
382
+ # followed by sorted list of symbols
383
+ for _ , split in symbols :
384
+ split [FILENAME ] = split [FILENAME ].lstrip ('.\\ ' )
385
+ file_ .write ('\t ' .join (split ))
386
+
387
+ os .remove (tag_file )
388
+ os .rename (tmp_file , tag_file )
369
389
370
390
#
371
391
# Models
@@ -393,16 +413,26 @@ def __init__(self, line, column=0):
393
413
self .column = column
394
414
395
415
def __lt__ (self , other ):
396
- return self .line .split ('\t ' )[self .column ] < other
416
+ try :
417
+ return self .key < other
418
+ except IndexError :
419
+ return False
397
420
398
421
def __gt__ (self , other ):
399
- return self .line .split ('\t ' )[self .column ] > other
422
+ try :
423
+ return self .key > other
424
+ except IndexError :
425
+ return False
400
426
401
427
def __getitem__ (self , index ):
402
- return self .line .split ('\t ' )[index ]
428
+ return self .line .split ('\t ' , self . column + 1 )[index ]
403
429
404
430
def __len__ (self ):
405
- return len (self .line .split ('\t ' ))
431
+ return self .line .count ('\t ' ) + 1
432
+
433
+ @property
434
+ def key (self ):
435
+ return self [self .column ]
406
436
407
437
class TagFile (object ):
408
438
"""
@@ -443,6 +473,8 @@ def __getitem__(self, index):
443
473
result = self .mapped .readline () # get a complete line
444
474
445
475
result = result .strip ()
476
+ if not result :
477
+ raise IndexError ("Invalid tag at index %d." % index )
446
478
447
479
return Tag (result , self .column )
448
480
@@ -476,7 +508,7 @@ def open(self):
476
508
"""
477
509
Open file.
478
510
"""
479
- self .file_o = codecs .open (self .path , 'r+b' , encoding = 'ascii ' )
511
+ self .file_o = codecs .open (self .path , 'r+b' , encoding = 'utf-8 ' )
480
512
self .mapped = mmap .mmap (self .file_o .fileno (), 0 ,
481
513
access = mmap .ACCESS_READ )
482
514
@@ -500,20 +532,21 @@ def search(self, exact_match=True, *tags):
500
532
if not tags :
501
533
while self .mapped .tell () < self .mapped .size ():
502
534
result = Tag (self .mapped .readline ().strip (), self .column )
503
- yield (result )
535
+ if result .line :
536
+ yield result
504
537
return
505
538
506
539
for key in tags :
507
540
left_index = bisect .bisect_left (self , key )
508
541
if exact_match :
509
542
result = self [left_index ]
510
543
while result .line and result [result .column ] == key :
511
- yield ( result )
544
+ yield result
512
545
result = Tag (self .mapped .readline ().strip (), self .column )
513
546
else :
514
547
result = self [left_index ]
515
548
while result .line and result [result .column ].startswith (key ):
516
- yield ( result )
549
+ yield result
517
550
result = Tag (self .mapped .readline ().strip (), self .column )
518
551
519
552
def search_by_suffix (self , suffix ):
@@ -529,10 +562,9 @@ def search_by_suffix(self, suffix):
529
562
:returns: matching tags
530
563
"""
531
564
for line in self .file_o :
532
- if line .split ('\t ' )[self .column ].endswith (suffix ):
533
- yield Tag (line )
534
- else :
535
- continue
565
+ tag = Tag (line , self .column )
566
+ if tag .key .endswith (suffix ):
567
+ yield tag
536
568
537
569
def tag_class (self ):
538
570
"""
0 commit comments