Exemplo n.º 1
0
class LaTeXCompletionHandler(ICompletionHandler):
    """
	This implements the LaTeX-specific code completion
	"""
    _log = getLogger("LaTeXCompletionHandler")

    trigger_keys = ["backslash", "braceleft"]
    prefix_delimiters = ["\\"]

    def __init__(self):
        self._log.debug("init")

        self._language_model = LanguageModelFactory().create_language_model()
        self._bibtex_document_cache = BibTeXDocumentCache()

    def set_outline(self, outline):
        """
		Process a LaTeX outline model
		
		@param outline: a latex.outline.Outline instance
		"""

        # labels
        label_choices = [Choice(None, label.value) for label in outline.labels]
        self._language_model.fill_placeholder("Labels", label_choices)

        # colors
        color_choices = [Choice(None, color) for color in outline.colors]
        self._language_model.fill_placeholder("Colors", color_choices)

        # newcommands
        newcommands = []
        for n in outline.newcommands:
            command = Command(None, n.value)
            for i in range(n.numOfArgs):
                command.children.append(
                    MandatoryArgument(None, "#%s" % (i + 1)))
            newcommands.append(command)
        self._language_model.set_newcommands(newcommands)

        # newenvironments
        newenvironments = []
        for n in outline.newenvironments:
            choice = Choice(None, n.value)
            newenvironments.append(choice)
        self._language_model.fill_placeholder("Newenvironments",
                                              newenvironments)

        #
        # bibtex entries
        #
        try:

            entry_choices = []

            for bib_file in outline.bibliographies:
                try:
                    bibtex_document = self._bibtex_document_cache.get_document(
                        bib_file)

                    # generate choices from entries

                    for entry in bibtex_document.entries:

                        # build table data for DetailsPopup
                        rows = []
                        for field in entry.fields:
                            rows.append([field.name, field.valueMarkup])

                        entry_choices.append(Choice(None, entry.key, rows))

                except OSError:
                    # BibTeX file not found
                    self._log.error("Not found: %s" % bib_file)

            # attach to placeholders in CommandStore
            self._language_model.fill_placeholder("Bibitems", entry_choices)

        except IOError:
            self._log.debug(
                "Failed to provide BibTeX completion due to IOError")

    def set_neighbors(self, tex_files, bib_files, graphic_files):
        """
		Populate the lists of neighbor files
		
		@param tex_files: list of neighbor TeX files
		@param bib_files: list of neighbor BibTeX files
		@param graphic_files: list of neighbor graphics
		"""
        tex_choices = [Choice(None, file.shortbasename) for file in tex_files]
        self._language_model.fill_placeholder("TexFiles", tex_choices)

        bib_choices = [Choice(None, file.shortbasename) for file in bib_files]
        self._language_model.fill_placeholder("BibFiles", bib_choices)

        graphic_choices = [
            Choice(None, file.basename) for file in graphic_files
        ]
        self._language_model.fill_placeholder("ImageFiles", graphic_choices)

    def complete(self, prefix):
        """
		Try to complete a given prefix
		"""
        self._log.debug("complete: '%s'" % prefix)

        #proposals = [LaTeXTemplateProposal(Template("Hello[${One}][${Two}][${Three}]"), "Hello[Some]"), LaTeXProposal("\\world")]

        fragment = Node(Node.DOCUMENT)
        parser = PrefixParser()

        try:
            parser.parse(prefix, fragment)

            modelParser = PrefixModelParser(self._language_model)
            proposals = modelParser.parse(fragment)

            self._log.debug("Generated %s proposals" % len(proposals))

            return proposals

        except Exception, e:
            self._log.debug(e)

        return []
Exemplo n.º 2
0
 def __init__(self):
     self._environment = Environment()
     #the the language_model singleton
     self._language_model = LanguageModelFactory().get_language_model()
