Revision: 28467
http://sourceforge.net/p/bibdesk/svn/28467
Author: hofman
Date: 2023-11-28 17:11:45 +0000 (Tue, 28 Nov 2023)
Log Message:
-----------
Add completions for auto-complete when adding items to a document. Also remove
field values for completion when they are changed or itemas are removed, so
erroneous strings are not kept as completion. Use counted sets to hold the
completion strings, so strings remain when overwritten while another item has
the value.
Modified Paths:
--------------
trunk/bibdesk/BDSKBibTeXParser.m
trunk/bibdesk/BDSKCompletionManager.h
trunk/bibdesk/BDSKCompletionManager.m
trunk/bibdesk/BibDocument.m
trunk/bibdesk/BibItem.m
Modified: trunk/bibdesk/BDSKBibTeXParser.m
===================================================================
--- trunk/bibdesk/BDSKBibTeXParser.m 2023-11-26 17:36:32 UTC (rev 28466)
+++ trunk/bibdesk/BDSKBibTeXParser.m 2023-11-28 17:11:45 UTC (rev 28467)
@@ -56,7 +56,6 @@
#import "BDSKGroupsArray.h"
#import "NSScanner_BDSKExtensions.h"
#import "NSError_BDSKExtensions.h"
-#import "BDSKCompletionManager.h"
#import "NSData_BDSKExtensions.h"
#import "CFString_BDSKExtensions.h"
#import "NSDictionary_BDSKExtensions.h"
@@ -596,7 +595,6 @@
[authors addObject:anAuthor];
[anAuthor release];
}
- [[BDSKCompletionManager sharedManager] addNamesForCompletion:authors];
CFRelease(names);
return authors;
}
@@ -1092,10 +1090,6 @@
}
if (fieldName && fieldValue) {
- // add the expanded values to the autocomplete dictionary; authors
are handled elsewhere
- if ([fieldName isPersonField] == NO)
- [[BDSKCompletionManager sharedManager] addString:fieldValue
forCompletionEntry:fieldName];
-
[dictionary setObject:fieldValue forKey:fieldName];
} else {
hadProblems = YES;
@@ -1134,8 +1128,6 @@
if ([crossref isCaseInsensitiveEqual:citeKey])
[dictionary setObject:[NSString stringWithFormat:@"(%@)",
crossref] forKey:BDSKCrossrefString];
- [[BDSKCompletionManager sharedManager] addString:citeKey
forCompletionEntry:BDSKCrossrefString];
-
BibItem *newBI = [[BibItem alloc] initWithType:entryType
citeKey:citeKey
pubFields:dictionary
Modified: trunk/bibdesk/BDSKCompletionManager.h
===================================================================
--- trunk/bibdesk/BDSKCompletionManager.h 2023-11-26 17:36:32 UTC (rev
28466)
+++ trunk/bibdesk/BDSKCompletionManager.h 2023-11-28 17:11:45 UTC (rev
28467)
@@ -46,8 +46,12 @@
+ (id)sharedManager;
+- (void)addString:(NSString *)string forCompletionEntry:(NSString *)entry;
+- (void)removeString:(NSString *)string forCompletionEntry:(NSString *)entry;
- (void)addNamesForCompletion:(NSArray *)authors;
-- (void)addString:(NSString *)string forCompletionEntry:(NSString *)entry;
+- (void)removeNamesForCompletion:(NSArray *)authors;
+- (void)addCompletionsFromItems:(NSArray *)items;
+- (void)removeCompletionsFromItems:(NSArray *)items;
- (NSRange)entry:(NSString *)entry rangeForUserCompletion:(NSRange)charRange
ofString:(NSString *)fullString;
- (NSArray *)entry:(NSString *)entry completions:(NSArray *)words
forPartialWordRange:(NSRange)charRange ofString:(NSString *)fullString
indexOfSelectedItem:(NSInteger *)index;
Modified: trunk/bibdesk/BDSKCompletionManager.m
===================================================================
--- trunk/bibdesk/BDSKCompletionManager.m 2023-11-26 17:36:32 UTC (rev
28466)
+++ trunk/bibdesk/BDSKCompletionManager.m 2023-11-28 17:11:45 UTC (rev
28467)
@@ -39,10 +39,10 @@
#import "BDSKCompletionManager.h"
#import "BDSKStringConstants.h"
#import "BDSKTypeManager.h"
-#import "NSArray_BDSKExtensions.h"
-#import "CFString_BDSKExtensions.h"
#import "NSString_BDSKExtensions.h"
+#import "BDSKComplexString.h"
#import "BibAuthor.h"
+#import "BibItem.h"
@implementation BDSKCompletionManager
@@ -67,7 +67,7 @@
- (NSMutableSet *)setForCompletionEntry:(NSString *)entry {
NSMutableSet *set = [autoCompletionDict objectForKey:entry];
if (set == nil) {
- set = [[NSMutableSet alloc] initWithCapacity:500];
+ set = [[NSCountedSet alloc] init];
[autoCompletionDict setObject:set forKey:entry];
[set release];
}
@@ -74,33 +74,19 @@
return set;
}
-- (void)addNamesForCompletion:(NSArray *)authors {
- NSMutableSet *nameSet = [self setForCompletionEntry:BDSKAuthorString];
- for (BibAuthor *author in authors) {
- NSString *name = [author originalName];
- if ([name isComplex])
- name = [NSString stringWithString:name];
- [nameSet addObject:name];
- NSString *lastName = [[author lastName] stringByRemovingCurlyBraces];
- if (lastName && [[name stringByRemovingCurlyBraces]
hasCaseInsensitivePrefix:lastName] == NO)
- [lastNamesDict setObject:lastName forKey:name];
- }
-}
-
-- (void)addString:(NSString *)string forCompletionEntry:(NSString *)entry{
+- (void)addString:(NSString *)string forCompletionEntry:(NSString *)entry {
- if (BDIsEmptyString((CFStringRef)entry) || [entry isNumericField] ||
[entry isURLField] || [entry isPersonField] || [entry isCitationField] ||
[entry hasPrefix:@"Bdsk-"])
+ if ([NSString isEmptyString:entry] || [entry isNumericField] || [entry
isURLField] || [entry isPersonField] || [entry isNoteField] || [entry
isCitationField] || [entry hasPrefix:@"Bdsk-"])
return;
if ([entry isEqualToString:BDSKBooktitleString])
entry = BDSKTitleString;
- NSMutableSet *completionSet = [self setForCompletionEntry:entry];
+ NSMutableSet *completionSet = [self setForCompletionEntry:entry];
// more efficient for the splitting and checking functions
// also adding complex strings can lead to a crash after the containing
document closes
- if ([string isComplex])
- string = [NSString stringWithString:string];
+ string = [string expandedString];
if ([entry isSingleValuedField]) { // add the whole string
[completionSet addObject:[string
stringByCollapsingAndTrimmingCharactersInSet:[NSCharacterSet
whitespaceCharacterSet]]];
@@ -116,6 +102,100 @@
}
}
+- (void)removeString:(NSString *)string forCompletionEntry:(NSString *)entry {
+
+ if ([NSString isEmptyString:entry] || [entry isNumericField] || [entry
isURLField] || [entry isPersonField] || [entry isNoteField] || [entry
isCitationField] || [entry hasPrefix:@"Bdsk-"])
+ return;
+
+ if ([entry isEqualToString:BDSKBooktitleString])
+ entry = BDSKTitleString;
+
+ NSMutableSet *completionSet = [autoCompletionDict objectForKey:entry];
+
+ // more efficient for the splitting and checking functions
+ // also adding complex strings can lead to a crash after the containing
document closes
+ string = [string expandedString];
+
+ if ([entry isSingleValuedField]) { // remove the whole string
+ [completionSet removeObject:[string
stringByCollapsingAndTrimmingCharactersInSet:[NSCharacterSet
whitespaceCharacterSet]]];
+ } else {
+ NSCharacterSet *acSet = [[BDSKTypeManager sharedManager]
separatorCharacterSetForField:entry];
+ if ([string rangeOfCharacterFromSet:acSet].location != NSNotFound) {
+ for (NSString *s in [string
componentsSeparatedByCharactersInSet:acSet trimWhitespace:YES])
+ [completionSet removeObject:s];
+ } else if ([entry isEqualToString:BDSKKeywordsString]) {
+ // if it wasn't punctuated, try this; Elsevier uses "and" as a
separator, and it's annoying to have the whole string autocomplete on you
+ for (NSString *s in [[string componentsSeparatedByString:@" and "]
valueForKey:@"stringByCollapsingWhitespaceAndRemovingSurroundingWhitespace"])
+ [completionSet removeObject:s];
+ } else {
+ [completionSet removeObject:[string
stringByCollapsingAndTrimmingCharactersInSet:[NSCharacterSet
whitespaceCharacterSet]]];
+ }
+ }
+}
+
+- (void)addNamesForCompletion:(NSArray *)authors {
+ NSMutableSet *nameSet = [self setForCompletionEntry:BDSKAuthorString];
+ for (BibAuthor *author in authors) {
+ NSString *name = [author originalName];
+ if ([name isComplex])
+ name = [NSString stringWithString:name];
+ [nameSet addObject:name];
+ NSString *lastName = [[author lastName] stringByRemovingCurlyBraces];
+ if (lastName && [[name stringByRemovingCurlyBraces]
hasCaseInsensitivePrefix:lastName] == NO)
+ [lastNamesDict setObject:lastName forKey:name];
+ }
+}
+
+- (void)removeNamesForCompletion:(NSArray *)authors {
+ NSMutableSet *nameSet = [autoCompletionDict objectForKey:BDSKAuthorString];
+ for (BibAuthor *author in authors) {
+ NSString *name = [author originalName];
+ if ([name isComplex])
+ name = [NSString stringWithString:name];
+ [nameSet removeObject:name];
+ }
+}
+
+- (void)addCompletionsFromItems:(NSArray *)items {
+ NSMutableArray *authors = [[NSMutableArray alloc] init];
+ for (BibItem *item in items) {
+ [[item pubFields] enumerateKeysAndObjectsUsingBlock:^(NSString *entry,
NSString *string, BOOL *stop){
+ if ([NSString isEmptyString:string]) return;
+ if ([entry isPersonField])
+ [authors addObjectsFromArray:[item
peopleArrayForField:entry inherit:NO]];
+ else
+ [self addString:string forCompletionEntry:entry];
+ }];
+ if ([authors count]) {
+ [self addNamesForCompletion:authors];
+ [authors removeAllObjects];
+ }
+ if ([item hasEmptyOrDefaultCiteKey] == NO)
+ [self addString:[item citeKey]
forCompletionEntry:BDSKCrossrefString];
+ }
+ [authors release];
+}
+
+- (void)removeCompletionsFromItems:(NSArray *)items {
+ NSMutableArray *authors = [[NSMutableArray alloc] init];
+ for (BibItem *item in items) {
+ [[item pubFields] enumerateKeysAndObjectsUsingBlock:^(NSString *entry,
NSString *string, BOOL *stop){
+ if ([NSString isEmptyString:string]) return;
+ if ([entry isPersonField])
+ [authors addObjectsFromArray:[item peopleArrayForField:entry
inherit:NO]];
+ else
+ [self removeString:string forCompletionEntry:entry];
+ }];
+ if ([authors count]) {
+ [self removeNamesForCompletion:authors];
+ [authors removeAllObjects];
+ }
+ if ([item hasEmptyOrDefaultCiteKey] == NO)
+ [self removeString:[item citeKey]
forCompletionEntry:BDSKCrossrefString];
+ }
+ [authors release];
+}
+
- (NSRange)entry:(NSString *)entry rangeForUserCompletion:(NSRange)charRange
ofString:(NSString *)fullString {
NSCharacterSet *wsCharSet = [NSCharacterSet whitespaceCharacterSet];
NSCharacterSet *acSet = [[BDSKTypeManager sharedManager]
separatorCharacterSetForField:entry];
@@ -167,7 +247,7 @@
NSSet *strings = [autoCompletionDict objectForKey:entry];
NSString *string = nil;
- NSMutableArray *completions = [NSMutableArray arrayWithCapacity:[strings
count]];
+ NSMutableArray *completions = [NSMutableArray array];
BOOL isAuthor = [entry isEqualToString:BDSKAuthorString];
for (string in strings) {
Modified: trunk/bibdesk/BibDocument.m
===================================================================
--- trunk/bibdesk/BibDocument.m 2023-11-26 17:36:32 UTC (rev 28466)
+++ trunk/bibdesk/BibDocument.m 2023-11-28 17:11:45 UTC (rev 28467)
@@ -125,6 +125,7 @@
#import "BDSKSaveAccessoryViewController.h"
#import "NSObject_BDSKExtensions.h"
#import "NSLayoutConstraint_BDSKExtensions.h"
+#import "BDSKCompletionManager.h"
// these are the same as in Info.plist
NSString *BDSKBibTeXDocumentType = @"BibTeX Database";
@@ -760,6 +761,10 @@
[self endObserving];
+ // discard completions from temporary draft documents, but keep them from
saved ones
+ if ([self fileURL] == nil)
+ [[BDSKCompletionManager sharedManager]
removeCompletionsFromItems:publications];
+
// workaround for crash: to reproduce, create empty doc, hit cmd-n for new
editor window, then cmd-q to quit, choose "don't save"; this results in an
-undoManager message to the dealloced document
[publications setValue:nil forKey:@"owner"];
@@ -928,10 +933,14 @@
// This is not undoable!
- (void)setPublications:(NSArray *)newPubs{
+ [[BDSKCompletionManager sharedManager]
removeCompletionsFromItems:publications];
+
[publications setValue:nil forKey:@"owner"];
[publications setArray:newPubs];
[publications setValue:self forKey:@"owner"];
+ [[BDSKCompletionManager sharedManager]
addCompletionsFromItems:publications];
+
[notesSearchIndex resetWithPublications:newPubs];
[fileSearchController resetWithPublications:newPubs];
}
@@ -945,6 +954,8 @@
[pubs setValue:self forKey:@"owner"];
+ [[BDSKCompletionManager sharedManager] addCompletionsFromItems:pubs];
+
NSDictionary *notifInfo = @{BDSKDocumentPublicationsKey:pubs};
[[NSNotificationCenter defaultCenter]
postNotificationName:BDSKDocumentDidAddItemNotification
object:self
@@ -974,7 +985,9 @@
[publications removeObjectsAtIndexes:indexes];
- [pubs setValue:nil forKey:@"owner"];
+ [[BDSKCompletionManager sharedManager] removeCompletionsFromItems:pubs];
+
+ [pubs setValue:nil forKey:@"owner"];
NSFileManager *fm = [NSFileManager defaultManager];
for (BibItem *pub in pubs)
[fm removeSpotlightCacheFileForCiteKey:[pub citeKey]];
Modified: trunk/bibdesk/BibItem.m
===================================================================
--- trunk/bibdesk/BibItem.m 2023-11-26 17:36:32 UTC (rev 28466)
+++ trunk/bibdesk/BibItem.m 2023-11-28 17:11:45 UTC (rev 28467)
@@ -1183,12 +1183,18 @@
if(NO == [newFields isEqualToDictionary:oldFields]){
[[[self undoManager] prepareWithInvocationTarget:self]
setPubFields:oldFields];
+ if ([[self owner] isDocument])
+ [[BDSKCompletionManager sharedManager]
removeCompletionsFromItems:@[self]];
+
[pubFields release];
pubFields = [[NSMutableDictionary alloc] initWithDictionary:newFields];
[self updateMetadataForKey:BDSKAllFieldsString];
- NSDictionary *notifInfo = @{}; // cmh: maybe not the best info,
but handled correctly
+ if ([[self owner] isDocument])
+ [[BDSKCompletionManager sharedManager]
addCompletionsFromItems:@[self]];
+
+ NSDictionary *notifInfo = @{}; // cmh: maybe not the best info, but
handled correctly
[[NSNotificationCenter defaultCenter]
postNotificationName:BDSKBibItemChangedNotification
object:self
userInfo:notifInfo];
@@ -1214,15 +1220,27 @@
toValue:oldValue
withModDate:[self dateModified]];
}
-
+ if ([[self owner] isDocument] && oldValue) {
+ // remove possibly erroneous value for completion
+ if ([key isPersonField])
+ [[BDSKCompletionManager sharedManager]
removeNamesForCompletion:[self peopleArrayForField:key inherit:NO]];
+ else
+ [[BDSKCompletionManager sharedManager] removeString:oldValue
forCompletionEntry:key];
+ }
+
[pubFields setValue:value forKey:key];
- // to allow autocomplete:
- if (value)
- [[BDSKCompletionManager sharedManager] addString:value
forCompletionEntry:key];
[self setModifiedDate:date];
[self updateMetadataForKey:key];
-
+
if ([self owner]) {
+ if ([[self owner] isDocument] && value) {
+ // to allow autocomplete:
+ if ([key isPersonField])
+ [[BDSKCompletionManager sharedManager]
addNamesForCompletion:[self peopleArrayForField:key inherit:NO]];
+ else
+ [[BDSKCompletionManager sharedManager] addString:value
forCompletionEntry:key];
+ }
+
NSMutableDictionary *notifInfo = [NSMutableDictionary
dictionaryWithObjectsAndKeys:key, BDSKBibItemKeyKey, nil];
[notifInfo setValue:value forKey:BDSKBibItemNewValueKey];
[notifInfo setValue:oldValue forKey:BDSKBibItemOldValueKey];
@@ -4103,10 +4121,12 @@
// parser doesn't allow empty cite keys
BDSKPRECONDITION([NSString isEmptyString:newCiteKey] == NO);
if(newCiteKey != citeKey){
+ if ([[self owner] isDocument] && [self hasEmptyOrDefaultCiteKey] == NO)
+ [[BDSKCompletionManager sharedManager] removeString:citeKey
forCompletionEntry:BDSKCrossrefString];
[citeKey autorelease];
citeKey = [newCiteKey copy];
- if ([newCiteKey isEqualToString:defaultCiteKey] == NO && [newCiteKey
isEqualToString:placeholderCiteKey] == NO)
- [[BDSKCompletionManager sharedManager] addString:newCiteKey
forCompletionEntry:BDSKCrossrefString];
+ if ([[self owner] isDocument] && [self hasEmptyOrDefaultCiteKey] == NO)
+ [[BDSKCompletionManager sharedManager] addString:newCiteKey
forCompletionEntry:BDSKCrossrefString];
}
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit