Example #1
0
class TestSpellChecker(unittest.TestCase):
    def setUp(self):
        self.spellChecker = SpellChecker()
        self.spellChecker.load_words('spell.words')

    def test_spell_checker(self):
        self.assertTrue(self.spellChecker.check_word('zygotic'))
        failed_words = self.spellChecker.check_words(
            'zygotic mistasdas elementary')
        self.assertEquals(1, len(failed_words))
        self.assertEquals('mistasdas', failed_words[0]['word'])
        self.assertEquals(1, failed_words[0]['line'])
        self.assertEquals(9, failed_words[0]['pos'])
        self.assertEquals(
            0,
            len(self.spellChecker.check_words('our first correct sentence')))
        # handle case sensitivity
        self.assertEquals(
            0, len(self.spellChecker.check_words('Our capital sentence')))
        # handle full stop
        self.assertEquals(
            0, len(self.spellChecker.check_words('Our full stop sentence.')))
        failed_words = self.spellChecker.check_words(
            'zygotic mistasdas spelllleeeing elementary')
        self.assertEquals(2, len(failed_words))
        self.assertEquals('mistasdas', failed_words[0]['word'])
        self.assertEquals(1, failed_words[0]['line'])
        self.assertEquals(9, failed_words[0]['pos'])
        self.assertEquals('spelllleeeing', failed_words[1]['word'])
        self.assertEquals(1, failed_words[1]['line'])
        self.assertEquals(19, failed_words[1]['pos'])
        self.spellChecker.check_document('stuff.txt')
Example #2
0
class TestSpellChecker(unittest.TestCase):
    def setUp(self):
        self.spellChecker = SpellChecker()
        self.spellChecker.load_words('spell.words')

    def test_spell_checker(self):
        self.assertTrue(self.spellChecker.check_word('zygotic'))
        failed_words = self.spellChecker.check_words(
                'zygotic mistasdas elementary')
        self.assertEquals(1, len(failed_words))
        self.assertEquals('mistasdas', failed_words[0])
        self.assertEquals(0, len(self.spellChecker.check_words(
                'our first correct sentence')))
        # handle case sensitivity
        self.assertEquals(0, len(self.spellChecker.check_words(
                'Our first correct sentence')))
        # handle full stop
        self.assertEquals(0, len(self.spellChecker.check_words(
                'Our first correct sentence.')))
        failed_words = self.spellChecker.check_words(
                'zygotic mistasdas spelllleeeing elementary')
        self.assertEquals(2, len(failed_words))
        self.assertEquals('mistasdas', failed_words[0])
        self.assertEquals('spelllleeeing', failed_words[1])
        # more bugs because the spell checker doesn't spell check itself correctly 21 entries not correct dictionary words need to be lower
        self.assertEqual(0, len(self.spellChecker.check_document('spell.words')))
class TestSpellChecker(unittest.TestCase):

    def setUp(self):
        self.spellChecker = SpellChecker()
        # This is the path name for our dictionary file
        file_name = '/Users/barrysheppard/Github/DBSDataAnalysis/'
        file_name = file_name + 'BigData/04Lecture/spell.words'
        self.spellChecker.load_words(file_name)

    def test_spell_checker(self):
        self.assertTrue(self.spellChecker.check_word('zygotic'))
        failed_words = self.spellChecker.check_words('zygotic mistasdas elementary')
        self.assertEqual(1, len(failed_words))
        self.assertEqual('mistasdas', failed_words[0]['word'])
        self.assertEqual(1, failed_words[0]['line'])
        self.assertEqual(9, failed_words[0]['pos'])
        self.assertEqual(0, len(self.spellChecker.check_words('our first correct sentence')))
        # handle case sensitivity
        self.assertEqual(0, len(self.spellChecker.check_words('Our capital sentence')))
        # handle full stop
        self.assertEqual(0, len(self.spellChecker.check_words('Our full stop sentence.')))
        failed_words = self.spellChecker.check_words('zygotic mistasdas spelllleeeing elementary')
        self.assertEqual(2, len(failed_words))
        self.assertEqual('mistasdas', failed_words[0]['word'])
        self.assertEqual(1, failed_words[0]['line'])
        self.assertEqual(9, failed_words[0]['pos'])
        self.assertEqual('spelllleeeing', failed_words[1]['word'])
        self.assertEqual(1, failed_words[1]['line'])
        self.assertEqual(19, failed_words[1]['pos'])
        self.assertEqual(0, len(self.spellChecker.check_document('spell.words')))
Example #4
0
class SpellCheckerTestCase(unittest.TestCase):
    def setUp(self):
        self.checker = SpellChecker()

    def test_complete(self):
        self.assertEqual(self.checker.complete(''), [
            'I', 'The', "I'm", 'You', 'My', 'It', 'But', 'If', 'This', "It's",
            'And', 'So', 'He', 'A', 'Just', 'In', 'We', 'What', 'Why', 'No'
        ])

    def test_correct(self):
        self.assertEqual(self.checker.correct('wrrong'), 'wrong')

    def test_guess(self):
        self.assertEqual(self.checker.guess('aa'), ['as', 'era'])
Example #5
0
    def init(self, file, context):
        """
		@param file: base.File
		@param context: base.WindowContext
		"""
        self._log.debug("init(%s)" % file)

        self._file = file
        self._context = context

        self._preferences = Preferences()
        self._preferences.register_monitor(
            self)  # listen to 'Show...InOutline' settings

        self.register_marker_type(
            "latex-spell",
            self._preferences.get("SpellingBackgroundColor"),
            anonymous=False)
        self.register_marker_type(
            "latex-error", self._preferences.get("ErrorBackgroundColor"))
        self.register_marker_type(
            "latex-warning", self._preferences.get("WarningBackgroundColor"))

        self._issue_view = context.find_view(self, "IssueView")
        self._outline_view = context.find_view(self, "LaTeXOutlineView")

        self._parser = LaTeXParser()
        self._outline_generator = LaTeXOutlineGenerator()
        self._validator = LaTeXValidator()
        self._document = None

        self._document_dirty = True

        # if the document is no master we display an info message on the packages to
        # include - _ensured_packages holds the already mentioned packages to not
        # annoy the user
        self._ensured_packages = []

        # spell checking
        self.__spell_checker = SpellChecker()

        #
        # initially parse
        #
        self._change_reference = self.initial_timestamp

        self.__parse()
        self.__update_neighbors()
