private IEnumerable <Bibitem> GetBibitemsInOrderOfAppearance(BibtexDatabase bibtexDatabase) { // Build up unique collection of bibitems. var citationKeys = new HashSet <string>(); foreach (var auxEntry in _auxEntries.Where(x => x.Type == AuxEntryType.Citation)) { if (!citationKeys.Contains(auxEntry.Key)) { citationKeys.Add(auxEntry.Key); if (bibtexDatabase.Entries.TryGetFirst(bibtexEntry => bibtexEntry.CitationKey == auxEntry.Key, out var bibtexEntry)) { var style = BibliographyStyle.EntryStyles.FirstOrDefault(s => s.Type == bibtexEntry.EntryType) ?? EntryStyle.Default; yield return(new Bibitem(citationKeys.Count, auxEntry, bibtexEntry, style)); } else { var warning = $"No bibliography entry matching citation key: '{auxEntry.Key}' found."; _logger.LogWarning(warning); yield return(new Bibitem(citationKeys.Count, auxEntry.Key, auxEntry.Label, warning)); } } } }
private void importBibTexFromClipBoardToolStripMenuItem_Click(object sender, EventArgs e) { if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text)) { BibtexParser parser = new BibtexParser(new StringReader(Clipboard.GetDataObject().GetData(DataFormats.Text).ToString())); var result = parser.Parse(); db = result.Database; foreach (var entry in db.getEntries()) { AddBibTeXEntry(entry); } } }
/// <inheritdoc /> public BibtexDatabase ParseStream(string databaseName, Stream stream) { var database = new BibtexDatabase(databaseName); int failedTags = 0; using var sr = new StreamReader(stream); while (sr.Peek() >= 0) { try { var entryType = GetEntryType(sr); if (entryType.HasValue) { switch (entryType) { case EntryType.Comment: database.Comments.Add(GetComment(sr)); break; case EntryType.Preamble: database.Preambles.Add(GetPreamble(sr)); break; case EntryType.String: database.Strings.Add(GetStringEntry(sr)); break; default: database.Entries.Add(GetEntryContent(entryType.Value, sr)); break; } } } catch (Exception ex) { _logger.LogWarning(ex, $"An error occurred parsing the Bibtex stream at entry: {database.AllEntriesCount + ++failedTags} - this tag will be skipped."); } } return(database); }
/** * Will parse the BibTex-Data found when reading from reader. * * The reader will be consumed. * * Multiple calls to parse() return the same results * * @return ParserResult * @throws IOException */ public ParserResult Parse() { // If we already parsed this, just return it. if (_pr != null) return _pr; _db = new BibtexDatabase(); // Bibtex related contents. _meta = new Dictionary<string, string>(); // Metadata in comments for Bibkeeper. entryTypes = new Dictionary<string, BibtexEntryType>(); // To store custem entry types parsed. _pr = new ParserResult(_db, _meta, entryTypes); // First see if we can find the version number of the JabRef version that // wrote the file: string versionNum = ReadJabRefVersionNumber(); if (versionNum != null) { _pr.JabrefVersion = versionNum; SetMajorMinorVersions(); } else { // No version number found. However, we have only } SkipWhitespace(); try { while (!_eof) { bool found = ConsumeUncritically('@'); if (!found) break; SkipWhitespace(); string entryType = ParseTextToken(); BibtexEntryType tp = BibtexEntryType.getType(entryType); bool isEntry = (tp != null); // Util.pr(tp.getName()); if (!isEntry) { // The entry type name was not recognized. This can mean // that it is a string, preamble, or comment. If so, // parse and set accordingly. If not, assume it is an entry // with an unknown type. if (entryType.ToLower().Equals("preamble")) { _db.setPreamble(ParsePreamble()); } else if (entryType.ToLower().Equals("string")) { BibtexString bs = ParseString(); try { _db.addString(bs); } catch (KeyCollisionException) { _pr.AddWarning(Globals.lang("Duplicate string name") + ": " + bs.getName()); // ex.printStackTrace(); } } else if (entryType.ToLower().Equals("comment")) { StringBuilder commentBuf = ParseBracketedTextExactly(); /** * * Metadata are used to store Bibkeeper-specific * information in .bib files. * * Metadata are stored in bibtex files in the format * * @comment{jabref-meta: type:data0;data1;data2;...} * * Each comment that starts with the META_FLAG is stored * in the meta Dictionary, with type as key. Unluckily, the * old META_FLAG bibkeeper-meta: was used in JabRef 1.0 * and 1.1, so we need to support it as well. At least * for a while. We'll always save with the new one. */ // TODO: unicode escape sequences string comment = commentBuf.ToString().Replace("[\\x0d\\x0a]", ""); if (comment.Substring(0, Math.Min(comment.Length, Globals.META_FLAG.Length)).Equals( Globals.META_FLAG) || comment.Substring(0, Math.Min(comment.Length, Globals.META_FLAG_OLD.Length)) .Equals(Globals.META_FLAG_OLD)) { string rest; if (comment.Substring(0, Globals.META_FLAG.Length).Equals( Globals.META_FLAG)) rest = comment.Substring(Globals.META_FLAG.Length); else rest = comment.Substring(Globals.META_FLAG_OLD.Length); int pos = rest.IndexOf(':'); if (pos > 0) _meta.Add(rest.Substring(0, pos), rest.Substring(pos + 1)); // We remove all line breaks in the metadata - these // will have been inserted // to prevent too long lines when the file was // saved, and are not part of the data. } /** * A custom entry type can also be stored in a * * @comment: */ if (comment.Substring(0, Math.Min(comment.Length, Globals.ENTRYTYPE_FLAG.Length)).Equals( Globals.ENTRYTYPE_FLAG)) { CustomEntryType typ = CustomEntryType.parseEntryType(comment); entryTypes.Add(typ.getName().ToLower(), typ); } } else { // The entry type was not recognized. This may mean that // it is a custom entry type whose definition will // appear // at the bottom of the file. So we use an // UnknownEntryType // to remember the type name by. tp = new UnknownEntryType(entryType.ToLower()); // System.out.println("unknown type: "+entryType); isEntry = true; } } if (isEntry) // True if not comment, preamble or string. { /** * Morten Alver 13 Aug 2006: Trying to make the parser more * robust. If an exception is thrown when parsing an entry, * drop the entry and try to resume parsing. Add a warning * for the user. * * An alternative solution is to try rescuing the entry for * which parsing failed, by returning the entry with the * exception and adding it before parsing is continued. */ try { BibtexEntry be = ParseEntry(tp); bool duplicateKey = _db.insertEntry(be); if (duplicateKey) // JZTODO lyrics _pr.AddDuplicateKey(be.getCiteKey()); /*_pr.AddWarning(Globals.lang("duplicate BibTeX key") + ": " + be.getCiteKey() + " (" + Globals.lang("grouping may not work for this entry") + ")"); */ else if (be.getCiteKey() == null || be.getCiteKey().Equals("")) { _pr.AddWarning(Globals.lang("empty BibTeX key") + ": " + be.getAuthorTitleYear(40) + " (" + Globals.lang("grouping may not work for this entry") + ")"); } } catch (IOException ex) { _pr.AddWarning(Globals.lang("Error occured when parsing entry") + ": '" + ex.Message + "'. " + Globals.lang("Skipped entry.")); } } SkipWhitespace(); } // Before returning the database, update entries with unknown type // based on parsed type definitions, if possible. CheckEntryTypes(_pr); return _pr; } catch (KeyCollisionException kce) { // kce.printStackTrace(); throw new IOException("Duplicate ID in bibtex file: " + kce.ToString()); } }
public ParserResult(BibtexDatabase database, Dictionary<string, string> metaData, Dictionary<string, BibtexEntryType> entryTypes) { Database = database; MetaData = metaData; EntryTypes = entryTypes; }
private List <(AuxEntry AuxEntry, BibtexEntry BibtexEntry, EntryStyle EntryStyle)> GetMatchedEntries(BibtexDatabase bibtexDatabase) { // Build up unique collection of bibtex entries. var matchedEntries = new List <(AuxEntry AuxEntry, BibtexEntry BibtexEntry, EntryStyle EntryStyle)>(); var citationKeys = new HashSet <string>(); foreach (var auxEntry in _auxEntries.Where(x => x.Type == AuxEntryType.Citation)) { if (!citationKeys.Contains(auxEntry.Key)) { citationKeys.Add(auxEntry.Key); var bibtexEntry = bibtexDatabase.Entries.FirstOrDefault(bibtexEntry => bibtexEntry.CitationKey == auxEntry.Key); var entryStyle = bibtexEntry != null ? (BibliographyStyle.EntryStyles.FirstOrDefault(s => s.Type == bibtexEntry.EntryType) ?? EntryStyle.Default) : null; matchedEntries.Add((auxEntry, bibtexEntry, entryStyle)); } } return(matchedEntries); }
private List <Bibitem> GetBibitemsOrderedByTitle(BibtexDatabase bibtexDatabase) => GetOrderedItems(GetMatchedEntries(bibtexDatabase), x => x.BibtexEntry?.Title).ToList();
private List <Bibitem> GetBibitemsOrderedByFirstAuthorLastName(BibtexDatabase bibtexDatabase) => GetOrderedItems(GetMatchedEntries(bibtexDatabase), x => BibtexAuthor.GetFirstAuthorLastName(x.BibtexEntry?.Author) ?? x.BibtexEntry?.Title).ToList();