Commits

Anonymous committed eb71c0f

Indenting and deindenting for NormalIndenter

Comments (0)

Files changed (7)

   * Only highlighting the changed region
   * Extend highlighting region while highlighting if necessay
   * Highlighting after cut, paste, undo and redo
+  * Use Modified event for updating highlighting only when necessary
 
 
 * Enhancing menu @ 1
 * Auto-complete variable names @ 3
 
 
+* Show searching status in the status bar @ 1
+
+
+* Adding TextIterator or LineOriented to the Editor class @ 1
+
+
 * Enhancing editor @ 1
   * Clearing selection if something happens
   * Unifying builtin and emacs-style selections; if selection
     is active do the builtin cut and paste
   * Edit menu: cut, paste, undo, redo, revert
+  * Showing modified file status
 
 
 * Making ASTs @ 4
 > Public release 0.1 : May 6, 2006
 
 
-* Show searching status in the status bar @ 1
-
-
-* Adding TextIterator for Editor class @ 1
-
-
-* Use Modified event for updating highlighting only when necessary @ 1
-
-
-* Enhancing editor and indentation @ 1
-  * Showing modified file status
-
-
 --- Remaining Stories ---
 ? Using SF SVN; Making a script for committing to SF
 ? Separate domain and presentation everywhere
 * Make tests less dependant
+? Changing used graphical interface
 * Make a new Project; Seperate opening and creating projects
 * Add removing resources to Core
 ? Project resource consistency; What if it is deleted after being created.

docs/workingon.txt

-* Showing modified file status
+* Extract NormalIndenter class
 
-- not using editor._rope_title
 
-
+- Back space does not work for normal files when deindenting
 ? SF repository; Subversion or CVS? Synchronizing local SVN with SF?
 ? Adding selection list class
 ? Separation of acceptance and unit tests
         self.editors.remove(editor)
         self.editors.insert(0, editor)
 
-    def get_resource_editor(self, file):
+    def get_resource_editor(self, file_):
         for editor in self.editors:
-            if editor.get_file() == file:
+            if editor.get_file() == file_:
                 self.buttons[editor].invoke()
                 return editor
-        editor = FileEditor(file, GraphicalEditor(self.editor_frame))
+        editor = FileEditor(file_, GraphicalEditor(self.editor_frame))
         self.editors.append(editor)