Example #6
0
	def init(self, file, context):
		"""
		@param file: base.File
		@param context: base.WindowContext
		"""
		self._log.debug("init(%s)" % file)

		self._file = file
		self._context = context

		self._preferences = Preferences()
		self._preferences.register_monitor(self)	# listen to 'Show...InOutline' settings

		self.register_marker_type("latex-spell", self._preferences.get("SpellingBackgroundColor"), anonymous=False)
		self.register_marker_type("latex-error", self._preferences.get("ErrorBackgroundColor"))
		self.register_marker_type("latex-warning", self._preferences.get("WarningBackgroundColor"))

		self._issue_view = context.find_view(self, "IssueView")
		self._outline_view = context.find_view(self, "LaTeXOutlineView")

		self._parser = LaTeXParser()
		self._outline_generator = LaTeXOutlineGenerator()
		self._validator = LaTeXValidator()
		self._document = None

		self._document_dirty = True

		# if the document is no master we display an info message on the packages to
		# include - _ensured_packages holds the already mentioned packages to not
		# annoy the user
		self._ensured_packages = []

		# spell checking
		self.__spell_checker = SpellChecker()

		#
		# initially parse
		#
		self._change_reference = self.initial_timestamp

		self.__parse()
		self.__update_neighbors()
Example #7
0
class LaTeXEditor(Editor, IIssueHandler, IMisspelledWordHandler,
                  IPreferencesMonitor):

    _log = getLogger("LaTeXEditor")

    #extensions = [".tex"]
    extensions = Preferences().get("LatexExtensions", ".tex").split(" ")

    dnd_extensions = [".png", ".pdf", ".bib", ".tex"]

    @property
    def completion_handlers(self):
        self.__latex_completion_handler = LaTeXCompletionHandler()
        self.__snippet_completion_handler = SnippetCompletionHandler()

        return [
            self.__latex_completion_handler, self.__snippet_completion_handler
        ]

    def init(self, file, context):
        """
		@param file: base.File
		@param context: base.WindowContext
		"""
        self._log.debug("init(%s)" % file)

        self._file = file
        self._context = context

        self._preferences = Preferences()
        self._preferences.register_monitor(
            self)  # listen to 'Show...InOutline' settings

        self.register_marker_type(
            "latex-spell",
            self._preferences.get("SpellingBackgroundColor"),
            anonymous=False)
        self.register_marker_type(
            "latex-error", self._preferences.get("ErrorBackgroundColor"))
        self.register_marker_type(
            "latex-warning", self._preferences.get("WarningBackgroundColor"))

        self._issue_view = context.find_view(self, "IssueView")
        self._outline_view = context.find_view(self, "LaTeXOutlineView")

        self._parser = LaTeXParser()
        self._outline_generator = LaTeXOutlineGenerator()
        self._validator = LaTeXValidator()
        self._document = None

        self._document_dirty = True

        # if the document is no master we display an info message on the packages to
        # include - _ensured_packages holds the already mentioned packages to not
        # annoy the user
        self._ensured_packages = []

        # spell checking
        self.__spell_checker = SpellChecker()

        #
        # initially parse
        #
        self._change_reference = self.initial_timestamp

        self.__parse()
        self.__update_neighbors()

    def _on_value_changed(self, key, new_value):
        # see preferences.IPreferencesMonitor._on_value_changed

        if key in [
                "ShowLabelsInOutline", "ShowTablesInOutline",
                "ShowGraphicsInOutline"
        ]:
            # regenerate outline model
            if self._document_is_master:
                self._outline = self._outline_generator.generate(
                    self._document, self)
                self._outline_view.set_outline(self._outline)
            else:
                # FIXME: self._document contains the full model of child and master
                # so we may not use it for regenerating the outline here
                self.__parse()
        elif key == "ShowLatexToolbar":
            show_toolbar = self._preferences.get_bool("ShowLatexToolbar", True)
            if show_toolbar:
                self._window_context._window_decorator._toolbar.show()
            else:
                self._window_context._window_decorator._toolbar.hide()

    def _ctrl_left_clicked(self, it):
        """
		For synchronization by synctex
		"""
        # Editor._ctrl_left_clicked

        tab = self.tab_decorator.tab
        line = it.get_line() + 1
        column = it.get_line_offset() + 1
        source_file = "%s/%s" % (self._file.dirname, self._file.basename)
        # We use self.file and not self._file here, to get the
        # master document, because the output file will have the
        # name of the master document
        try:
            output_file = "%s.pdf" % self.file.shortname
        except:
            # Is this due to a bug ? Or is there a method I
            # don't know to check wether a file has/is a
            # master file or doesn't/couldn't have one ?
            self.__log.debug(
                "Error while trying to get the output file path. No master document ?"
            )
            return

        from livepreview import LaTeXPreviews

        if self._window_context.latex_previews == None:
            self._window_context.latex_previews = LaTeXPreviews(
                self._window_context)

        latex_previews = self._window_context.latex_previews
        latex_previews.sync_view(tab, source_file, line, column, output_file)

    def drag_drop_received(self, files):
        # see base.Editor.drag_drop_received

        # TODO: we need to insert the source at the drop location - so pass it here

        self._log.debug("drag_drop: %s" % files)