Exemplo n.º 3
0
    def __init__(self):
        self._log.debug("init")

        self._language_model = LanguageModelFactory().create_language_model()
        self._bibtex_document_cache = BibTeXDocumentCache()
Exemplo n.º 4
0
class LaTeXValidator(object):
    """
    This validates the following aspects by walking the document model
    and using the outline:

     * unused labels
     * unclosed environments, also "\[" and "\]"
    """

    def __init__(self):
        self._environment = Environment()
        #the the language_model singleton
        self._language_model = LanguageModelFactory().get_language_model()

    def validate(self, document_node, outline, issue_handler, document_preferences):
        """
        Validate a LaTeX document

        @param document_node: the root node of the document tree
        @param outline: a LaTeX outline object
        @param issue_handler: an object implementing IIssueHandler
        @param document_preferences: a DocumentPreferences object, so we can query the
               graphics file extensions, etc
        """

        LOG.debug("Validating")

        #~ # TODO: this is dangerous, the outline object could be outdated
        #~ self._outline = outline

        # cache some settings now to save time
        self._potential_graphics_extensions = [""] + document_preferences.get("graphics-extensions").split(",")
        self._potential_graphics_paths = document_preferences.get("graphics-paths").split(",")
        self._extra_issue_commands = set([c for c in document_preferences.get("extra-issue-commands").split(",") if len(c)])

        # prepare a map for checking labels
        self._labels = {}
        for label in outline.labels:
            self._labels[label.value] = [label, False]

        self._environStack = []

        self._checkRefs = True

        self._run(document_node, issue_handler)

        # evaluate label map
        for label, used in self._labels.values():
            if not used:
                # FIXME: we need to know in which File the label was defined!
                issue_handler.issue(Issue("Label <b>%s</b> is never used" % escape(label.value), label.start, label.end, label.file, Issue.SEVERITY_WARNING))

    def _run(self, parentNode, issue_handler):
        """
        Recursive method validation
        """
        for node in parentNode:
            recurse = True
