Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/vimtutor.py
diff options
context:
space:
mode:
Diffstat (limited to 'vimtutor.py')
-rw-r--r--vimtutor.py311
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 ############
+