#		if len(files) == 1:
#			file = files[0]
#			self._log.debug("Got one file: %s, extension: %s" % (file.path, file.extension))
#			if file.extension == ".png":
#				self._log.debug("PNG image - including...")
#				source = "\\includegraphics{%s}" % file.path
#				self.insert(source)

    def insert(self, source):
        # see base.Editor.insert

        if type(source) is LaTeXSource:
            if source.packages and len(source.packages) > 0:
                self.ensure_packages(source.packages)

            Editor.insert(self, source.source)
        else:
            Editor.insert(self, source)

    POSITION_PACKAGES, POSITION_BIBLIOGRAPHY = 1, 2

    def insert_at_position(self, source, position):
        """
		Insert source at a certain position in the LaTeX document:

		 * POSITION_PACKAGES: after the last \usepackage statement
		 * POSITION_BIBLIOGRAPHY: before \end{document}

		@param source: a LaTeXSource object
		@param position: POSITION_PACKAGES | POSITION_BIBLIOGRAPHY
		"""

        if position == self.POSITION_BIBLIOGRAPHY:
            offset = self._document.end_of_document
            Editor.insert_at_offset(self, offset, source, True)
        elif position == self.POSITION_PACKAGES:
            offset = self._document.end_of_packages
            Editor.insert_at_offset(self, offset, source, False)
        else:
            raise NotImplementedError

    def ensure_packages(self, packages):
        """
		Ensure that certain packages are included

		@param packages: a list of package names
		"""
        self.__parse()  # ensure up-to-date document model

        if not self._document_is_master:
            self._log.debug("ensure_packages: document is not a master")

            # find the packages that haven't already been mentioned
            info_packages = [
                p for p in packages if not p in self._ensured_packages
            ]

            if len(info_packages) > 0:
                # generate markup
                li_tags = "\n".join(
                    [" • <tt>%s</tt>" % p for p in info_packages])

                from ..util import open_info
                open_info(
                    "LaTeX Package Required",
                    "Please make sure that the following packages are included in the master document per <tt>\\usepackage</tt>: \n\n%s"
                    % li_tags)

                # extend the already mentioned packages
                self._ensured_packages.extend(info_packages)

            return

        # find missing packages
        present_package_names = [p.value for p in self._outline.packages]
        package_names = [p for p in packages if not p in present_package_names]

        # insert the necessary \usepackage commands
        if len(package_names) > 0:
            source = "\n" + "\n".join(
                ["\\usepackage{%s}" % n for n in package_names])
            self.insert_at_position(source, self.POSITION_PACKAGES)

    def on_save(self):
        """
		The file has been saved

		Update models
		"""

        #		from multiprocessing import Process
        #
        #		p_parse = Process(target=self.__parse)
        #		p_parse.start()

        self.__parse()

    def __update_neighbors(self):
        """
		Find all files in the working directory that are relevant for LaTeX, e.g.
		other *.tex files or images.
		"""

        # TODO: this is only needed to feed the LaTeXCompletionHandler. So maybe it should
        # know the edited file and the Editor should call an update() method of the handler
        # when the file is saved.

        tex_files = self._file.find_neighbors(".tex")
        bib_files = self._file.find_neighbors(".bib")

        graphic_files = []
        for extension in [".ps", ".pdf", ".png", ".jpg", ".eps"]:
            graphic_files.extend(self._file.find_neighbors(extension))

        self.__latex_completion_handler.set_neighbors(tex_files, bib_files,
                                                      graphic_files)

    #@verbose
    def __parse(self):
        """
		Ensure that the document model is up-to-date
		"""
        if self.content_changed(self._change_reference):
            # content has changed so document model may be dirty
            self._change_reference = self.current_timestamp

            self._log.debug("Parsing document...")

            # reset highlight
            self.remove_markers("latex-error")
            self.remove_markers("latex-warning")

            # reset issues
            self._issue_view.clear()

            if BENCHMARK: t = time.clock()

            # parse document
            if self._document != None:
                self._document.destroy()
                del self._document
            self._document = self._parser.parse(self.content, self._file, self)

            if BENCHMARK:
                self._log.info("LaTeXParser.parse: %f" % (time.clock() - t))

            # create a copy that won't be expanded (e.g. for spell check)
            #self._local_document = deepcopy(self._document)

            self._log.debug("Parsed %s bytes of content" % len(self.content))

            # FIXME: the LaTeXChooseMasterAction enabled state has to be updated on tab change, too!

            if self._document.is_master:

                self._context.set_action_enabled("LaTeXChooseMasterAction",
                                                 False)
                self._document_is_master = True

                # expand child documents
                expander = LaTeXReferenceExpander()
                expander.expand(self._document, self._file, self, self.charset)

                # generate outline from the expanded model
                self._outline = self._outline_generator.generate(
                    self._document, self)

                # pass to view
                self._outline_view.set_outline(self._outline)

                # validate
                self._validator.validate(self._document, self._outline, self)
            else:
                self._log.debug("Document is not a master")

                self._context.set_action_enabled("LaTeXChooseMasterAction",
                                                 True)
                self._document_is_master = False

                # the outline used by the outline view has to be created only from the child model
                # otherwise we see the outline of the master and get wrong offsets
                self._outline = self._outline_generator.generate(
                    self._document, self)
                self._outline_view.set_outline(self._outline)

                # find master
                master_file = self.__master_file

                if master_file is None:
                    return

                # parse master
                master_content = open(master_file.path).read()
                self._document = self._parser.parse(master_content,
                                                    master_file, self)

                # expand its child documents
                expander = LaTeXReferenceExpander()
                expander.expand(self._document, master_file, self,
                                self.charset)

                # create another outline of the expanded master model to make elements
                # from the master available (labels, colors, BibTeX files etc.)
                self._outline = self._outline_generator.generate(
                    self._document, self)

                # validate
                self._validator.validate(self._document, self._outline, self)

            # pass outline to completion
            self.__latex_completion_handler.set_outline(self._outline)

            # pass neighbor files to completion
            self.__update_neighbors()

            self._log.debug("Parsing finished")

            #print self._document.xml

    @property
    @returns(File)
    def __master_file(self):
        """
		Find the LaTeX master of this child

		@return: base.File
		"""
        # TODO: cache result

        property_file = PropertyFile(self._file)
        try:
            #return File(property_file["MasterFilename"])

            path = property_file["MasterFilename"]
            # the property file may contain absolute and relative paths
            # because we switched in 0.2rc2
            if File.is_absolute(path):
                self._log.debug("Path is absolute")
                return File(path)
            else:
                self._log.debug("Path is relative")
                return File.create_from_relative_path(path, self._file.dirname)
        except KeyError:  # master filename not found
            # ask user
            master_filename = ChooseMasterDialog().run(self._file.dirname)
            if master_filename:
                # relativize the master filename
                master_filename = File(master_filename).relativize(
                    self._file.dirname, True)

                property_file["MasterFilename"] = master_filename
                property_file.save()
                return File(master_filename)
            else:
                # no master file chosen
                return None

    def issue(self, issue):
        # see IIssueHandler.issue

        local = (issue.file == self._file)

        self._issue_view.append_issue(issue, local)

        if issue.file == self._file:
            if issue.severity == Issue.SEVERITY_ERROR:
                self.create_marker("latex-error", issue.start, issue.end)
            elif issue.severity == Issue.SEVERITY_WARNING:
                self.create_marker("latex-warning", issue.start, issue.end)

    #
    # spell checking begin
    #
    # TODO: put this in a SpellCheckDelegate or so
    #

    def spell_check(self):
        """
		Run a spell check on the file

		@raise ImportError: if pyenchant is not installed
		"""
        self.remove_markers("latex-spell")
        self.__word_markers = {}

        #
        # FIXME: it makes no sense to pass _document here because it contains
        # the expanded model of the document. We must keep the the not expanded
        # one, too.
        #
        try:
            self.__spell_checker.run(self._document, self.edited_file, self)
        except ImportError:
            open_error(
                "Enchant is missing",
                "The enchant library and its Python bindings (package is propably called pyenchant) are needed for spell checking but could not be found"
            )

    def on_misspelled_word(self, word, position):
        # see IMisspelledWordHandler.on_misspelled_word
        marker = self.create_marker("latex-spell", position,
                                    position + len(word))
        self.__word_markers[marker.id] = word

    def on_marker_activated(self, marker, event):
        """
		A marker has been activated
		"""
        #self._log.debug("activate_marker(%s, %s)" % (marker, event))

        if marker.type == "latex-spell":
            word = self.__word_markers[marker.id]
            suggestions = self.__spell_checker.find_suggestions(word)

            self._log.debug(str(suggestions))

            # build and show the context menu
            menu = self.__get_suggestions_menu(word, suggestions, marker)
            menu.popup(None, None, None, event.button, event.time)

            # swallow the signal so that the original context menu
            # isn't shown
            return True

    def __get_suggestions_menu(self, word, suggestions, marker):
        """
		Return the context menu for spell check suggestions

		@param word: the misspelled word
		@param suggestions: a list of suggested words
		@param marker: the activated Marker
		"""
        suggestions_menu = gtk.Menu()

        suggestions_menu.add(gtk.SeparatorMenuItem())

        item_add = gtk.ImageMenuItem(gtk.STOCK_ADD)
        item_add.connect("activate", self.__on_add_word_activated, marker,
                         word)
        suggestions_menu.add(item_add)

        suggestions_menu.add(gtk.SeparatorMenuItem())

        item_abort = gtk.ImageMenuItem(gtk.STOCK_CANCEL)
        item_abort.connect("activate", self.__on_abort_spell_check_activated)
        suggestions_menu.add(item_abort)

        suggestions_menu.show_all()

        # add suggestions
        suggestions.reverse()  # we insert in reverse order, so reverse before

        for suggestion in suggestions:
            if suggestion.user_defined:
                item = gtk.ImageMenuItem(suggestion.word)
                item.set_image(
                    gtk.image_new_from_stock(gtk.STOCK_FLOPPY,
                                             gtk.ICON_SIZE_MENU))
            else:
                item = gtk.MenuItem(suggestion.word)

            item.connect("activate", self.__on_suggestion_activated,
                         suggestion, marker)
            suggestions_menu.insert(item, 0)
            item.show()

        return suggestions_menu

    def __on_suggestion_activated(self, menu_item, suggestion, marker):
        """
		A suggestion from the context menu has been activated

		@param menu_item: the activated MenuItem
		@param suggestion: the word
		"""
        self.replace_marker_content(marker, suggestion.word)

    def __on_abort_spell_check_activated(self, menu_item):
        """
		"""
        self.remove_markers("latex-spell")

    def __on_add_word_activated(self, menu_item, marker, word):
        """
		Add a word to the dictionary

		@param marker: the marker for the word
		@param word: the checked word
		"""
        self.__spell_checker.add_word(word)
        self.remove_marker(marker)

    #
    # spell checking end
    #

    def on_cursor_moved(self, offset):
        """
		The cursor has moved
		"""
        if self._preferences.get_bool("ConnectOutlineToEditor", True):
            self._outline_view.select_path_by_offset(offset)

    @property
    def file(self):
        # overrides Editor.file

        # we may not call self._document.is_master because _document is always
        # replaced by the master model
        if self._document_is_master:
            return self._file
        else:
            return self.__master_file

    @property
    def edited_file(self):
        """
		Always returns the really edited file instead of the master

		This is called by the outline view to identify foreign nodes
		"""
        return self._file

    def destroy(self):
        # stop listening preferences
        self._preferences.remove_monitor(self)

        # unreference the window context
        del self._context

        # destroy the cached document
        self._document.destroy()
        del self._document

        Editor.destroy(self)

    def __del__(self):
        self._log.debug("Properly destroyed %s" % self)
