diff options
Diffstat (limited to 'vimtutor.py')
-rw-r--r-- | vimtutor.py | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/vimtutor.py b/vimtutor.py new file mode 100644 index 0000000..db6edbf --- /dev/null +++ b/vimtutor.py @@ -0,0 +1,311 @@ +# Copyright (C) 2011, George Hunt georgejhunt@gmail.com +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import sys +#import simplejson +import pickle +import ConfigParser +import shutil +import gobject +import subprocess +from exceptions import * + +import logging +from gettext import gettext as _ + +import gtk +import vte +import pango + +from sugar.graphics.toolbutton import ToolButton +from sugar.activity import activity +from sugar import env +#from help.help import Help +from terminal_gui import TerminalActivity +from terminal import TerminalBase +import util + +logging.basicConfig() +_logger = logging.getLogger('vimtutor') +_logger.setLevel(logging.DEBUG) + +#A place where a student can make world writeable, hence multi-Activity +ICTDIR = '/home/olpc/.ictcore' + +class VimTutor(TerminalActivity): + + def __init__(self, handle): + TerminalActivity.__init__(self, self, handle) + _logger.debug('lower level init completed') + self.util = util.Utilities(self) + self.tutor = 'vimtutor' + self.session_list = [] + self.session_cwd = {} + #start up vimtutor 5 times automatically, 1 for testing + self.tutor_count = 1 + self.noautotutor = False + + ########## Additions for VimTutor ########### + self.saved_env = os.environ.copy() + self.python_version = sys.version[0:3] + #set up HOME directory if not initialized to activity root + self.home = self.get_home() + self.mergetree( + os.path.join(activity.get_bundle_path(),'home'), + self.home, overwrite=False) + + #move the HOME directory to something writeable + os.environ['HOME'] = self.home + os.chdir(os.path.join(self.home,'vimtutor')) + + #add activity bin to PATH + self.add_to_path('PATH', os.path.join(activity.get_bundle_path(),'bin:')) + + for f in sys.path: + self.add_to_path('PYTHONPATH', f) + + #runtime libraries needed but not present in some builds: + self.add_to_path('LD_LIBRARY_PATH', os.path.join(activity.get_bundle_path(), 'lib')) + + if self.python_version != '2.6': + os.environ['VIMRUNTIME'] = os.path.join(activity.get_bundle_path(),'vim71') + self.vim_version_selector = '71' + else: + os.environ['VIMRUNTIME'] = os.path.join(activity.get_bundle_path(),'vim73') + self.vim_version_selector = '73' + + #ipython uses envirnment to find editor, PATH already set + os.environ['EDITOR'] = 'gvim' + self.vim_exe = os.path.join(activity.get_bundle_path(), + 'bin',self.vim_version_selector, 'vim') + #following env variable required by vimtutor script + os.environ['VIM'] = self.vim_exe + + #rewrite .bashrc so that aliases are set for vi, vim, gvim correctly + self.rewrite_bashrc() + + if self.tutor_count > 0: + #start up vimtutor and switch to that vte.terminal + self._create_tab(None) + self.feed_terminal(0, self.tutor) + + self._create_tab(None) + self.feed_terminal(1, self.vim_exe + ' --servername VIM -p') + self.set_terminal(0) + gobject.idle_add(self.set_first) + _logger.debug('finished top level init') + + def set_first(self): + self.set_terminal(0) + + ############### Routines for VimTutor ############ + def can_close(self): + _logger.debug('can close') + + cmd = self.vim_exe + ' --serverlist' + results,error = self.util.command_line(cmd) + _logger.debug('sessionlist is:%r Error: %s'%(results,error,) ) + clean_list = [] + if not error: + self.session_list = results.split('\n') + for session_name in self.session_list: + if not session_name: continue + #actually interogate server, is it really alive? + cmd = self.vim_exe + ' --servername %s --remote-expr "getcwd()"'%(session_name,) + results,error = self.util.command_line(cmd) + if not error: + clean_list.append(session_name) + self.session_cwd[session_name] = results + session_path = os.path.join(self.home, '.vim', 'sessions', session_name + '.vim') + #write out the session information for later journal inclusion + cmd = self.vim_exe + ' --servername %s --remote-send "<C-\><C-N>:mks! %s<CR>"'%\ + (session_name, session_path,) + results,error = self.util.command_line(cmd) + #write open buffers and quit + cmd = self.vim_exe + ' --servername %s --remote-send "<C-\><C-N>:wqa<CR>"'%\ + (session_name,) + results,error = self.util.command_line(cmd) + self.session_list = clean_list + return True + + def add_to_path(self, path, new_dir): + if new_dir not in os.environ.get(path,'').split(':'): + if os.environ.get(path): + os.environ[path] = new_dir + ':' + os.environ[path] + else: + os.environ[path] = new_dir + + def page_selected(self, widget, tab_no, dummy): + """tab clicked grabs focus away from terminal, grab it back""" + gobject.idle_add(self.grab_vt_focus) + + def get_home(self): + """Accomodates the change in Sugar for getting root""" + #look for bitfrost antidote + ictcore = self.get_writeable_ictcore() + if ictcore: + return ictcore + if hasattr(activity, 'get_activity_root'): + return os.path.join(activity.get_activity_root(), 'data') + return os.path.join(self.get_activity_root(), 'data') + + def get_writeable_ictcore(self): + """bitfrost isolates activities from one another, defeat this for + ict activities""" + if os.path.isdir(ICTDIR): + #is it writeable? + try: + fd = open(os.path.join(ICTDIR,'test'),'w') + fd.write('this is a test') + fd.close() + os.unlink(os.path.join(ICTDIR,'test')) + except IOError,e: + return None + return ICTDIR + + def mergetree(self, src, dst, symlinks=False, overwrite=True, + ignore=None): + """Recursively copy a directory tree using copy(). + <minor rework of shutil.copytree so no error if dir exisis, + and add a flag to overwrite existing file or not. Original + purpose is to initialize home directory w/ config files> + + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + XXX Consider this example code rather than the ultimate tool. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + if not os.path.isdir(dst): + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + + try: + if symlinks and os.path.islink(srcname): + linkto = os.readlink(srcname) + os.symlink(linkto, dstname) + elif os.path.isdir(srcname): + self.mergetree(srcname, dstname, symlinks, ignore) + else: + if not os.path.isdir(srcname) and (overwrite or + not os.path.isfile(dstname)): + shutil.copy(srcname, dstname) + # XXX What about devices, sockets etc.? + except (IOError, os.error), why: + errors.append((srcname, dstname, str(why))) + _logger.exception('failed inner copy2') + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error, err: + errors.extend(err.args[0]) + try: + #shutil.copystat(src, dst) + pass + except OSError, why: + errors.extend((src, dst, str(why))) + _logger.exception('failed copystat') + if errors: + raise Error, errors + + def rewrite_bashrc(self): + text = '' + try: + f = open(os.path.join(self.home, '.bashrc'),"r") + except IOError,e: + _logger.error('unable to open%s Exception:%s'% + (os.path.join(self.home, '.bashrc'),e)) + return + for line in f: + if line.find('alias gvim=') != -1: + continue + if line.find('alias vim=') != -1: + continue + if line.find('alias vi=') != -1: + continue + text += line + text += "alias vi='" + os.path.join(activity.get_bundle_path(), + 'bin', self.vim_version_selector, 'vim') + " -u NONE -c set nocp'\n" + text += "alias vim='" + os.path.join(activity.get_bundle_path(), + 'bin',self.vim_version_selector, 'vim') + " -p --servername vim'\n" + text += "alias gvim='" + os.path.join(activity.get_bundle_path(), + 'bin', self.vim_version_selector, 'gvim') + " -g -p --servername gvim'\n" + try: + _file = file(os.path.join(self.home,'.bashrc'), 'w') + _file.write(text) + _file.close() + except IOError,e: + _logger.error('unable to rewrite%s Exception:%s'% + (os.path.join(self.home, '.bashrc'),e)) + + + def feed_terminal(self, tab_no, cmd): + vt = self._notebook.get_nth_page(tab_no).vt + vt.feed_child('%s\r\n'%cmd) + + def display_terminal(self, tab_no, cmd): + vt = self._notebook.get_nth_page(tab_no).vt + vt.feed('%s\r\n'%cmd) + + def set_terminal(self, tab_no): + self._notebook.set_current_page(tab_no) + + """ + def _create_gvim_tab(self): + self.gvim_label = gtk.Label() + self._socket = gtk.Socket() + self._socket.show() + #self.event_box.add(self._socket) + self.gvim_label.set_text('GVIM') + index = self._notebook.append_page(self._socket, self.gvim_label) + self.socket_id = str(self._socket.get_id()) + exe = (os.path.join(activity.get_bundle_path(), + 'bin', self.vim_version_selector, 'gvim')) + + myargs = '--socketid ' + self.socket_id + _logger.debug('exe:%s args:%s'%(exe, myargs,)) + self.gvim_pid = subprocess.Popen([exe, myargs,]).pid + self.set_terminal(index) + self._notebook.show_all() + """ + ############### End Routines for VimTutor ############ + |