#            if node.type == Node.DOCUMENT:
#
#                self._log.debug("DOCUMENT: %s" % node.value)
#
#                # the document node contains the File object as value
#                self._file = node.value

            if node.type == Node.COMMAND:
                if node.value == "begin":
                    try:
                        # push environment on stack
                        environ = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        self._environStack.append((environ, node.start, node.lastEnd))
                    except IndexError:
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif node.value == "end":
                    try:
                        # check environment
                        environ = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        try:
                            tEnviron, tStart, tEnd = self._environStack.pop()
                            if tEnviron != environ:
                                issue_handler.issue(Issue("Environment <b>%s</b> has to be ended before <b>%s</b>" % (escape(tEnviron), escape(environ)), node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))
                        except IndexError:
                            issue_handler.issue(Issue("Environment <b>%s</b> has no beginning" % escape(environ), node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))
                    except IndexError:
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif node.value == "[":
                    # push eqn env on stack
                    self._environStack.append(("[", node.start, node.end))

                elif node.value == "]":
                    try:
                        tEnviron, tStart, tEnd = self._environStack.pop()
                        if tEnviron != "[":
                            issue_handler.issue(Issue("Environment <b>%s</b> has to be ended before <b>]</b>" % escape(tEnviron), node.start, node.end, node.file, Issue.SEVERITY_ERROR))
                    except IndexError:
                        issue_handler.issue(Issue("Environment <b>%s</b> has no beginning" % escape(environ), node.start, node.end, node.file, Issue.SEVERITY_ERROR))

                elif self._language_model.is_ref_command(node.value):
                    # mark label as used
                    try:
                        label = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        try:
                            self._labels[label][1] = True
                        except KeyError:
                            issue_handler.issue(Issue("Label <b>%s</b> has not been defined" % escape(label), node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))
                    except IndexError:
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif self._checkRefs and (node.value == "includegraphics"):
                    try:
                        # check referenced image file
                        target = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        if len(target) > 0:
                            found = False

                            if File.is_absolute(target):
                                for ext in self._potential_graphics_extensions:
                                    if exists(target + ext):
                                        found = True
                                        break
                            else:
                                for p in self._potential_graphics_paths:
                                    if found: break
                                    for ext in self._potential_graphics_extensions:
                                        if found: break
                                        filename = os.path.abspath(os.path.join(node.file.dirname, p, target) + ext)
                                        if os.path.exists(filename):
                                            found = True

                            if not found:
                                issue_handler.issue(Issue("Image <b>%s</b> could not be found" % escape(target), node.start, node.lastEnd, node.file, Issue.SEVERITY_WARNING))
                        else:
                            issue_handler.issue(Issue("No image file specified", node.start, node.lastEnd, node.file, Issue.SEVERITY_WARNING))
                    except IndexError:
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif self._checkRefs and (node.value == "include" or node.value == "input"):
                    # check referenced tex file
                    try:
                        target = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        if len(target) > 0:
                            if File.is_absolute(target):
                                filename = target
                            else:
                                file = File.create_from_relative_path(target, node.file.dirname)
                                filename = file.path

                            # an input may be specified without the extension
                            potential_extensions = ["", ".tex"]

                            found = False
                            for ext in potential_extensions:
                                if exists(filename + ext):
                                    found = True
                                    break

                            if not found:
                                issue_handler.issue(Issue("Document <b>%s</b> could not be found" % escape(filename), node.start, node.lastEnd, node.file, Issue.SEVERITY_WARNING))
                    except IndexError:        # firstOfType failed
                        # this happens on old-style syntax like "\input myfile"
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif self._checkRefs and node.value == "bibliography":
                    try:
                        # check referenced BibTeX file(s)
                        value = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                        for target in value.split(","):
                            if File.is_absolute(target):
                                filename = target
                            else:
                                file = File.create_from_relative_path(target, node.file.dirname)
                                filename = file.path

                            # a bib file may be specified without the extension
                            potential_extensions = ["", ".bib"]

                            found = False
                            for ext in potential_extensions:
                                if exists(filename + ext):
                                    found = True
                                    break

                            if not found:
                                issue_handler.issue(Issue("Bibliography <b>%s</b> could not be found" % escape(filename), node.start, node.lastEnd, node.file, Issue.SEVERITY_WARNING))
                    except IndexError:        # firstOfType failed
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif node.value == "newcommand":
                    # don't validate in newcommand definitions
                    recurse = False

                elif node.value == "bibliographystyle":
                    try:
                        # check if style exists
                        value = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText

                        # search the TeX environment
                        if not self._environment.file_exists("%s.bst" % value):
                            # search the working directory
                            bst_file = File.create_from_relative_path("%s.bst" % value, node.file.dirname)
                            if not bst_file.exists:
                                issue_handler.issue(Issue("Bibliography style <b>%s</b> could not be found" % escape(value), node.start, node.lastEnd, node.file, Issue.SEVERITY_WARNING))
                    except IndexError:
                        issue_handler.issue(Issue("Malformed command", node.start, node.lastEnd, node.file, Issue.SEVERITY_ERROR))

                elif node.value in self._extra_issue_commands:
                    try:
                        text = node.firstOfType(Node.MANDATORY_ARGUMENT).innerText
                    except IndexError:
                        text = node.value
                    issue_handler.issue(Issue(text, node.start, node.lastEnd, node.file, Issue.SEVERITY_TASK))

            if recurse:
                self._run(node, issue_handler)
Exemplo n.º 5
0
 def __init__(self):
     self._log.debug("init")
     #get the language_model singleton
     self._language_model = LanguageModelFactory().get_language_model()
     self._bibtex_document_cache = BibTeXDocumentCache()