Example #8
0
 def setUp(self):
     self.spellChecker = SpellChecker()
     self.spellChecker.load_words('spell.words')
class TestSpellChecker(unittest.TestCase):
    def setUp(self):
        self.spellChecker = SpellChecker()
        self.spellChecker.load_words('spell.words')

    def test_spell_checker(self):
        self.assertEqual(53751, len(self.spellChecker.words))
        self.assertTrue(self.spellChecker.check_word('zygotic'))
        self.assertEqual([{
            'line': 1,
            'pos': 9,
            'word': 'mistasdas'
        }], self.spellChecker.check_words('zygotic mistasdas elementary'))
        self.assertEqual(
            [], self.spellChecker.check_words('our first correct sentence'))
        self.assertEqual(
            0,
            len(self.spellChecker.check_words('Our first correct sentence.')))
        self.assertEqual([{
            'line': 1,
            'pos': 9,
            'word': 'mistasdas'
        }, {
            'line': 1,
            'pos': 19,
            'word': 'spelllleeeing'
        }],
                         self.spellChecker.check_words(
                             'zygotic mistasdas spelllleeeing elementary'))
        self.assertEqual(
            2,
            len(
                self.spellChecker.check_words(
                    'zygotic mistasdas spelllleeeing elementary')))
        self.assertEqual(0, len(self.spellChecker.check_document("karen.txt")))
        #self.assertEqual(0, len(self.spellChecker.check_document('spell.words')))
        self.assertEqual(
            26,
            len(
                self.spellChecker.check_dir(
                    "/Users/karenbyrne/Desktop/python_files/")))
        self.assertEqual(
            2,
            len(
                self.spellChecker.check_dir(
                    "/Users/karenbyrne/Desktop/python_files/")))
