summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py')
-rw-r--r--Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py587
1 files changed, 587 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py b/Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py
new file mode 100644
index 00000000000..f0be509ea7a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/biblatex-gb7714-2015/biblatex_check.py
@@ -0,0 +1,587 @@
+#!/usr/bin/env python
+
+"""
+BibLaTeX check on missing fields and consistent name conventions,
+especially developed for requirements in Computer Science.
+"""
+
+__author__ = "Pez Cuckow"
+__version__ = "0.1.4"
+__credits__ = ["Pez Cuckow", "BibTex Check 0.2.0 by Fabian Beck"]
+__license__ = "MIT"
+__email__ = "email<at>pezcuckow.com"
+
+####################################################################
+# Properties (please change according to your needs)
+####################################################################
+
+# links
+citeulikeUsername = "" # if no username is profided, no CiteULike links appear
+citeulikeHref = "http://www.citeulike.org/user/" + \
+ citeulikeUsername + "/article/"
+
+libraries = [("Scholar", "http://scholar.google.de/scholar?hl=en&q="),
+ ("Google", "https://www.google.com/search?q="),
+ ("DBLP", "http://dblp.org/search/index.php#query="),
+ ("IEEE", "http://ieeexplore.ieee.org/search/searchresult.jsp?queryText="),
+ ("ACM", "http://dl.acm.org/results.cfm?query="),
+ ]
+
+
+# fields that are required for a specific type of entry
+requiredFields = {"article": ["author", "title", "journaltitle/journal", "year/date"],
+ "book": ["author", "title", "year/date"],
+ "mvbook": "book",
+ "inbook": ["author", "title", "booktitle", "year/date"],
+ "bookinbook": "inbook",
+ "suppbook": "inbook",
+ "booklet": ["author/editor", "title", "year/date"],
+ "collection": ["editor", "title", "year/date"],
+ "mvcollection": "collection",
+ "incollection": ["author", "title", "booktitle", "year/date"],
+ "suppcollection": "incollection",
+ "manual": ["author/editor", "title", "year/date"],
+ "misc": ["author/editor", "title", "year/date"],
+ "online": ["author/editor", "title", "year/date", "url"],
+ "patent": ["author", "title", "number", "year/date"],
+ "periodical": ["editor", "title", "year/date"],
+ "suppperiodical": "article",
+ "proceedings": ["title", "year/date"],
+ "mvproceedings": "proceedings",
+ "inproceedings": ["author", "title", "booktitle", "year/date"],
+ "reference": "collection",
+ "mvreference": "collection",
+ "inreference": "incollection",
+ "report": ["author", "title", "type", "institution", "year/date"],
+ "thesis": ["author", "title", "type", "institution", "year/date"],
+ "unpublished": ["author", "title", "year/date"],
+
+ # semi aliases (differing fields)
+ "mastersthesis": ["author", "title", "institution", "year/date"],
+ "techreport": ["author", "title", "institution", "year/date"],
+
+ # other aliases
+ "conference": "inproceedings",
+ "electronic": "online",
+ "phdthesis": "mastersthesis",
+ "www": "online",
+ "school": "mastersthesis"
+ }
+
+####################################################################
+
+import string
+import re
+import sys
+from optparse import OptionParser
+
+# Parse options
+usage = sys.argv[
+ 0] + " [-b|--bib=<input.bib>] [-a|--aux=<input.aux>] [-o|--output=<output.html>] [-v|--view] [-h|--help]"
+
+parser = OptionParser(usage)
+
+parser.add_option("-b", "--bib", dest="bibFile",
+ help="Bib File", metavar="input.bib", default="input.bib")
+
+parser.add_option("-a", "--aux", dest="auxFile",
+ help="Aux File", metavar="input.aux", default="references.aux")
+
+parser.add_option("-o", "--output", dest="htmlOutput",
+ help="HTML Output File", metavar="output.html")
+
+parser.add_option("-v", "--view", dest="view", action="store_true",
+ help="Open in Browser")
+
+parser.add_option("-N", "--no-console", dest="no_console", action="store_true",
+ help="Do not print problems to console")
+
+(options, args) = parser.parse_args()
+
+# Backporting Python 3 open(encoding="utf-8") to Python 2
+# based on http://stackoverflow.com/questions/10971033/backporting-python-3-openencoding-utf-8-to-python-2
+
+if sys.version_info[0] > 2:
+ # py3k
+ pass
+else:
+ # py2
+ import codecs
+ import warnings
+ reload(sys)
+ sys.setdefaultencoding('utf8')
+ def open(file, mode='r', buffering=-1, encoding=None,
+ errors=None, newline=None, closefd=True, opener=None):
+ if newline is not None:
+ warnings.warn('newline is not supported in py2')
+ if not closefd:
+ warnings.warn('closefd is not supported in py2')
+ if opener is not None:
+ warnings.warn('opener is not supported in py2')
+ return codecs.open(filename=file, mode=mode, encoding=encoding,
+ errors=errors, buffering=buffering)
+
+### End Backport ###
+
+print("INFO: Reading references from '" + options.bibFile + "'")
+try:
+ fIn = open(options.bibFile, 'r', encoding="utf8")
+except IOError as e:
+ print("ERROR: Input bib file '" + options.bibFile +
+ "' doesn't exist or is not readable")
+ sys.exit(-1)
+
+if options.no_console:
+ print("INFO: Will surpress problems on console")
+
+if options.htmlOutput:
+ print("INFO: Will output HTML to '" + options.htmlOutput + "'"
+ + (" and auto open in the default web browser" if options.view else ""))
+
+# Filter by reference ID's that are used
+usedIds = set()
+if options.auxFile:
+ print("INFO: Filtering by references found in '" + options.auxFile + "'")
+ try:
+ fInAux = open(options.auxFile, 'r', encoding="utf8")
+ for line in fInAux:
+ if line.startswith("\\citation"):
+ ids = line.split("{")[1].rstrip("} \n").split(", ")
+ for id in ids:
+ if (id != ""):
+ usedIds.add(id)
+ fInAux.close()
+ except IOError as e:
+ print ("WARNING: Aux file '" + options.auxFile +
+ "' doesn't exist -> not restricting entries")
+
+# Go through and check all references
+completeEntry = ""
+currentId = ""
+ids = []
+currentType = ""
+currentArticleId = ""
+currentTitle = ""
+fields = []
+problems = []
+subproblems = []
+
+counterMissingFields = 0
+counterFlawedNames = 0
+counterWrongTypes = 0
+counterNonUniqueId = 0
+counterWrongFieldNames = 0
+
+removePunctuationMap = dict((ord(char), None) for char in string.punctuation)
+
+for line in fIn:
+ line = line.strip("\n")
+ if line.startswith("@"):
+ if currentId in usedIds or not usedIds:
+ for fieldName, requiredFieldsType in requiredFields.items():
+ if fieldName == currentType.lower():
+ # alises use a string to point at another set of fields
+ currentRequiredFields = requiredFieldsType
+ while isinstance(currentRequiredFields, str):
+ currentRequiredFields = requiredFields[currentRequiredFields] # resolve alias
+
+ for requiredFieldsString in currentRequiredFields:
+ # support for author/editor syntax
+ typeFields = requiredFieldsString.split('/')
+
+ # at least one the required fields is not found
+ if set(typeFields).isdisjoint(fields):
+ subproblems.append(
+ "missing field '" + requiredFieldsString + "'")
+ counterMissingFields += 1
+ else:
+ subproblems = []
+
+ if currentId in usedIds or (currentId and not usedIds):
+ cleanedTitle = currentTitle.translate(removePunctuationMap)
+ problem = "<div id='" + currentId + \
+ "' class='problem severe" + str(len(subproblems)) + "'>"
+ problem += "<h2>" + currentId + " (" + currentType + ")</h2> "
+ problem += "<div class='links'>"
+ if citeulikeUsername:
+ problem += "<a href='" + citeulikeHref + \
+ currentArticleId + "' target='_blank'>CiteULike</a> |"
+
+ list = []
+ for name, site in libraries:
+ list.append(
+ " <a href='" + site + cleanedTitle + "' target='_blank'>" + name + "</a>")
+ problem += " | ".join(list)
+
+ problem += "</div>"
+ problem += "<div class='reference'>" + currentTitle
+ problem += "</div>"
+ problem += "<ul>"
+ for subproblem in subproblems:
+ problem += "<li>" + subproblem + "</li>"
+ if not options.no_console:
+ print("PROBLEM: " + currentId + " - " + subproblem)
+ problem += "</ul>"
+ problem += "<form class='problem_control'><label>checked</label><input type='checkbox' class='checked'/></form>"
+ problem += "<div class='bibtex_toggle'>Current BibLaTex Entry</div>"
+ problem += "<div class='bibtex'>" + completeEntry + "</div>"
+ problem += "</div>"
+ problems.append(problem)
+ fields = []
+ subproblems = []
+ currentId = line.split("{")[1].rstrip(",\n")
+ if currentId in ids:
+ subproblems.append("non-unique id: '" + currentId + "'")
+ counterNonUniqueId += 1
+ else:
+ ids.append(currentId)
+ currentType = line.split("{")[0].strip("@ ")
+ completeEntry = line + "<br />"
+ else:
+ if line != "":
+ completeEntry += line + "<br />"
+ if currentId in usedIds or not usedIds:
+ if "=" in line:
+ # biblatex is not case sensitive
+ field = line.split("=")[0].strip().lower()
+ fields.append(field)
+ value = line.split("=")[1].strip("{} ,\n")
+ if field == "author":
+ currentAuthor = filter(
+ lambda x: not (x in "\\\"{}"), value.split(" and ")[0])
+ if field == "citeulike-article-id":
+ currentArticleId = value
+ if field == "title":
+ currentTitle = re.sub(r'\}|\{', r'', value)
+
+ ###############################################################
+ # Checks (please (de)activate/extend to your needs)
+ ###############################################################
+
+ # check if type 'proceedings' might be 'inproceedings'
+ if currentType == "proceedings" and field == "pages":
+ subproblems.append(
+ "wrong type: maybe should be 'inproceedings' because entry has page numbers")
+ counterWrongTypes += 1
+
+ # check if abbreviations are used in journal titles
+ if currentType == "article" and (field == "journal" or field == "journaltitle"):
+
+ if "." in line:
+ subproblems.append(
+ "flawed name: abbreviated journal title '" + value + "'")
+ counterFlawedNames += 1
+
+ # check booktitle format; expected format "ICBAB '13: Proceeding of the 13th International Conference on Bla and Blubb"
+ # if currentType == "inproceedings" and field == "booktitle":
+ # if ":" not in line or ("Proceedings" not in line and "Companion" not in line) or "." in line or " '" not in line or "workshop" in line or "conference" in line or "symposium" in line:
+ #subproblems.append("flawed name: inconsistent formatting of booktitle '"+value+"'")
+ #counterFlawedNames += 1
+
+ # check if title is capitalized (heuristic)
+ # if field == "title":
+ # for word in currentTitle.split(" "):
+ #word = word.strip(":")
+ # if len(word) > 7 and word[0].islower() and not "-" in word and not "_" in word and not "[" in word:
+ #subproblems.append("flawed name: non-capitalized title '"+currentTitle+"'")
+ #counterFlawedNames += 1
+ # break
+
+ ###############################################################
+
+fIn.close()
+
+
+problemCount = counterMissingFields + counterFlawedNames + counterWrongFieldNames + counterWrongTypes + counterNonUniqueId
+
+# Write out our HTML file
+if options.htmlOutput:
+ html = open(options.htmlOutput, 'w', encoding="utf8")
+ html.write("""<!doctype html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>BibLatex Check</title>
+<style>
+body {
+ font-family: Calibri, Arial, Sans;
+ padding: 10px;
+ width: 1030px;
+ margin: 10px auto;
+ border-top: 1px solid black;
+}
+
+#title {
+ width: 720px;
+ border-bottom: 1px solid black;
+}
+
+#title h1 {
+ margin: 10px 0px;
+}
+
+#title h1 a {
+ color: black;
+ text-decoration: none;
+}
+
+#control {
+ clear: both;
+}
+
+#search {
+ float: left;
+}
+
+#search input {
+ width: 300px;
+ font-size: 14pt;
+}
+
+#mode {
+ text-align: right;
+}
+
+#mode label:first-child {
+ font-weight: bold;
+}
+
+#mode input {
+ margin-left: 20px;
+}
+
+.info {
+ margin-top: 10px;
+ padding: 10px;
+ background: #FAFADD;
+ width: 250px;
+ float: right;
+ box-shadow: 1px 1px 1px 1px #ccc;
+ clear: both;
+}
+
+.info h2 {
+ font-size: 12pt;
+ padding: 0px;
+ margin: 0px;
+}
+
+.problem {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 10px;
+ background: #FFBBAA;
+ counter-increment: problem;
+ width: 700px;
+ border: 1px solid #993333;
+ border-left: 5px solid #993333;
+ box-shadow: 1px 1px 1px 1px #ccc;
+ float: left;
+}
+
+.active {
+ box-shadow: 5px 5px 3px 3px #ccc;
+ position: relative;
+ top: -2px;
+}
+
+.severe0 {
+ background: #FAFAFA;
+ border: 1px solid black;
+ border-left: 5px solid black;
+}
+
+.severe1 {
+ background: #FFEEDD;
+}
+
+.severe2 {
+ background: #FFDDCC;
+}
+
+.severe3 {
+ background: #FFCCBB;
+}
+
+.problem_checked {
+ border: 1px solid #339933;
+ border-left: 5px solid #339933;
+}
+
+.problem h2:before {
+ content: counter(problem) ". "; color: gray;
+}
+
+.problem h2 {
+ font-size: 12pt;
+ padding: 0px;
+ margin: 0px;
+}
+
+.problem .links {
+ float: right;
+ position:relative;
+ top: -22px;
+}
+
+.problem .links a {
+ color: #3333CC;
+}
+
+.problem .links a:visited {
+ color: #666666;
+}
+
+.problem .reference {
+ clear: both;
+ font-size: 9pt;
+ margin-left: 20px;
+ font-style:italic;
+ font-weight:bold;
+}
+
+.problem ul {
+ clear: both;
+}
+
+.problem .problem_control {
+ float: right;
+ margin: 0px;
+ padding: 0px;
+}
+
+.problem .bibtex_toggle{
+ text-decoration: underline;
+ font-size: 9pt;
+ cursor: pointer;
+ padding-top: 5px;
+}
+
+.problem .bibtex {
+ margin-top: 5px;
+ font-family: Monospace;
+ font-size: 8pt;
+ display: none;
+ border: 1px solid black;
+ background-color: #FFFFFF;
+ padding: 5px;
+}
+</style>
+<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
+<script>
+
+function isInProblemMode() {
+ return $('#mode_problems:checked').val() == 'problems'
+}
+
+function update() {
+ $('.problem').hide();
+ $('.problem[id*='+$('#search input').val()+']').show();
+ $('.problem .checked').each(function () {
+ if ($(this).attr('checked')) {
+ $(this).parents('.problem').addClass('problem_checked');
+ } else {
+ $(this).parents('.problem').removeClass('problem_checked');
+ }
+ });
+ if (isInProblemMode()) {
+ $('.severe0').hide();
+ $('.problem_checked').hide();
+ }
+}
+
+$(document).ready(function(){
+
+ $(".bibtex_toggle").click(function(event){
+ event.preventDefault();
+ $(this).next().slideToggle();
+ });
+
+ $('#search input').live('input', function() {
+ update();
+ });
+
+ $('#mode input').change(function() {
+ update();
+ });
+
+ $("#uncheck_button").click(function(){
+ $('.problem .checked').attr('checked',false);
+ localStorage.clear();
+ update();
+ });
+
+ $('.problem a').mousedown(function(event) {
+ $('.problem').removeClass('active');
+ $(this).parents('.problem').addClass('active');
+ });
+
+ $('.problem .checked').change(function(event) {
+ var problem = $(this).parents('.problem');
+ problem.toggleClass('problem_checked');
+ var checked = problem.hasClass('problem_checked');
+ localStorage.setItem(problem.attr('id'),checked);
+ if (checked && isInProblemMode()) {
+ problem.slideUp();
+ }
+ });
+
+ $('.problem .checked').each(function () {
+ $(this).attr('checked',localStorage.getItem($(this).parents('.problem').attr('id'))=='true');
+ });
+ update();
+});
+
+</script>
+</head>
+<body>
+<div id="title">
+<h1><a href='http://github.com/pezmc/BibLatex-Check'>BibLaTeX Check</a></h1>
+<div id="control">
+<form id="search"><input placeholder="search entry ID ..."/></form>
+<form id="mode">
+<label>show entries:</label>
+<input type = "radio"
+ name = "mode"
+ id = "mode_problems"
+ value = "problems"
+ checked = "checked" />
+ <label for = "mode_problems">problems</label>
+ <input type = "radio"
+ name = "mode"
+ id = "mode_all"
+ value = "all" />
+ <label for = "mode_all">all</label>
+<input type="button" value="uncheck all" id="uncheck_button"></button>
+</form>
+<br style="clear: both; " />
+</div>
+</div>
+""")
+ html.write("<div class='info'><h2>Info</h2><ul>")
+ html.write("<li>bib file: " + options.bibFile + "</li>")
+ html.write("<li>aux file: " + options.auxFile + "</li>")
+ html.write("<li># entries: " + str(len(problems)) + "</li>")
+ html.write("<li># problems: " + str(problemCount) + "</li><ul>")
+ html.write("<li># missing fields: " + str(counterMissingFields) + "</li>")
+ html.write("<li># flawed names: " + str(counterFlawedNames) + "</li>")
+ html.write("<li># wrong types: " + str(counterWrongTypes) + "</li>")
+ html.write("<li># non-unique id: " + str(counterNonUniqueId) + "</li>")
+ html.write("<li># wrong field: " + str(counterWrongFieldNames) + "</li>")
+ html.write("</ul></ul></div>")
+
+ problems.sort()
+ for problem in problems:
+ html.write(problem)
+ html.write("</body></html>")
+ html.close()
+
+ if options.view:
+ import webbrowser
+ webbrowser.open(html.name)
+
+ print("SUCCESS: Report {} has been generated".format(options.htmlOutput))
+
+if problemCount > 0:
+ print("WARNING: Found {} problems.".format(problemCount))
+ sys.exit(-1)