-        title = Radiobutton(self.editor_list, text=file.get_name(),
+        title = Radiobutton(self.editor_list, text=file_.get_name(),
                             variable=self.active_file_path,
-                            value=file.get_path(), indicatoron=0, bd=2,
+                            value=file_.get_path(), indicatoron=0, bd=2,
                             command=lambda: self.activate_editor(editor),
                             selectcolor='#99A', relief=GROOVE)
         self.buttons[editor] = title
         if self.editors:
             self.buttons[self.editors[0]].invoke()
 
-        
+
 class Core(object):
     '''The main class for the IDE'''
     def __init__(self):
         self.root.protocol('WM_DELETE_WINDOW', self.exit)
         self.runningThread = Thread(target=self.run)
         self.project = None
-    
+
     def _create_menu(self):
         fileMenu = Menu(self.menubar, tearoff=0)
         self.menubar.add_cascade(label='File', menu=fileMenu, underline=1)
             else:
                 result = file_finder.find_files_starting_with(name.get())
             found.delete(0, END)
-            for file in result:
-                found.insert(END, file.get_path())
+            for file_ in result:
+                found.insert(END, file_.get_path())
             if result:
                 found.selection_set(0)
         def open_selected():
         return 'break'
 
     def _show_open_dialog(self, openCommand, title='Open Dialog'):
-        input = tkSimpleDialog.askstring(title, 'Address :', parent=self.root)
-        if input:
+        input_ = tkSimpleDialog.askstring(title, 'Address :', parent=self.root)
+        if input_:
             try:
-                openCommand(input)
+                openCommand(input_)
             except Exception, e:
                 tkMessageBox.showerror(parent=self.root, title='Failed',
                                        message=str(e))
     def open_file(self, fileName):
         if self.project is None:
             raise RopeException('No project is open')
-        file = self.project.get_resource(fileName)
-        return self.editor_manager.get_resource_editor(file)
+        file_ = self.project.get_resource(fileName)
+        return self.editor_manager.get_resource_editor(file_)
 
     def activate_editor(self, editor):
         self.editor_manager.activate_editor(editor)
 
 
 class TextEditor(object):
-    '''A class representing a text editor'''
+    '''The base class for all text editor'''
     def get_text(self):
         pass
     
 
     def get_start(self):
         pass
-    
+
     def get_insert(self):
         pass
 
     def get_end(self):
         pass
-    
+
     def get_relative(self, base_index, offset):
         pass
-    
+
     def get_index(self, offset):
         pass
-    
+
     def set_insert(self, index):
         pass
 
     def get(self, start=None, end=None):
         pass
-    
+
     def insert(self, index, text):
         pass
 
         self._bind_keys()
         self._initialize_highlighting()
         self.highlighting = rope.highlight.NoHighlighting()
-        self.indenter = rope.indenter.NullIndenter()
+        self.indenter = rope.indenter.NormalIndenter(self)
 
     def _initialize_highlighting(self):
-        def colorize(event):
+        def colorize(event=None):
             start = 'insert linestart-2c'
             end = 'insert lineend'
             start_tags = self.text.tag_names(start)
             if start_tags:
                 tag = start_tags[0]
-                range = self.text.tag_prevrange(tag, start + '+1c')
-                if self.text.compare(range[0], '<', start):
-                    start = range[0]
-                if self.text.compare(range[1], '>', end):
-                    end = range[1]
+                range_ = self.text.tag_prevrange(tag, start + '+1c')
+                if self.text.compare(range_[0], '<', start):
+                    start = range_[0]
+                if self.text.compare(range_[1], '>', end):
+                    end = range_[1]
             end_tags = self.text.tag_names(end)
             if end_tags:
                 tag = end_tags[0]
-                range = self.text.tag_prevrange(tag, end + '+1c')
-                if self.text.compare(range[1], '>', end):
-                    end = range[1]
+                range_ = self.text.tag_prevrange(tag, end + '+1c')
+                if self.text.compare(range_[1], '>', end):
+                    end = range_[1]
             self._highlight_range(start, end)
+        def modified(event):
+            if not self.modified_flag:
+                print 'start modified', event
+                self.modified_flag = True
+                colorize()
+                self.text.edit_modified(False)
+                self.modified_flag = False
+                print 'end modified', event
+        self.modified_flag = False
         self.text.bind('<Any-KeyRelease>', colorize, '+')
+#        self.text.bind('<<Modified>>', modified)
+        self.text.edit_modified(False)
 
     def _highlight_range(self, startIndex, endIndex):
         for style in self.highlighting.getStyles().keys():
 
     def get_text(self):
         return self.text.get('1.0', 'end-1c')
-    
+
     def set_text(self, text):
         self.text.delete('1.0', END)
         self.text.insert('1.0', text)
         self.text.mark_set(INSERT, '1.0')
         self._highlight_range('0.0', 'end')
         self.text.edit_reset()
+        self.text.edit_modified(False)
 
     def get_start(self):
         return GraphicalTextIndex(self, '1.0')
 
     def _get_line_from_index(self, index):
         return int(self.text.index(index).split('.')[0])
-        
+
     def _get_column_from_index(self, index):
         return int(self.text.index(index).split('.')[1])
-    
+
     def set_insert(self, textIndex):
         self.text.mark_set(INSERT, textIndex._getIndex())
 
 
 class TextIndenter(object):
     '''A class for formatting texts'''
-    def indent_line(self, index):
-        '''Correct the indentation of the line containing the given index'''
-    def deindent(self, index):
-        '''Deindent the line containing the given index'''
 
-class NullIndenter(TextIndenter):
-    pass
-
-class PythonCodeIndenter(TextIndenter):
     def __init__(self, editor):
         self.editor = editor
 
-    def _get_line_start(self, index):
-        while index != self.editor.get_start():
-            index = self.editor.get_relative(index, -1)
-            if self.editor.get(index) == '\n':
-                return self.editor.get_relative(index, +1)
-        return self.editor.get_start()
+    def indent_line(self, index):
+        '''Correct the indentation of the line containing the given index'''
+
+    def deindent(self, index):
+        '''Deindent the line containing the given index'''
 
     def _get_prev_line_start(self, line_start):
         return self._get_line_start(self.editor.get_relative(line_start, -1))
             index = self.editor.get_relative(index, +1)
         return self.editor.get_end()
 
+    def _get_line_contents(self, line_start):
+        end = self._get_line_end(line_start)
+        return self.editor.get(line_start, end)
+
     def _set_line_indents(self, line_start, indents):
         old_indents = self._count_line_indents(line_start)
         indent_diffs = indents - old_indents
         if indent_diffs > 0:
             self.editor.insert(line_start, ' ' * indent_diffs)
         else:
-            self.editor.delete(line_start, self.editor.get_relative(line_start, -indent_diffs))
+            self.editor.delete(line_start, 
+                               self.editor.get_relative(line_start, -indent_diffs))
 
-    def _get_line_contents(self, line_start):
-        end = self._get_line_end(line_start)
-        return self.editor.get(line_start, end)
-
-    def _get_last_non_empty_line(self, line_start):
-        current_line = self._get_prev_line_start(line_start)
-        while current_line != self.editor.get_start() and \
-                  self._get_line_contents(current_line).strip() == '':
-            current_line = self._get_prev_line_start(current_line)
-        return current_line
+    def _get_line_start(self, index):
+        while index != self.editor.get_start():
+            index = self.editor.get_relative(index, -1)
+            if self.editor.get(index) == '\n':
+                return self.editor.get_relative(index, +1)
+        return self.editor.get_start()
 
     def _count_line_indents(self, index):
         contents = self._get_line_contents(index)
                 break
         return result
 
+
+class NormalIndenter(TextIndenter):
+    def __init__(self, editor):
+        super(NormalIndenter, self).__init__(editor)
+
+    def indent_line(self, index):
+        start = self._get_line_start(index)
+        current_indents = self._count_line_indents(start)
+        new_indents = current_indents + 4
+        self._set_line_indents(start, new_indents)
+        
+    def deindent(self, index):
+        start = self._get_line_start(index)
+        current_indents = self._count_line_indents(start)
+        new_indents = max(0, current_indents - 4)
+        self._set_line_indents(start, new_indents)
+
+
+class PythonCodeIndenter(TextIndenter):
+    def __init__(self, editor):
+        super(PythonCodeIndenter, self).__init__(editor)
+
+    def _get_last_non_empty_line(self, line_start):
+        current_line = self._get_prev_line_start(line_start)
+        while current_line != self.editor.get_start() and \
+                  self._get_line_contents(current_line).strip() == '':
+            current_line = self._get_prev_line_start(current_line)
+        return current_line
+
     def _get_starting_backslash_line(self, line_start):
         current = line_start
         while current != self.editor.get_start():

ropetest/indentertest.py

 import unittest
 
 from ropetest.mockeditortest import GraphicalEditorFactory, MockEditorFactory
-from rope.indenter import PythonCodeIndenter
+from rope.indenter import PythonCodeIndenter, NormalIndenter
 
 class PythonCodeIndenterTest(unittest.TestCase):
     __factory = MockEditorFactory()
         self.indenter.deindent(self.editor.get_relative(self.editor.get_end(), -2))
         self.assertEquals('def f()\n    print "hello"\ndef g():\n', self.editor.get_text())
 
+    def test_normal_indenter_indenting(self):
+        self.editor.set_text('a sample text')
+        indenter = NormalIndenter(self.editor)
+        indenter.indent_line(self.editor.get_start())
+        self.assertEquals('    a sample text', self.editor.get_text())
+
+    def test_normal_indenter_deindenting(self):
+        self.editor.set_text('a sample \n        text')
+        indenter = NormalIndenter(self.editor)
+        indenter.deindent(self.editor.get_end())
+        self.assertEquals('a sample \n    text', self.editor.get_text())
+
 
 if __name__ == '__main__':
     unittest.main()
       author_email='aligrudi@users.sourceforge.net',
       url='http://rope.sf.net/',
       packages=['rope'],
-      scripts=['rope'])
+      scripts=['rope.py'])