Example #10
0
 def setUp(self):
     self.checker = SpellChecker()
	def setUp(self):
		self.trie = Trie()
		self.checker = SpellChecker(self.trie)
class TestSpellcheckTrie(unittest.TestCase):
	def setUp(self):
		self.trie = Trie()
		self.checker = SpellChecker(self.trie)

	def tearDown(self):
		self.trie.reset()
		self.checker.reset()

	def test_exact_match(self):
		self.trie.add('bayern')

		self.assertEqual(self.checker.spellcheck('bayern'), 'bayern')

	def test_miss(self):
		self.trie.add('bayern')

		self.assertFalse(self.checker.spellcheck('byern'))

	def test_vowel(self):
		self.trie.add('bayern')

		self.assertEqual(self.checker.spellcheck('bayarn'), 'bayern')

	def test_vowel_miss(self):
		self.trie.add('bayern')

		self.assertFalse(self.checker.spellcheck('barn'))

	def test_vowel_last_letter(self):
		self.trie.add('ygapo')

		self.assertEqual(self.checker.spellcheck('ygapu'), 'ygapo')

	def test_repeating_chars(self):
		self.trie.add('job')

		self.assertEqual(self.checker.spellcheck('jjoobbb'), 'job')

	def test_repeating_chars_smaller_word(self):
		self.trie.add('cuppy')
		self.trie.add('cuphead')

		self.assertEqual(self.checker.spellcheck('ccoppphead'), 'cuphead')

	def test_spellcheck_backtrack(self):
		self.trie.add('pea')
		self.trie.add('peep')
		self.trie.add('peeper')
		self.trie.add('peephole')
		self.trie.add('peon')
		self.trie.add('peonage')
		self.trie.add('people')

		self.assertEqual(self.checker.spellcheck('peepple'), 'people')

	def test_challenge_words(self):
		self.trie.add('conspiracy')
		self.trie.add('sheep')
		self.trie.add('people')
		self.trie.add('wake')

		self.assertEqual(self.checker.spellcheck('CUNsperrICY'), 'conspiracy')
		self.assertEqual(self.checker.spellcheck('sheeeeep'), 'sheep')
		self.assertEqual(self.checker.spellcheck('peepple'), 'people')
		self.assertEqual(self.checker.spellcheck('weke'), 'wake')
		self.assertEqual(self.checker.spellcheck('sheeple'), 'sheep')

	def test_vowels_and_repeating_letters(self):
		self.trie.add('sdrucciola')

		self.assertEqual(self.checker.spellcheck('sdrucciila'), 'sdrucciola')
Example #13
0
class LaTeXEditor(Editor, IIssueHandler, IMisspelledWordHandler, IPreferencesMonitor):

	_log = getLogger("LaTeXEditor")

	#extensions = [".tex"]
	extensions = Preferences().get("LatexExtensions", ".tex").split(" ")

	dnd_extensions = [".png", ".pdf", ".bib", ".tex"]

	@property
	def completion_handlers(self):
		self.__latex_completion_handler = LaTeXCompletionHandler()
		self.__snippet_completion_handler = SnippetCompletionHandler()

		return [ self.__latex_completion_handler, self.__snippet_completion_handler ]

	def init(self, file, context):
		"""
		@param file: base.File
		@param context: base.WindowContext
		"""
		self._log.debug("init(%s)" % file)

		self._file = file
		self._context = context

		self._preferences = Preferences()
		self._preferences.register_monitor(self)	# listen to 'Show...InOutline' settings

		self.register_marker_type("latex-spell", self._preferences.get("SpellingBackgroundColor"), anonymous=False)
		self.register_marker_type("latex-error", self._preferences.get("ErrorBackgroundColor"))
		self.register_marker_type("latex-warning", self._preferences.get("WarningBackgroundColor"))

		self._issue_view = context.find_view(self, "IssueView")
		self._outline_view = context.find_view(self, "LaTeXOutlineView")

		self._parser = LaTeXParser()
		self._outline_generator = LaTeXOutlineGenerator()
		self._validator = LaTeXValidator()
		self._document = None

		self._document_dirty = True

		# if the document is no master we display an info message on the packages to
		# include - _ensured_packages holds the already mentioned packages to not
		# annoy the user
		self._ensured_packages = []

		# spell checking
		self.__spell_checker = SpellChecker()

		#
		# initially parse
		#
		self._change_reference = self.initial_timestamp

		self.__parse()
		self.__update_neighbors()

	def _on_value_changed(self, key, new_value):
		# see preferences.IPreferencesMonitor._on_value_changed

		if key in ["ShowLabelsInOutline", "ShowTablesInOutline", "ShowGraphicsInOutline"]:
			# regenerate outline model
			if self._document_is_master:
				self._outline = self._outline_generator.generate(self._document, self)
				self._outline_view.set_outline(self._outline)
			else:
				# FIXME: self._document contains the full model of child and master
				# so we may not use it for regenerating the outline here
				self.__parse()
		elif key == "ShowLatexToolbar":
			show_toolbar = self._preferences.get_bool("ShowLatexToolbar", True)
			if show_toolbar:
				self._window_context._window_decorator._toolbar.show()
			else:
				self._window_context._window_decorator._toolbar.hide()

	def _ctrl_left_clicked(self, it):
		"""
		For synchronization by synctex
		"""
		# Editor._ctrl_left_clicked

		tab = self.tab_decorator.tab
		line = it.get_line() + 1
		column = it.get_line_offset() + 1
		source_file = "%s/%s" % (self._file.dirname, self._file.basename)
		# We use self.file and not self._file here, to get the
		# master document, because the output file will have the
		# name of the master document
		try:
			output_file = "%s.pdf" % self.file.shortname
		except:
			# Is this due to a bug ? Or is there a method I
			# don't know to check wether a file has/is a
			# master file or doesn't/couldn't have one ?
			self.__log.debug("Error while trying to get the output file path. No master document ?")
			return

		from livepreview import LaTeXPreviews

		if self._window_context.latex_previews == None:
			self._window_context.latex_previews = LaTeXPreviews(self._window_context)

		latex_previews = self._window_context.latex_previews
		latex_previews.sync_view(tab, source_file, line, column, output_file)

	def drag_drop_received(self, files):
		# see base.Editor.drag_drop_received

		# TODO: we need to insert the source at the drop location - so pass it here

		self._log.debug("drag_drop: %s" % files)

