Commits

Anonymous committed 51cb549

added statusbar module

Comments (0)

Files changed (15)

 
 License
 -------
-  This program is under the terms of GPL(GNU General Public License). Have a look
-at copying file for more information.
+  This program is under the terms of GPL(GNU General Public License). Have a
+look at copying file for more information.
+- Auto-complete class and function names : May 16, 2006
+
+
+- Auto-complete global variables : May 14, 2006
+
+
 > Public release 0.1 : May 8, 2006
 
 
 * Add import @ 2
 
 
-* Auto-complete class and function names @ 2
-
-
 * Show PyDoc @ 2
 
 
 * Replacement; M-% @ 1
 
 
-* Save as; C-x C-w
+* Save as and save all; C-x C-w, C-x s @ 1
 
 
 * Remembering last open project @ 1
 * Changing next/prev word to stop on underline and capital letters @ 1
 
 
+* Auto-completing function parameter names @ 2
+
+
 * Commenting and uncommenting lines @ 1
 
 
 * Writing ASTs @ 4
 
 
-* Auto-complete variable names @ 3
+* Auto-complete imported objects @ 3
 
 
-* Making ASTs @ 4
+* Proposing templates in auto-completion proposals @ 2
+
+
+* Auto completion type @ 3
+  * Inserting or overwriting
+  * Inserting common prefixes
+
+
+* Auto completing keywords and builtins @ 1
+
+
+* Auto-complete local variable names @ 3
+
+
+* Enhancing auto-completion @ 2
+  * What if the statement in current line is spread in more than one line
+  * Complete as you type (updating proposal list while typing)
+  * What to do when the program has syntax errors
 
 
 > Public release 0.2pre : May 20, 2006
 
 
-* Show searching status in the status bar @ 1
-
-
-* Auto-complete module names @ 3
+* Show searching status in the status bar @ 2
 
 
 --- Remaining Stories ---

docs/workingon.txt

-*** Auto-complete imports names @ 3 ***
+*** Show searching status in the status bar @ 2 ***
 
-- Applying the completion
+- Removing status kind
+- Return what when status kind does not exist
+- Setting width for status texts
+- Showing status while searching
+- Separate module for StatusBarManager
+- create_status, get_status
 
-* What if the statement in current line is spread in more than one line
+* What if the editor goes out of focus while searching
+* Fixed places for status texts
+
 * Extract listbox; duplicates in editor and core
-* Complete as you type (updating proposal list while typing)
+    ? uihelpers module
+? Separating ui modules and packages
+  ? Decide which modules are the domain and which are the presentation
+  ? Should editing tools access Editor directly? Which of them?
+? Specifing the type of each story; UI or Core
+
 ? The connection between ASTs and Type Hierarchies
-
 * Better font selection on windows
 ? Think about a library for functional testing
 ? SF repository; SVN or CVS? How to synchronize local SVN with SF?

rope/codeassist.py

 
 
 class CompletionResult(object):
+    """A completion result.
+    
+    Attribute:
+    proposals -- A list of CompletionProposals
+    start_offset -- completion start offset
+    end_offset -- completion end offset
+    
+    """
     def __init__(self, proposals=[], start_offset=0, end_offset=0):
         self.proposals = proposals
         self.start_offset = start_offset
 
 import rope.editor
 import rope.fileeditor
+import rope.statusbar
 from rope.exceptions import RopeException
 from rope.project import Project, FileFinder, PythonFileRunner
 
                 return editor
         editor = rope.fileeditor.FileEditor(Core.get_core().get_open_project(), file_,
                                             rope.editor.GraphicalEditor(self.editor_frame))
