# Copyright (C) 2011 Bradley N. Miller # # 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 3 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, see . # __author__ = 'bmiller' from docutils import nodes from docutils.parsers.rst import directives from docutils.parsers.rst import Directive import json import os # try: # import conf # version = conf.version # staticserver = conf.staticserver # except: # version = '2.1.0' # staticserver = 'runestonestatic.appspot.com' def setup(app): app.add_directive('activecode',ActiveCode) app.add_directive('actex',ActiveExercise) app.add_stylesheet('codemirror.css') app.add_stylesheet('activecode.css') app.add_javascript('jquery.highlight.js' ) app.add_javascript('bookfuncs.js' ) app.add_javascript('codemirror.js' ) app.add_javascript('python.js' ) app.add_javascript('javascript.js' ) app.add_javascript('activecode.js') app.add_javascript('skulpt.min.js' ) app.add_javascript('skulpt-stdlib.js') app.add_node(ActivcodeNode, html=(visit_ac_node, depart_ac_node)) app.connect('doctree-resolved',process_activcode_nodes) app.connect('env-purge-doc', purge_activecodes) START = '''
''' EDIT1 = '''

%(caption)s (%(divid)s)

''' UNHIDE=''' ''' GRADES = ''' ''' AUDIO = ''' ''' EDIT2 = '''
''' CANVAS = '''
''' SUFF = '''''' PRE = '''

''' END = '''
''' AUTO = ''' ''' #' class ActivcodeNode(nodes.General, nodes.Element): def __init__(self,content): """ Arguments: - `self`: - `content`: """ super(ActivcodeNode,self).__init__() self.ac_components = content # self for these functions is an instance of the writer class. For example # in html, self is sphinx.writers.html.SmartyPantsHTMLTranslator # The node that is passed as a parameter is an instance of our node class. def visit_ac_node(self,node): #print self.settings.env.activecodecounter res = START if 'above' in node.ac_components: res += CANVAS res += EDIT1 if 'tour_1' not in node.ac_components: res += EDIT2 else: res += AUDIO + EDIT2 if 'above' not in node.ac_components: if 'nocanvas' not in node.ac_components: res += CANVAS if 'hidecode' not in node.ac_components: node.ac_components['hidecode'] = 'block' if node.ac_components['hidecode'] == 'none': res += UNHIDE if 'gradebutton' in node.ac_components: res += GRADES if 'suffix' in node.ac_components: res += SUFF if 'nopre' not in node.ac_components: res += PRE if 'autorun' in node.ac_components: res += AUTO res += END res = res % node.ac_components res = res.replace("u'","'") # hack: there must be a better way to include the list and avoid unicode strings self.body.append(res) def depart_ac_node(self,node): ''' This is called at the start of processing an activecode node. If activecode had recursive nodes etc and did not want to do all of the processing in visit_ac_node any finishing touches could be added here. ''' pass def process_activcode_nodes(app,env,docname): pass def purge_activecodes(app,env,docname): pass class ActiveCode(Directive): required_arguments = 1 optional_arguments = 1 has_content = True option_spec = { 'nocanvas':directives.flag, 'nopre':directives.flag, 'above':directives.flag, # put the canvas above the code 'autorun':directives.flag, 'caption':directives.unchanged, 'include':directives.unchanged, 'hidecode':directives.flag, 'language':directives.unchanged, 'tour_1':directives.unchanged, 'tour_2':directives.unchanged, 'tour_3':directives.unchanged, 'tour_4':directives.unchanged, 'tour_5':directives.unchanged } def run(self): env = self.state.document.settings.env # keep track of how many activecodes we have.... could be used to automatically make a unique id for them. if not hasattr(env,'activecodecounter'): env.activecodecounter = 0 env.activecodecounter += 1 self.options['divid'] = self.arguments[0] if self.content: if '====' in self.content: idx = self.content.index('====') source = "\n".join(self.content[:idx]) suffix = "\n".join(self.content[idx+1:]) else: source = "\n".join(self.content) suffix = "\n" else: source = '\n' suffix = '\n' self.options['initialcode'] = source self.options['suffix'] = suffix str=source.replace("\n","*nline*") str0=str.replace("\"","*doubleq*") str1=str0.replace("(","*open*") str2=str1.replace(")","*close*") str3=str2.replace("'","*singleq*") self.options['argu']=str3 complete="" no_of_buttons=0 okeys = self.options.keys() for k in okeys: if '_' in k: x,label = k.split('_') no_of_buttons=no_of_buttons+1 complete=complete+self.options[k]+"*atype*" newcomplete=complete.replace("\"","*doubleq*") self.options['ctext'] = newcomplete self.options['no_of_buttons'] = no_of_buttons if 'caption' not in self.options: self.options['caption'] = '' if 'include' not in self.options: self.options['include'] = 'undefined' else: lst = self.options['include'].split(',') lst = [x.strip() for x in lst] self.options['include'] = lst if 'hidecode' in self.options: self.options['hidecode'] = 'none' else: self.options['hidecode'] = 'block' if 'language' not in self.options: self.options['language'] = 'python' return [ActivcodeNode(self.options)] class ActiveExercise(ActiveCode): required_arguments = 1 optional_arguments = 0 has_content = True def run(self): self.options['hidecode'] = True self.options['gradebutton'] = True return super(ActiveExercise,self).run() if __name__ == '__main__': a = ActiveCode()