#		if len(files) == 1:
#			file = files[0]
#			self._log.debug("Got one file: %s, extension: %s" % (file.path, file.extension))
#			if file.extension == ".png":
#				self._log.debug("PNG image - including...")
#				source = "\\includegraphics{%s}" % file.path
#				self.insert(source)

	def insert(self, source):
		# see base.Editor.insert

		if type(source) is LaTeXSource:
			if source.packages and len(source.packages) > 0:
				self.ensure_packages(source.packages)

			Editor.insert(self, source.source)
		else:
			Editor.insert(self, source)

	POSITION_PACKAGES, POSITION_BIBLIOGRAPHY = 1, 2

	def insert_at_position(self, source, position):
		"""
		Insert source at a certain position in the LaTeX document:

		 * POSITION_PACKAGES: after the last \usepackage statement
		 * POSITION_BIBLIOGRAPHY: before \end{document}

		@param source: a LaTeXSource object
		@param position: POSITION_PACKAGES | POSITION_BIBLIOGRAPHY
		"""

		if position == self.POSITION_BIBLIOGRAPHY:
			offset = self._document.end_of_document
			Editor.insert_at_offset(self, offset, source, True)
		elif position == self.POSITION_PACKAGES:
			offset = self._document.end_of_packages
			Editor.insert_at_offset(self, offset, source, False)
		else:
			raise NotImplementedError

	def ensure_packages(self, packages):
		"""
		Ensure that certain packages are included

		@param packages: a list of package names
		"""
		self.__parse()	# ensure up-to-date document model

		if not self._document_is_master:
			self._log.debug("ensure_packages: document is not a master")

			# find the packages that haven't already been mentioned
			info_packages = [p for p in packages if not p in self._ensured_packages]

			if len(info_packages) > 0:
				# generate markup
				li_tags = "\n".join([" • <tt>%s</tt>" % p for p in info_packages])

				from ..util import open_info
				open_info("LaTeX Package Required",
						"Please make sure that the following packages are included in the master document per <tt>\\usepackage</tt>: \n\n%s" % li_tags)

				# extend the already mentioned packages
				self._ensured_packages.extend(info_packages)

			return

		# find missing packages
		present_package_names = [p.value for p in self._outline.packages]
		package_names = [p for p in packages if not p in present_package_names]

		# insert the necessary \usepackage commands
		if len(package_names) > 0:
			source = "\n" + "\n".join(["\\usepackage{%s}" % n for n in package_names])
			self.insert_at_position(source, self.POSITION_PACKAGES)

	def on_save(self):
		"""
		The file has been saved

		Update models
		"""