Exemplo n.º 6
0
class LaTeXCompletionHandler(ICompletionHandler):
	"""
	This implements the LaTeX-specific code completion
	"""
	_log = getLogger("LaTeXCompletionHandler")

	trigger_keys = ["backslash", "braceleft"]
	prefix_delimiters = ["\\"]

	def __init__(self):
		self._log.debug("init")

		self._language_model = LanguageModelFactory().create_language_model()
		self._bibtex_document_cache = BibTeXDocumentCache()

	def set_outline(self, outline):
		"""
		Process a LaTeX outline model

		@param outline: a latex.outline.Outline instance
		"""

		# labels
		label_choices = [Choice(None, label.value) for label in outline.labels]
		self._language_model.fill_placeholder("Labels", label_choices)

		# colors
		color_choices = [Choice(None, color) for color in outline.colors]
		self._language_model.fill_placeholder("Colors", color_choices)

		# newcommands
		newcommands = []
		for n in outline.newcommands:
			command = Command(None, n.value)
			for i in range(n.numOfArgs):
				command.children.append(MandatoryArgument(None, "#%s" % (i + 1)))
			newcommands.append(command)
		self._language_model.set_newcommands(newcommands)

		# newenvironments
		newenvironments = []
		for n in outline.newenvironments:
			choice = Choice(None, n.value)
			newenvironments.append(choice)
		self._language_model.fill_placeholder("Newenvironments", newenvironments)

		#
		# bibtex entries
		#
		try:

			entry_choices = []

			for bib_file in outline.bibliographies:
				try:
					bibtex_document = self._bibtex_document_cache.get_document(bib_file)

					# generate choices from entries

					for entry in bibtex_document.entries:

						# build table data for DetailsPopup
						rows = []
						for field in entry.fields:
							rows.append([field.name, field.valueMarkup])

						entry_choices.append(Choice(None, entry.key, rows))

				except OSError:
					# BibTeX file not found
					self._log.error("Not found: %s" % bib_file)

			# attach to placeholders in CommandStore
			self._language_model.fill_placeholder("Bibitems", entry_choices)

		except IOError:
			self._log.debug("Failed to provide BibTeX completion due to IOError")


	def set_neighbors(self, tex_files, bib_files, graphic_files):
		"""
		Populate the lists of neighbor files

		@param tex_files: list of neighbor TeX files
		@param bib_files: list of neighbor BibTeX files
		@param graphic_files: list of neighbor graphics
		"""
		tex_choices = [Choice(None, file.shortbasename) for file in tex_files]
		self._language_model.fill_placeholder("TexFiles", tex_choices)

		bib_choices = [Choice(None, file.shortbasename) for file in bib_files]
		self._language_model.fill_placeholder("BibFiles", bib_choices)

		graphic_choices = [Choice(None, file.basename) for file in graphic_files]
		self._language_model.fill_placeholder("ImageFiles", graphic_choices)

	def complete(self, prefix):
		"""
		Try to complete a given prefix
		"""
		self._log.debug("complete: '%s'" % prefix)

		#proposals = [LaTeXTemplateProposal(Template("Hello[${One}][${Two}][${Three}]"), "Hello[Some]"), LaTeXProposal("\\world")]

		fragment = Node(Node.DOCUMENT)
		parser = PrefixParser()

		try:
			parser.parse(prefix, fragment)

			modelParser = PrefixModelParser(self._language_model)
			proposals = modelParser.parse(fragment)

			self._log.debug("Generated %s proposals" % len(proposals))

			return proposals

		except Exception, e:
			self._log.debug(e)

		return []
Exemplo n.º 7
0
	def __init__(self):
		self._log.debug("init")

		self._language_model = LanguageModelFactory().create_language_model()
		self._bibtex_document_cache = BibTeXDocumentCache()
Exemplo n.º 8
0
 def __init__(self):
     self._log.debug("init")
     #get the language_model singleton
     self._language_model = LanguageModelFactory().get_language_model()
     self._bibtex_document_cache = BibTeXDocumentCache()