+        editor.get_editor().set_status_bar_manager(self.core.status_bar_manager)
         self.editors.append(editor)
         title = Radiobutton(self.editor_list, text=file_.get_name(),
                             variable=self.active_file_path,
 
 
 class Core(object):
-    '''The main class for the IDE'''
+    """The main class for the IDE"""
     def __init__(self):
         self.root = Tk()
         self.root.title('Rope')
         self.editor_manager = EditorManager(self.editor_panel, self)
 
         self.status_bar = Frame(self.main, borderwidth=1, relief=RIDGE)
-        self.status_text = Label(self.status_bar, text=' ', height=1)
+        self.status_bar_manager = rope.statusbar.StatusBarManager(self.status_bar)
+        line_status = self.status_bar_manager.create_status('line')
+        line_status.set_width(20)
 
         self._set_key_binding(self.root)
         self.root.protocol('WM_DELETE_WINDOW', self.exit)
             self.switch_active_editor()
             return 'break'
         widget.bind('<Control-KeyRelease-F6>', do_switch_active_editor)
+        line_status = self.status_bar_manager.get_status('line')
         def show_current_line_number(event):
+            line_text = ' '
             if self.editor_manager.active_editor:
-                self.status_text['text'] = 'line : %d' % \
-                   self.editor_manager.active_editor.get_editor().get_current_line_number()
-            else:
-                self.status_text['text'] = ' '
+                line_text = 'line : %d' % \
+                              self.editor_manager.active_editor.get_editor().get_current_line_number()
+            line_status.set_text(line_text)
         widget.bind('<Any-KeyRelease>', show_current_line_number, '+')
         widget.bind('<Any-Button>', show_current_line_number)
         widget.bind('<FocusIn>', show_current_line_number)
         self.main.rowconfigure(0, weight=1)
         self.main.columnconfigure(0, weight=1)
         self.editor_panel.pack(fill=BOTH, expand=1)
-        self.status_text.pack(side=LEFT, fill=BOTH)
         self.status_bar.pack(fill=BOTH, side=BOTTOM)
         self.main.pack(fill=BOTH, expand=1)
         self.main.pack_propagate(0)
         self.highlighting = rope.highlight.NoHighlighting()
         self.indenter = rope.indenter.NormalIndenter(self)
         self.code_assist = rope.codeassist.NoAssist()
+        self.status_bar_manager = None
 
     def _initialize_highlighting(self):
         def colorize(event=None):
                 print 'end modified', event
         self.modified_flag = False
         self.text.bind('<Any-KeyRelease>', colorize, '+')
-#        self.text.bind('<<Modified>>', modified)
+        #        self.text.bind('<<Modified>>', modified)
         self.text.edit_modified(False)
 
     def _highlight_range(self, startIndex, endIndex):
 
 
     def _show_completion_window(self):
+        result = self.code_assist.complete_code(self.get_text(), self.get_current_offset())
         toplevel = Toplevel()
+        toplevel.title('Completion Proposals')
         frame = Frame(toplevel)
         label = Label(frame, text='Completion Proposals')
         proposals = Listbox(frame, selectmode=SINGLE, width=23, height=7)
         scrollbar = Scrollbar(frame, orient=VERTICAL)
         scrollbar['command'] = proposals.yview
         proposals.config(yscrollcommand=scrollbar.set)
-        result = self.code_assist.complete_code(self.get_text(), self.get_current_offset())
         for proposal in result.proposals:
             proposals.insert(END, proposal.completion)
         if result:
             current_pos = str(self.text.index(current_pos + ' +1l lineend'))
         return result
 
+    def set_status_bar_manager(self, manager):
+        self.status_bar_manager = manager
+
 
 class GraphicalTextIndex(TextIndex):
     '''An immutable class for pointing to a position in a text'''

rope/exceptions.py

 class RopeException(Exception):
-    '''Base exception for rope'''
-    pass
+    """Base exception for rope"""
+
+
+class RopeUIException(RopeException):
+    """Base exception for user interface parts of rope"""

rope/searching.py

         self.starting_index = self.editor.get_insert()
         self.searching_state = ForwardSearching()
         self.current_match = Match(self.starting_index, self.starting_index)
+        self.status_text = None
+        if self.editor.status_bar_manager:
+            self.status_text = self.editor.status_bar_manager.create_status('search')
+            self.status_text.set_width(25)
+        self.update_status_text()
+
+    def _finish_searching(self):
+        if self.status_text:
+            self.status_text.remove()
+        self.searching_state = NotSearching()
+        self.editor.highlight_match(self.current_match)
 
     def end_searching(self):
-        self.searching_state = NotSearching()
         self.current_match = Match(self.editor.get_insert(), self.editor.get_insert())
-        self.editor.highlight_match(self.current_match)
+        self._finish_searching()
 
     def is_searching(self):
         return self.searching_state.is_searching(self)
 
+    def update_status_text(self):
+        if self.status_text:
+            direction = ''
+            if isinstance(self.searching_state, BackwardSearching):
+                direction = ' backward'
+            self.status_text.set_text('searching%s: <%s>' % (direction, self.keyword))
+
     def append_keyword(self, postfix):
         self.searching_state.append_keyword(self, postfix)
+        self.update_status_text()
 
     def shorten_keyword(self):
         self.searching_state.shorten_keyword(self)
+        self.update_status_text()
 
     def cancel_searching(self):
-        self.searching_state = NotSearching()
         self.current_match = Match(self.starting_index, self.starting_index)
-        self.editor.highlight_match(self.current_match)
+        self._finish_searching()
 
     def configure_search(self, forward=True):
         if forward and self.searching_state.is_searching(self) and \
 
     def next_match(self):
         self.searching_state.next_match(self)
+        self.update_status_text()
 
     def _match(self, start, forward=True, insert_side='right'):
         if self.keyword:

rope/statusbar.py

+from Tkinter import *
+
+import rope.exceptions
+
+
+class StatusBarException(rope.exceptions.RopeUIException):
+    pass
+
+class StatusText(object):
+    def __init__(self, status_bar_manager, kind, label):
+        self.manager = status_bar_manager
+        self.kind = kind
+        self.label = label
+        self.width = 0
+    
+    def set_width(self, width):
+        self.width = width
+        #        self.label['width'] = width
+
+    def set_text(self, text):
+        self.label['text'] = text.ljust(self.width)
+        
+    def get_text(self):
+        return self.label['text']
+
+    def remove(self):
+        self.manager.remove_status(self)
+
+
+class StatusBarManager(object):
+    """Manages the status bar"""
+    
+    def __init__(self, status_bar):
+        self.status_bar = status_bar
+        self.status_text = {}
+    
+    def get_status(self, kind):
+        if not self.status_text.has_key(kind):
+            raise StatusBarException('StatusText <%s> does not exist' % kind)
+        return self.status_text[kind]
+
+    def create_status(self, kind):
+        if self.status_text.has_key(kind):
+            raise StatusBarException('StatusText <%s> already exists' % kind)
+        label = Label(self.status_bar, text=' ', height=1, relief=RIDGE)
+        self.status_text[kind] = StatusText(self, kind, label)
+        label.pack(side=LEFT)
+        self.status_text[kind].set_text('')
+        return self.status_text[kind]
+
+    def remove_status(self, status):
+        status.label.destroy()
+        del self.status_text[status.kind]

ropetest/coretest.py

         self.projectMaker = SampleProjectMaker()
         self.fileName = self.projectMaker.getSampleFileName()
         self.fileName2 = 'samplefile2.txt'
-        file = open(self.fileName, 'w')
-        file.write('sample text')
-        file.close()
+        file_ = open(self.fileName, 'w')
+        file_.write('sample text')
+        file_.close()
         Core.get_core().open_project(self.projectMaker.getRoot())
         self.textEditor = Core.get_core().open_file(self.fileName)
         self.project = Core.get_core().get_open_project()

ropetest/mockeditor.py

     def __init__(self):
         self.content = ''
         self.insertIndex = MockTextIndex(self, 0)
+        self.status_bar_manager = None
     
     def get_text(self):
         return self.content

ropetest/searchingtest.py

         self.assertEquals(False, self.searcher.is_searching())
         self.assertEquals(self.editor.get_start(), self.searcher.get_match().start)
 
-    def test_not_searching_when_not_searching(self):
-        self.searcher.append_keyword('s')
-        self.assertTrue(self.searcher.get_match() is None)
-
     def test_simple_one_char_searching(self):
         self.searcher.start_searching()
         self.searcher.append_keyword('s')
         self.searcher.append_keyword('a')
         self.assertEquals(self.editor.get_index(2), self.searcher.get_match().end)
 
+    def test_searching_status_bar(self):
+        self.editor.status_bar_manager = PlaceholderStatusBarManager()
+        # TODO: finish
+
+
+class PlaceholderStatusBarManager(object):
+    def get_status(self, kind):
+        if not self.status_text.has_key(kind):
+            self.status_text[kind] = StatusText(self, kind, label)
+            self.status_text[kind].set_text('')
+        return self.status_text[kind]
+
+    def remove_status(self, status):
+        del self.status_text[status.kind]
+
+
+class PlaceholderStatusText(object):
+    def __init__(self, status_bar_manager, kind):
+        self.manager = status_bar_manager
+        self.kind = kind
+        self.width = 0
+        self.text = ''
+    
+    def set_width(self, width):
+        self.width = width
+
+    def set_text(self, text):
+        self.text = text.ljust(self.width)
+
+    def get_text(self):
+        return self.text
+
+    def remove(self):
+        self.manager.remove_status(self)
+
+
 
 if __name__ == '__main__':
     unittest.main()

ropetest/statusbartest.py

+import unittest
+import Tkinter
+
+from rope.statusbar import StatusBarManager, StatusBarException
+
+class StatusBarTest(unittest.TestCase):
+
+    def setUp(self):
+        super(StatusBarTest, self).setUp()
+        if not hasattr(StatusBarTest, '_frame'):
+            StatusBarTest._frame = Tkinter.Frame()
+        self.manager = StatusBarManager(StatusBarTest._frame)
+
+    def tearDown(self):
+        super(StatusBarTest, self).tearDown()
+
+    def test_status_bar_manager(self):
+        status = self.manager.create_status('sample')
+        status.set_text('sample status')
+        self.assertEquals('sample status', status.get_text())
+        self.assertEquals('sample status', self.manager.get_status('sample').get_text())
+
+    def test_status_bar_manager_multiple_status(self):
+        status1 = self.manager.create_status('sample1')
+        status2 = self.manager.create_status('sample2')
+        status1.set_text('1. sample status')
+        status2.set_text('2. sample status')
+        self.assertEquals('1. sample status', status1.get_text())
+        self.assertEquals('2. sample status', status2.get_text())
+
+    def test_status_removing(self):
+        status = self.manager.create_status('sample')
+        self.assertEquals(status, self.manager.get_status('sample'))
+        status.remove()
+        self.assertNotEquals(status, self.manager.create_status('sample'))
+
+    def test_getting_a_nonexistant_status(self):
+        try:
+            status = self.manager.get_status('nonexistant')
+            self.fail('should have raised exception')
+        except StatusBarException:
+            pass
+
+    def test_creating_a_status_while_it_exists(self):
+        self.manager.create_status('sample')
+        try:
+            status = self.manager.create_status('sample')
+            self.fail('should have raised exception')
+        except StatusBarException:
+            pass
+
+
+if __name__ == '__main__':
+    unittest.main()
 import ropetest.searchingtest
 import ropetest.indentertest
 import ropetest.codeassisttest
+import ropetest.statusbartest
 
 
 if __name__ == '__main__':
     result.addTests(unittest.makeSuite(ropetest.highlighttest.HighlightTest))
     result.addTests(unittest.makeSuite(ropetest.indentertest.PythonCodeIndenterTest))
     result.addTests(unittest.makeSuite(ropetest.codeassisttest.CodeAssistTest))
+    result.addTests(unittest.makeSuite(ropetest.statusbartest.StatusBarTest))
     runner = unittest.TextTestRunner()
     runner.run(result)