#		from multiprocessing import Process
#
#		p_parse = Process(target=self.__parse)
#		p_parse.start()

		self.__parse()

	def __update_neighbors(self):
		"""
		Find all files in the working directory that are relevant for LaTeX, e.g.
		other *.tex files or images.
		"""

		# TODO: this is only needed to feed the LaTeXCompletionHandler. So maybe it should
		# know the edited file and the Editor should call an update() method of the handler
		# when the file is saved.

		tex_files = self._file.find_neighbors(".tex")
		bib_files = self._file.find_neighbors(".bib")

		graphic_files = []
		for extension in [".ps", ".pdf", ".png", ".jpg", ".eps"]:
			graphic_files.extend(self._file.find_neighbors(extension))

		self.__latex_completion_handler.set_neighbors(tex_files, bib_files, graphic_files)

	#@verbose
	def __parse(self):
		"""
		Ensure that the document model is up-to-date
		"""
		if self.content_changed(self._change_reference):
			# content has changed so document model may be dirty
			self._change_reference = self.current_timestamp

			self._log.debug("Parsing document...")

			# reset highlight
			self.remove_markers("latex-error")
			self.remove_markers("latex-warning")

			# reset issues
			self._issue_view.clear()

			if BENCHMARK: t = time.clock()

			# parse document
			if self._document != None:
				self._document.destroy()
				del self._document
			self._document = self._parser.parse(self.content, self._file, self)

			if BENCHMARK: self._log.info("LaTeXParser.parse: %f" % (time.clock() - t))

			# create a copy that won't be expanded (e.g. for spell check)
			#self._local_document = deepcopy(self._document)

			self._log.debug("Parsed %s bytes of content" % len(self.content))

			# FIXME: the LaTeXChooseMasterAction enabled state has to be updated on tab change, too!

			if self._document.is_master:

				self._context.set_action_enabled("LaTeXChooseMasterAction", False)
				self._document_is_master = True

				# expand child documents
				expander = LaTeXReferenceExpander()
				expander.expand(self._document, self._file, self, self.charset)

				# generate outline from the expanded model
				self._outline = self._outline_generator.generate(self._document, self)

				# pass to view
				self._outline_view.set_outline(self._outline)

				# validate
				self._validator.validate(self._document, self._outline, self)
			else:
				self._log.debug("Document is not a master")

				self._context.set_action_enabled("LaTeXChooseMasterAction", True)
				self._document_is_master = False

				# the outline used by the outline view has to be created only from the child model
				# otherwise we see the outline of the master and get wrong offsets
				self._outline = self._outline_generator.generate(self._document, self)
				self._outline_view.set_outline(self._outline)

				# find master
				master_file = self.__master_file

				if master_file is None:
					return

				# parse master
				master_content = open(master_file.path).read()
				self._document = self._parser.parse(master_content, master_file, self)

				# expand its child documents
				expander = LaTeXReferenceExpander()
				expander.expand(self._document, master_file, self, self.charset)

				# create another outline of the expanded master model to make elements
				# from the master available (labels, colors, BibTeX files etc.)
				self._outline = self._outline_generator.generate(self._document, self)

				# validate
				self._validator.validate(self._document, self._outline, self)

			# pass outline to completion
			self.__latex_completion_handler.set_outline(self._outline)

			# pass neighbor files to completion
			self.__update_neighbors()

			self._log.debug("Parsing finished")

			#print self._document.xml

	@property
	@returns(File)
	def __master_file(self):
		"""
		Find the LaTeX master of this child

		@return: base.File
		"""
		# TODO: cache result

		property_file = PropertyFile(self._file)
		try:
			#return File(property_file["MasterFilename"])

			path = property_file["MasterFilename"]
			# the property file may contain absolute and relative paths
			# because we switched in 0.2rc2
			if File.is_absolute(path):
				self._log.debug("Path is absolute")
				return File(path)
			else:
				self._log.debug("Path is relative")
				return File.create_from_relative_path(path, self._file.dirname)
		except KeyError:		# master filename not found
			# ask user
			master_filename = ChooseMasterDialog().run(self._file.dirname)
			if master_filename:
				# relativize the master filename
				master_filename = File(master_filename).relativize(self._file.dirname, True)

				property_file["MasterFilename"] = master_filename
				property_file.save()
				return File(master_filename)
			else:
				# no master file chosen
				return None

	def issue(self, issue):
		# see IIssueHandler.issue

		local = (issue.file == self._file)

		self._issue_view.append_issue(issue, local)

		if issue.file == self._file:
			if issue.severity == Issue.SEVERITY_ERROR:
				self.create_marker("latex-error", issue.start, issue.end)
			elif issue.severity == Issue.SEVERITY_WARNING:
				self.create_marker("latex-warning", issue.start, issue.end)

	#
	# spell checking begin
	#
	# TODO: put this in a SpellCheckDelegate or so
	#

	def spell_check(self):
		"""
		Run a spell check on the file

		@raise ImportError: if pyenchant is not installed
		"""
		self.remove_markers("latex-spell")
		self.__word_markers = {}

		#
		# FIXME: it makes no sense to pass _document here because it contains
		# the expanded model of the document. We must keep the the not expanded
		# one, too.
		#
		try:
			self.__spell_checker.run(self._document, self.edited_file, self)
		except ImportError:
			open_error("Enchant is missing", "The enchant library and its Python bindings (package is propably called pyenchant) are needed for spell checking but could not be found")

	def on_misspelled_word(self, word, position):
		# see IMisspelledWordHandler.on_misspelled_word
		marker = self.create_marker("latex-spell", position, position + len(word))
		self.__word_markers[marker.id] = word

	def on_marker_activated(self, marker, event):
		"""
		A marker has been activated
		"""
		#self._log.debug("activate_marker(%s, %s)" % (marker, event))

		if marker.type == "latex-spell":
			word = self.__word_markers[marker.id]
			suggestions = self.__spell_checker.find_suggestions(word)

			self._log.debug(str(suggestions))

			# build and show the context menu
			menu = self.__get_suggestions_menu(word, suggestions, marker)
			menu.popup(None, None, None, event.button, event.time)

			# swallow the signal so that the original context menu
			# isn't shown
			return True

	def __get_suggestions_menu(self, word, suggestions, marker):
		"""
		Return the context menu for spell check suggestions

		@param word: the misspelled word
		@param suggestions: a list of suggested words
		@param marker: the activated Marker
		"""
		suggestions_menu = gtk.Menu()

		suggestions_menu.add(gtk.SeparatorMenuItem())

		item_add = gtk.ImageMenuItem(gtk.STOCK_ADD)
		item_add.connect("activate", self.__on_add_word_activated, marker, word)
		suggestions_menu.add(item_add)

		suggestions_menu.add(gtk.SeparatorMenuItem())

		item_abort = gtk.ImageMenuItem(gtk.STOCK_CANCEL)
		item_abort.connect("activate", self.__on_abort_spell_check_activated)
		suggestions_menu.add(item_abort)

		suggestions_menu.show_all()

		# add suggestions
		suggestions.reverse()	# we insert in reverse order, so reverse before

		for suggestion in suggestions:
			if suggestion.user_defined:
				item = gtk.ImageMenuItem(suggestion.word)
				item.set_image(gtk.image_new_from_stock(gtk.STOCK_FLOPPY, gtk.ICON_SIZE_MENU))
			else:
				item = gtk.MenuItem(suggestion.word)

			item.connect("activate", self.__on_suggestion_activated, suggestion, marker)
			suggestions_menu.insert(item, 0)
			item.show()

		return suggestions_menu

	def __on_suggestion_activated(self, menu_item, suggestion, marker):
		"""
		A suggestion from the context menu has been activated

		@param menu_item: the activated MenuItem
		@param suggestion: the word
		"""
		self.replace_marker_content(marker, suggestion.word)

	def __on_abort_spell_check_activated(self, menu_item):
		"""
		"""
		self.remove_markers("latex-spell")

	def __on_add_word_activated(self, menu_item, marker, word):
		"""
		Add a word to the dictionary

		@param marker: the marker for the word
		@param word: the checked word
		"""
		self.__spell_checker.add_word(word)
		self.remove_marker(marker)

	#
	# spell checking end
	#

	def on_cursor_moved(self, offset):
		"""
		The cursor has moved
		"""
		if self._preferences.get_bool("ConnectOutlineToEditor", True):
			self._outline_view.select_path_by_offset(offset)

	@property
	def file(self):
		# overrides Editor.file

		# we may not call self._document.is_master because _document is always
		# replaced by the master model
		if self._document_is_master:
			return self._file
		else:
			return self.__master_file

	@property
	def edited_file(self):
		"""
		Always returns the really edited file instead of the master

		This is called by the outline view to identify foreign nodes
		"""
		return self._file

	def destroy(self):
		# stop listening preferences
		self._preferences.remove_monitor(self)

		# unreference the window context
		del self._context

		# destroy the cached document
		self._document.destroy()
		del self._document

		Editor.destroy(self)

	def __del__(self):
		self._log.debug("Properly destroyed %s" % self)
