overridedef theory_suffix: String = "bibtex_file" overridedef theory_content(name: String): String = """theory "bib" imports Pure begin bibtex_file "." end""" overridedef theory_excluded(name: String): Boolean = name == "bib"
overridedef html_document(snapshot: Document.Snapshot): Option[Browser_Info.HTML_Document] = { val name = snapshot.node_name if (detect(name.node)) { val title = "Bibliography " + quote(snapshot.node_name.file_name) val content =
Isabelle_System.with_tmp_file("bib", "bib") { bib =>
File.write(bib, snapshot.node.source)
Bibtex.html_output(List(bib), style = "unsort", title = title)
}
Some(Browser_Info.HTML_Document(title, content))
} else None
}
}
/** bibtex errors **/
def bibtex_errors(dir: Path, root_name: String): List[String] = { val log_path = dir + Path.explode(root_name).blg if (log_path.is_file) { val Error1 = """^(I couldn't open database file .+)$""".r val Error2 = """^(I found no .+)$""".r val Error3 = """^(.+)---line (\d+) of file (.+)""".r
Line.logical_lines(File.read(log_path)).flatMap(line =>
line match { case Error1(msg) => Some("Bibtex error: " + msg) case Error2(msg) => Some("Bibtex error: " + msg) case Error3(msg, Value.Int(l), file) => val path = File.standard_path(file) if (Path.is_wellformed(path)) { val pos = Position.Line_File(l, (dir + Path.explode(path)).canonical.implode)
Some("Bibtex error" + Position.here(pos) + ":\n " + msg)
} else None case _ => None
})
} else Nil
}
/** check database **/
def check_database(database: String): (List[(String, Position.T)], List[(String, Position.T)]) = { val chunks = parse(Line.normalize(database)) var chunk_pos = Map.empty[String, Position.T] val tokens = new mutable.ListBuffer[(Token, Position.T)] var line = 1 var offset = 1
val Error = """^(.*)---line (\d+) of file root.bib$""".r val Warning = """^Warning--(.+)$""".r val Warning_Line = """--line (\d+) of file root.bib$""".r val Warning_in_Chunk = """^Warning--(.+) in (.+)$""".r
val log_file = tmp_dir + Path.explode("root.blg") val lines = if (log_file.is_file) Line.logical_lines(File.read(log_file)) else Nil
val (errors, warnings) = if (lines.isEmpty) (Nil, Nil) else {
lines.zip(lines.tail ::: List("")).flatMap(
{ case (Error(msg, Value.Int(l)), _) =>
Some((true, (msg, get_line_pos(l)))) case (Warning_in_Chunk(msg, name), _) if chunk_pos.isDefinedAt(name) =>
Some((false, (Word.capitalized(msg) + " in entry " + quote(name), chunk_pos(name)))) case (Warning(msg), Warning_Line(Value.Int(l))) =>
Some((false, (Word.capitalized(msg), get_line_pos(l)))) case (Warning(msg), _) =>
Some((false, (Word.capitalized(msg), Position.none))) case _ => None
}
).partition(_._1)
}
(errors.map(_._2), warnings.map(_._2))
}
}
object Session_Entries extends Scala.Fun("bibtex_session_entries") { val here = Scala_Project.here
overridedef invoke(session: Session, args: List[Bytes]): List[Bytes] = { val sessions = session.resources.sessions_structure val id = Value.Long.parse(Library.the_single(args).text) val qualifier =
session.get_state().lookup_id(id) match { case None => Sessions.DRAFT case Some(st) => sessions.theory_qualifier(st.command.node_name.theory)
} val res = if (qualifier == Sessions.DRAFT || !sessions.defined(qualifier)) Nil else qualifier :: sessions(qualifier).bibtex_entries.entries.map(_.encode)
res.map(Bytes.apply)
}
}
object Token { object Kind extends Enumeration { val COMMAND = Value("command") val ENTRY = Value("entry") val KEYWORD = Value("keyword") val NAT = Value("natural number") val STRING = Value("string") val NAME = Value("name") val IDENT = Value("identifier") val SPACE = Value("white space") val COMMENT = Value("ignored text") val ERROR = Value("bad input")
}
}
privateval content: Option[List[Token]] =
tokens match { case Token(Token.Kind.KEYWORD, "@") :: body if body.nonEmpty =>
(body.init.filterNot(_.is_ignored), body.last) match { case (tok :: Token(Token.Kind.KEYWORD, "{") :: toks, Token(Token.Kind.KEYWORD, "}")) if tok.is_kind => Some(toks)
case (tok :: Token(Token.Kind.KEYWORD, "(") :: toks, Token(Token.Kind.KEYWORD, ")")) if tok.is_kind => Some(toks)
case _ => None
} case _ => None
}
def name: String =
content match { case Some(tok :: _) if tok.is_name => tok.source case _ => ""
}
def heading_length: Int = if (name == "") 1 else {
tokens.takeWhile(tok => !tok.is_open).foldLeft(0) { case (n, tok) => n + tok.source.length }
}
privateval body =
delimited | (recover_delimited | other_token)
privatedef body_line(ctxt: Item) = if (ctxt.delim.depth > 0)
delimited_line(ctxt) else
delimited_line(ctxt) |
other_token ^^ { case a => (Chunk(ctxt.kind, List(a)), ctxt) } |
ctxt.end ^^ { case a => (Chunk(ctxt.kind, List(keyword(a))), Ignored) }
/* items: command or entry */
privateval item_kind =
identifier ^^ { case a => val kind = if (is_command(a)) Token.Kind.COMMAND elseif (known_entry(a).isDefined) Token.Kind.ENTRY else Token.Kind.IDENT
Token(kind, a)
}
privateval item_begin = "{" ^^ { case a => ("}", keyword(a)) } | "(" ^^ { case a => (")", keyword(a)) }
privatedef item_name(kind: String) =
kind.toLowerCase match { case"preamble" => failure("") case"string" => identifier ^^ token(Token.Kind.NAME) case _ => name
}
privateval item_start =
at ~ spaces ~ item_kind ~ spaces ^^
{ case a ~ b ~ c ~ d => (c.source, List(a) ::: b ::: List(c) ::: d) }
privateval item: Parser[Chunk] =
(item_start ~ item_begin ~ spaces) into
{ case (kind, a) ~ ((end, b)) ~ c =>
opt(item_name(kind)) ~ rep(body) ~ opt(end ^^ keyword) ^^ { case d ~ e ~ f => Chunk(kind, a ::: List(b) ::: c ::: d.toList ::: e ::: f.toList) } }
privateval recover_item: Parser[Chunk] =
at ~ "[^@]*".r ^^ { case a ~ b => Chunk("", List(a, Token(Token.Kind.ERROR, b))) }
/* chunks */
val chunk: Parser[Chunk] = ignored | (item | recover_item)
def chunk_line(ctxt: Line_Context): Parser[(Chunk, Line_Context)] = {
ctxt match { case Ignored =>
ignored_line |
at ^^ { case a => (Chunk("", List(a)), At) }
case At =>
space ^^ { case a => (Chunk("", List(a)), ctxt) } |
item_kind ^^ { case a => (Chunk(a.source, List(a)), Item_Start(a.source)) } |
recover_item ^^ { case a => (a, Ignored) } |
ignored_line
case Item_Start(kind) =>
space ^^ { case a => (Chunk(kind, List(a)), ctxt) } |
item_begin ^^ { case (end, a) => (Chunk(kind, List(a)), Item_Open(kind, end)) } |
recover_item ^^ { case a => (a, Ignored) } |
ignored_line
case Item_Open(kind, end) =>
space ^^ { case a => (Chunk(kind, List(a)), ctxt) } |
item_name(kind) ^^ { case a => (Chunk(kind, List(a)), Item(kind, end, Closed)) } |
body_line(Item(kind, end, Closed)) |
ignored_line
case item_ctxt: Item =>
body_line(item_ctxt) |
ignored_line
case _ => failure("")
}
}
}
/* parse */
def parse(input: CharSequence): List[Chunk] =
Parsers.parseAll(Parsers.rep(Parsers.chunk), Scan.char_reader(input)) match { case Parsers.Success(result, _) => result case _ => error("Unexpected failure to parse input:\n" + input.toString)
}
def parse_line(input: CharSequence, context: Line_Context): (List[Chunk], Line_Context) = { var in: Reader[Char] = Scan.char_reader(input) val chunks = new mutable.ListBuffer[Chunk] var ctxt = context while (!in.atEnd) { val result = Parsers.parse(Parsers.chunk_line(ctxt), in)
(result : @unchecked) match { case Parsers.Success((x, c), rest) => chunks += x; ctxt = c; in = rest case Parsers.NoSuccess(_, rest) =>
error("Unepected failure to parse input:\n" + rest.source.toString)
}
}
(chunks.toList, ctxt)
}
val bib_files = bib.map(_.drop_ext) val bib_names = { val names0 = bib_files.map(_.file_name) if (Library.duplicates(names0).isEmpty) names0 else names0.zipWithIndex.map({ case (name, i) => (i + 1).toString + "-" + name })
}
for ((a, b) <- bib_files zip bib_names) {
Isabelle_System.copy_file(a.bib, tmp_dir + Path.basic(b).bib)
}
/* style file */
val bst =
output_styles.toMap.get(style) match { case Some(base) => base + (if (chronological) "c"else"") + ".bst" case None =>
error("Bad style for bibtex HTML output: " + quote(style) + "\n(expected: " + commas_quote(output_styles.map(_._1)) + ")")
}
Isabelle_System.copy_file(Path.explode("$BIB2XHTML_HOME/bst") + Path.explode(bst), tmp_dir)
/* result */
val in_file = Path.explode("bib.aux") val out_file = Path.explode("bib.html")
if (body) {
cat_lines(
split_lines(html).
dropWhile(line => !line.startsWith("<!-- BEGIN BIBLIOGRAPHY")).reverse.
dropWhile(line => !line.startsWith("<!-- END BIBLIOGRAPHY")).reverse)
} else html
}
}
val location: Parser[String] = embedded ~ $$$("in") ^^ { case x ~ _ => x } | success("") val citations: Parser[String] = rep1sep(name, $$$("and")) ^^ (x => x.mkString(",")) val kind: Parser[String] = $$$("using") ~! name ^^ { case _ ~ x => x } | success(CITE)
def inner(pos: Position.T): Parser[Inner] =
location ~ citations ~ kind ^^
{ case x ~ y ~ z => Inner(z, y, XML.string(x), pos) }
}
def parse(
cite_commands: List[String],
text: String,
start: Isar_Token.Pos = Isar_Token.Pos.start
): List[Outer] = { val controls = cite_commands.map(s => Symbol.control_prefix + s + Symbol.control_suffix) val special = (controls ::: controls.map(Symbol.decode)).toSet
val Parsers = Antiquote.Parsers
Parsers.parseAll(Parsers.rep(Parsers.antiquote_special(special)), text) match { case Parsers.Success(ants, _) => var pos = start val result = new mutable.ListBuffer[Outer] for (ant <- ants) {
ant match { case Antiquote.Control(source) => for {
head <- Symbol.iterator(source).nextOption
kind <- Symbol.control_name(Symbol.encode(head))
} { val rest = source.substring(head.length) val (body, pos1) = if (rest.isEmpty) (rest, pos) else (Scan.Parsers.cartouche_content(rest), pos.advance(Symbol.open))
result += Outer(kind, body, pos1)
} case _ =>
}
pos = pos.advance(ant.source)
}
result.toList case _ => error("Unexpected failure parsing special antiquotations:\n" + text)
}
}
}
/* update old forms: @{cite ...} and \cite{...} */
def cite_antiquotation(name: String, body: String): String = """\<^""" + name + """>\<open>""" + body + """\<close>"""
def cite_antiquotation(name: String, location: String, citations: List[String]): String = { val body =
if_proper(location, Symbol.cartouche(location) + " in ") +
citations.map(quote).mkString(" and ")
cite_antiquotation(name, body)
}
def update_cite_commands(str: String): String =
Cite_Command.replaceAllIn(str, { m => val name = m.group(1) val loc = m.group(2) val location = if (loc.startsWith("[") && loc.endsWith("]")) loc.substring(1, loc.length - 1) else loc val citations = space_explode(',', m.group(3)).map(_.trim)
Regex.quoteReplacement(cite_antiquotation(name, location, citations))
})
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.