Example #14
0
class TestSpellChecker(unittest.TestCase):
    def setUp(self):
        self.spellChecker = SpellChecker()
        self.spellChecker.load_words('spell.words')

    def test_spell_checker(self):
        self.assertTrue(self.spellChecker.check_word(
            'zygotic'))  # Checks if (single) word is present in list
        failed_words = self.spellChecker.check_words(
            'zygotic mistasdas tennyy elementary')  # two incorrect words
        self.assertEquals(
            2, len(failed_words)
        )  # Checks that failed_words has two entries, i.e. mistasdas and tennyy
        print('Contents of failed words array ',
              failed_words)  # print failed_words array to see what's in it.
        self.assertEquals(
            'mistasdas', failed_words[0]['word']
        )  # Checks that the zero'th failed word in the array is mistasda
        self.assertEquals(
            'tennyy', failed_words[1]['word']
        )  # checks that the 2nd failed word (in Position 1) is tennyy
        self.assertEquals(
            {
                'line': 1,
                'word': 'mistasdas',
                'pos': 9
            }, failed_words[0]
        )  # checks the line number, word (mistasdas) and caret position are correct
        self.assertEquals(
            {
                'line': 1,
                'word': 'tennyy',
                'pos': 19
            }, failed_words[1]
        )  # checks the line number, word (tenny) and caret position are correct
        self.assertEquals(
            1, failed_words[0]['line']
        )  # Checks that the zero'th failed (mistasdas) word occurs on line 1
        self.assertEquals(
            19, failed_words[1]['pos']
        )  # checks that the 2nd failed word occurs at caret position 19
        self.assertEquals(
            0, len(self.spellChecker.check_words('our first correct sentence'))
        )  # checks that lebgth of array is 0, i.e. includes no failed words

        # handle case sensitivity
        self.assertEquals(
            0,
            len(self.spellChecker.check_words('Our first correct sentence')))
        # handle full stop
        self.assertEquals(
            0,
            len(self.spellChecker.check_words('Our first correct sentence.')))

        failed_words = self.spellChecker.check_words(
            'zygotic mistasdas spelllleeeing elementary')
        print('Contents of failed words array ',
              failed_words)  # print failed_words array to see what's in it.
        self.assertEquals(
            2, len(failed_words)
        )  # Checks that array length is 2, i.e. has two failed words
        self.assertEquals('mistasdas', failed_words[0]['word'])
        self.assertEquals(
            1, failed_words[0]['line']
        )  # Checks that the zero'th failed (mistasdas) word occurs on line 1
        self.assertEquals(
            9, failed_words[0]['pos']
        )  # checks that the zero'th failed word occurs at caret position 9
        self.assertEquals(
            'spelllleeeing', failed_words[1]
            ['word'])  # checks the 2nd word in the failed words array
        self.assertEquals(
            1, failed_words[1]['line']
        )  # Checks that the 2nd failed (spelllleeeing) word occurs on line 1
        self.assertEquals(
            19, failed_words[1]['pos']
        )  # checks that the 2nd failed word occurs at caret position 19

        self.assertEquals(
            {
                'line': 1,
                'word': 'mistasdas',
                'pos': 9
            }, failed_words[0]
        )  # Checks the contents of zero'th position in failed words array
        self.assertEquals(
            {
                'line': 1,
                'word': 'spelllleeeing',
                'pos': 19
            }, failed_words[1]
        )  # Checks the contents of 2ND position in failed words array

        # more bugs because the spell checker doesn’t spell check itself correctly – 0 entries when .lower is used – dictionary words need to be lower
        self.assertEqual(0,
                         len(self.spellChecker.check_document('spell.words')))
class TestSpellChecker(unittest.TestCase):

    def setUp(self):
        self.spellChecker = SpellChecker()
        self.spellChecker.load_words('spell.words')

    def test_spell_checker(self):
        self.assertTrue(len(self.spellChecker.words) > 50000)
        self.assertTrue(self.spellChecker.check_word('zygotic'))
        self.assertFalse(self.spellChecker.check_word('zogotic'))
        self.assertEqual([{'line': 1, 'pos': 9, 'word': 'mistasdas'}],
                self.spellChecker.check_words('zygotic mistasdas elementary'))
        self.assertEqual([],
                self.spellChecker.check_words('our first correct sentence'))
        self.assertEqual(0,
                len(self.spellChecker.check_words('Our first correct sentence.')))
        self.assertEqual([{'line': 1, 'pos': 9, 'word': 'mistasdas'}, {'line': 1, 'pos': 19, 'word': 'spelllleeeing'}],
                self.spellChecker.check_words('zygotic mistasdas spelllleeeing elementary'))
        self.assertEqual(2,
                len(self.spellChecker.check_words('zygotic mistasdas spelllleeeing elementary')))
        #self.assertEqual(0, len(self.spellChecker.check_document('spell.words')))
        self.assertEqual([{'line': 2, 'pos': 8, 'word': 'larn'}, 
                          {'line': 2, 'pos': 13, 'word': 'huw'}, 
                          {'line': 2, 'pos': 26, 'word': 'wurdz'}],
                self.spellChecker.check_document('darren.txt'))
        self.assertEqual({'darren.txt': [{'line': 2, 'pos': 8, 'word': 'larn'}, 
                          {'line': 2, 'pos': 13, 'word': 'huw'}, 
                          {'line': 2, 'pos': 26, 'word': 'wurdz'}]},
                self.spellChecker.check_directory('*.txt'))
 def setUp(self):
     self.spellChecker = SpellChecker()
     # This is the path name for our dictionary file
     file_name = '/Users/barrysheppard/Github/DBSDataAnalysis/'
     file_name = file_name + 'BigData/04Lecture/spell.words'
     self.spellChecker.load_words(file_name)