<commit_before>import sys
import os
import traceback, linecache
import re
import objc
import time
import random
import signal
import atexit

import pprint
pp = pprint.pprint

import pdb

# set to true to have stdio on the terminal for pdb
debugging = False

# if true print out some debug info on stdout
kwlog = False

import Foundation
import AppKit
NSObject = AppKit.NSObject
NSColor = AppKit.NSColor
NSScriptCommand = AppKit.NSScriptCommand

NSDocument = AppKit.NSDocument
NSDocumentController = AppKit.NSDocumentController

NSNotificationCenter = AppKit.NSNotificationCenter

NSFontAttributeName = AppKit.NSFontAttributeName
NSScreen = AppKit.NSScreen
NSMenu = AppKit.NSMenu
NSCursor = AppKit.NSCursor
NSTimer = AppKit.NSTimer
NSForegroundColorAttributeName = AppKit.NSForegroundColorAttributeName

NSPasteboard = AppKit.NSPasteboard
NSPDFPboardType = AppKit.NSPDFPboardType
NSPostScriptPboardType = AppKit.NSPostScriptPboardType
NSTIFFPboardType = AppKit.NSTIFFPboardType

NSBundle = AppKit.NSBundle
NSSavePanel = AppKit.NSSavePanel
NSLog = AppKit.NSLog
NSApp = AppKit.NSApp
NSPrintOperation = AppKit.NSPrintOperation
NSWindow = AppKit.NSWindow
NSBorderlessWindowMask = AppKit.NSBorderlessWindowMask
NSBackingStoreBuffered = AppKit.NSBackingStoreBuffered
NSView = AppKit.NSView
NSGraphicsContext = AppKit.NSGraphicsContext
NSRectFill = AppKit.NSRectFill
NSAffineTransform = AppKit.NSAffineTransform
NSFocusRingTypeExterior = AppKit.NSFocusRingTypeExterior
NSResponder = AppKit.NSResponder

NSURL = AppKit.NSURL
NSWorkspace = AppKit.NSWorkspace
NSBezierPath = AppKit.NSBezierPath


import threading
Thread = threading.Thread

import ValueLadder
MAGICVAR = ValueLadder.MAGICVAR

import PyDETextView

import preferences
NodeBoxPreferencesController = preferences.NodeBoxPreferencesController
LibraryFolder = preferences.LibraryFolder

import util
errorAlert = util.errorAlert


# from nodebox import util
import nodebox.util
util = nodebox.util
makeunicode = nodebox.util.makeunicode

import nodebox.util.ottobot
genProgram = nodebox.util.ottobot.genProgram


import nodebox.util.QTSupport
QTSupport = nodebox.util.QTSupport

# from nodebox import graphics
import nodebox.graphics
graphics = nodebox.graphics

# AppleScript enumerator codes for PDF and Quicktime export
PDF = 0x70646678 # 'pdfx'
QUICKTIME = 0x71747878 # 'qt  '


black = NSColor.blackColor()
VERY_LIGHT_GRAY = black.blendedColorWithFraction_ofColor_(0.95,
                                                          NSColor.whiteColor())
DARKER_GRAY = black.blendedColorWithFraction_ofColor_(0.8,
                                                      NSColor.whiteColor())

# from nodebox.gui.mac.dashboard import *
# from nodebox.gui.mac.progressbar import ProgressBarController
import dashboard
DashboardController = dashboard.DashboardController

import progressbar
ProgressBarController = progressbar.ProgressBarController

class ExportCommand(NSScriptCommand):
    pass    

class OutputFile(object):

    def __init__(self, data, isErr=False):
        self.data = data
        self.isErr = isErr

    def write(self, data):
        if isinstance(data, str):
            try:
                data = unicode(data, "utf_8", "replace")
            except UnicodeDecodeError:
                data = "XXX " + repr(data)
        self.data.append((self.isErr, data))



# class defined in NodeBoxDocument.xib
class NodeBoxDocument(NSDocument):

    graphicsView = objc.IBOutlet()
    outputView = objc.IBOutlet() 
    textView = objc.IBOutlet()
    window = objc.IBOutlet()
    variablesController = objc.IBOutlet()
    dashboardController = objc.IBOutlet()
    animationSpinner = objc.IBOutlet()

    # The ExportImageAccessory adds:
    exportImageAccessory = objc.IBOutlet()
    exportImageFormat = objc.IBOutlet()
    exportImagePageCount = objc.IBOutlet()

    # The ExportMovieAccessory adds:
    exportMovieAccessory = objc.IBOutlet()
    exportMovieFrames = objc.IBOutlet()
    exportMovieFps = objc.IBOutlet()

    # When the PageCount accessory is loaded, we also add:
    pageCount = objc.IBOutlet()
    pageCountAccessory = objc.IBOutlet()

    # When the ExportSheet is loaded, we also add:
    exportSheet = objc.IBOutlet()
    exportSheetIndicator = objc.IBOutlet()

    path = None
    exportDir = None
    magicvar = None # Used for value ladders.
    _code = None
    vars = []
    movie = None

    def windowNibName(self):
        return "NodeBoxDocument"

    def init(self):
        self = super(NodeBoxDocument, self).init()
        nc = NSNotificationCenter.defaultCenter()
        nc.addObserver_selector_name_object_(self,
                                             "textFontChanged:",
                                             "PyDETextFontChanged",
                                             None)
        self.namespace = {}
        self.canvas = graphics.Canvas()
        self.context = graphics.Context(self.canvas, self.namespace)
        self.animationTimer = None
        self.__doc__ = {}
        self._pageNumber = 1
        self._frame = 150
        self.fullScreen = None
        self._seed = time.time()

        # this is None
        self.currentView = self.graphicsView
        return self

    def autosavesInPlace(self):
        return True

    def close(self):
        self.stopScript()
        super(NodeBoxDocument, self).close()

    def __del__(self):
        nc = NSNotificationCenter.defaultCenter()
        nc.removeObserver_name_object_(self, "PyDETextFontChanged", None)
        # text view has a couple of circular refs, it can let go of them now
        self.textView._cleanup()

    def textFontChanged_(self, notification):
        font = PyDETextView.getBasicTextAttributes()[NSFontAttributeName]
        self.outputView.setFont_(font)

    def readFromFile_ofType_(self, path, tp):
        if self.textView is None:
            # we're not yet fully loaded
            self.path = path
        else:
            # "revert"
            self.readFromUTF8_(path)
        return True

    def writeToFile_ofType_(self, path, tp):
        f = file(path, "w")
        text = self.textView.string()
        f.write(text.encode("utf8"))
        f.close()
        return True

    def windowControllerDidLoadNib_(self, controller):
        if self.path:
            self.readFromUTF8_(self.path)
        font = PyDETextView.getBasicTextAttributes()[NSFontAttributeName]
        self.outputView.setFont_(font)
        self.textView.window().makeFirstResponder_(self.textView)
        self.windowControllers()[0].setWindowFrameAutosaveName_("NodeBoxDocumentWindow")

        # switch off automatic substitutions
        try:
            self.textView.setAutomaticQuoteSubstitutionEnabled_( False )
            self.textView.setAutomaticDashSubstitutionEnabled_( False )

            # This does not work well with syntax coloring
            #self.textView.setAutomaticLinkDetectionEnabled_( True )
            #self.textView.setDisplaysLinkToolTips_( True )

            self.outputView.setAutomaticQuoteSubstitutionEnabled_( False )
            self.outputView.setAutomaticDashSubstitutionEnabled_( False )
            #self.outputView.setAutomaticLinkDetectionEnabled_( True )
            #self.outputView.setDisplaysLinkToolTips_( True )
        except Exception, err:
            pass

    def readFromUTF8_(self, path):
        f = file(path)
        text = unicode(f.read(), "utf_8")
        f.close()
        self.textView.setString_(text)
        self.textView.usesTabs = "\t" in text
        
    def cleanRun_newSeed_buildInterface_(self, fn, newSeed, buildInterface):
        self.animationSpinner.startAnimation_(None)

        # Prepare everything for running the script
        self.prepareRun()

        # Run the actual script
        success = self.fastRun_newSeed_(fn, newSeed)
        self.animationSpinner.stopAnimation_(None)

        if success and buildInterface:

            # Build the interface
            self.vars = self.namespace["_ctx"]._vars
            if len(self.vars) > 0:
                self.buildInterface_(None)

        return success

    def prepareRun(self):

        # Compile the script
        success, output = self.boxedRun_args_(self._compileScript, [])
        self.flushOutput_(output)
        if not success:
            return False

        # Initialize the namespace
        self._initNamespace()
        
        # Reset the pagenum
        self._pageNum = 1
        
        # Reset the frame
        self._frame = 1

        self.speed = self.canvas.speed = None

    def fastRun_newSeed_(self, fn, newSeed = False):
        """This is the old signature. Dispatching to the new with args"""
        return self.fastRun_newSeed_args_( fn, newSeed, [])


    def fastRun_newSeed_args_(self, fn, newSeed = False, args=[]):
        # Check if there is code to run
        if self._code is None:
            return False

        # Clear the canvas
        self.canvas.clear()

        # Generate a new seed, if needed
        if newSeed:
            self._seed = time.time()
        random.seed(self._seed)

        # Set the mouse position
        
        # kw fix
        if not self.currentView:
            self.currentView = self.graphicsView

        window = self.currentView.window()
        pt = window.mouseLocationOutsideOfEventStream()
        mx, my = window.contentView().convertPoint_toView_(pt, self.currentView)
        # Hack: mouse coordinates are flipped vertically in FullscreenView.
        # This flips them back.
        if isinstance(self.currentView, FullscreenView):
            my = self.currentView.bounds()[1][1] - my
        if self.fullScreen is None:
            mx /= self.currentView.zoom
            my /= self.currentView.zoom
        self.namespace["MOUSEX"], self.namespace["MOUSEY"] = mx, my
        self.namespace["mousedown"] = self.currentView.mousedown
        self.namespace["keydown"] = self.currentView.keydown
        self.namespace["key"] = self.currentView.key
        self.namespace["keycode"] = self.currentView.keycode
        self.namespace["scrollwheel"] = self.currentView.scrollwheel
        self.namespace["wheeldelta"] = self.currentView.wheeldelta

        # Reset the context
        self.context._resetContext()

        # Initalize the magicvar
        self.namespace[MAGICVAR] = self.magicvar

        # Set the pagenum
        self.namespace['PAGENUM'] = self._pageNumber
        
        # Set the frame
        self.namespace['FRAME'] = self._frame

        # Run the script
        success, output = self.boxedRun_args_(fn, args)
        self.flushOutput_(output)
        if not success:
            return False

        # Display the output of the script
        self.currentView.setCanvas_(self.canvas)

        return True
        

    @objc.IBAction
    def clearMessageArea_(self, sender):
        # pp( dir(self.outputView.textStorage()))
        self.outputView.textStorage().mutableString().setString_(u"")

    @objc.IBAction
    def runFullscreen_(self, sender):
        if self.fullScreen is not None:
            return
        # self.clearMessageArea_( None )
        self.stopScript()
        self.currentView = FullscreenView.alloc().init()
        self.currentView.canvas = None
        fullRect = NSScreen.mainScreen().frame()
        self.fullScreen = FullscreenWindow.alloc().initWithRect_(fullRect)
        self.fullScreen.setContentView_(self.currentView)
        self.fullScreen.makeKeyAndOrderFront_(self)
        self.fullScreen.makeFirstResponder_(self.currentView)
        NSMenu.setMenuBarVisible_(False)
        NSCursor.hide()
        self._runScript()

    @objc.IBAction
    def runScript_(self, sender):
        # self.clearMessageArea_( None )
        self.runScript()
        
    def runScript(self, compile=True, newSeed=True):
        if self.fullScreen is not None: return
        self.currentView = self.graphicsView
        self._runScript(compile, newSeed)

    def _runScript(self, compile=True, newSeed=True):
        if not self.cleanRun_newSeed_buildInterface_(self._execScript, True, True):
            pass

        # Check whether we are dealing with animation
        if self.canvas.speed is not None:
            if not self.namespace.has_key("draw"):
                errorAlert("Not a proper NodeBox animation",
                    "NodeBox animations should have at least a draw() method.")
                return

            # Check if animationTimer is already running
            if self.animationTimer is not None:
                self.stopScript()

            self.speed = self.canvas.speed

            # Run setup routine
            if self.namespace.has_key("setup"):
                self.fastRun_newSeed_(self.namespace["setup"], False)
            window = self.currentView.window()
            window.makeFirstResponder_(self.currentView)

            # Start the timer
            timer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_
            self.animationTimer = timer(1.0 / self.speed,
                                        self,
                                        objc.selector(self.doFrame, signature="v@:@"),
                                        None,
                                        True)

            # Start the spinner
            self.animationSpinner.startAnimation_(None)

    def runScriptFast(self):        
        if self.animationTimer is None:
            self.fastRun_newSeed_(self._execScript, False)
        else:
            # XXX: This can be sped up. We just run _execScript to get the
            # method with __MAGICVAR__ into the namespace, and execute
            # that, so it should only be called once for animations.
            self.fastRun_newSeed_(self._execScript, False)
            self.fastRun_newSeed_(self.namespace["draw"], False)

    def doFrame(self):
        self.fastRun_newSeed_(self.namespace["draw"], True)
        self._frame += 1
        
    def source(self):
        return self.textView.string()

    def setSource_(self, source):
        self.textView.setString_(source)

    @objc.IBAction
    def stopScript_(self, sender=None):
        self.stopScript()
        
    def stopScript(self):
        if self.namespace.has_key("stop"):
            success, output = self.boxedRun_args_(self.namespace["stop"], [])
            self.flushOutput_(output)
        self.animationSpinner.stopAnimation_(None)
        if self.animationTimer is not None:
            self.animationTimer.invalidate()
            self.animationTimer = None
        if self.fullScreen is not None:
            self.currentView = self.graphicsView
            self.fullScreen = None
            NSMenu.setMenuBarVisible_(True)
        NSCursor.unhide()
        self.textView.hideValueLadder()
        window = self.textView.window()
        window.makeFirstResponder_(self.textView)

    def _compileScript(self, source=None):
        if source is None:
            source = self.textView.string()

        # if this is activated, all unicode carrying scripts NEED a "encoding" line
        # OTOH if this is on, NB accepts scripts with an encoding line.
        # currently an error
        # source = source.encode("utf-8")
        self._code = None
        self._code = compile(source + "\n\n",
                             self.scriptName.encode('ascii', 'ignore'),
                             "exec")

    def _initNamespace(self):

        self.namespace.clear()
        # Add everything from the namespace
        for name in graphics.__all__:<commit_msg>Formatting<commit_after>import sys
import os
import traceback, linecache
import re
import objc
import time
import random
import signal
import atexit

import pprint
pp = pprint.pprint

import pdb

kwdbg = False

# set to true to have stdio on the terminal for pdb
debugging = False

# if true print out some debug info on stdout
kwlog = False

import Foundation
import AppKit
NSObject = AppKit.NSObject
NSColor = AppKit.NSColor
NSScriptCommand = AppKit.NSScriptCommand

NSDocument = AppKit.NSDocument
NSDocumentController = AppKit.NSDocumentController

NSNotificationCenter = AppKit.NSNotificationCenter

NSFontAttributeName = AppKit.NSFontAttributeName
NSScreen = AppKit.NSScreen
NSMenu = AppKit.NSMenu
NSCursor = AppKit.NSCursor
NSTimer = AppKit.NSTimer
NSForegroundColorAttributeName = AppKit.NSForegroundColorAttributeName

NSPasteboard = AppKit.NSPasteboard
NSPDFPboardType = AppKit.NSPDFPboardType
NSPostScriptPboardType = AppKit.NSPostScriptPboardType
NSTIFFPboardType = AppKit.NSTIFFPboardType

NSBundle = AppKit.NSBundle
NSSavePanel = AppKit.NSSavePanel
NSLog = AppKit.NSLog
NSApp = AppKit.NSApp
NSPrintOperation = AppKit.NSPrintOperation
NSWindow = AppKit.NSWindow
NSBorderlessWindowMask = AppKit.NSBorderlessWindowMask
NSBackingStoreBuffered = AppKit.NSBackingStoreBuffered
NSView = AppKit.NSView
NSGraphicsContext = AppKit.NSGraphicsContext
NSRectFill = AppKit.NSRectFill
NSAffineTransform = AppKit.NSAffineTransform
NSFocusRingTypeExterior = AppKit.NSFocusRingTypeExterior
NSResponder = AppKit.NSResponder

NSURL = AppKit.NSURL
NSWorkspace = AppKit.NSWorkspace
NSBezierPath = AppKit.NSBezierPath


import threading
Thread = threading.Thread

import ValueLadder
MAGICVAR = ValueLadder.MAGICVAR

import PyDETextView

import preferences
NodeBoxPreferencesController = preferences.NodeBoxPreferencesController
LibraryFolder = preferences.LibraryFolder

import util
errorAlert = util.errorAlert


# from nodebox import util
import nodebox.util
util = nodebox.util
makeunicode = nodebox.util.makeunicode

import nodebox.util.ottobot
genProgram = nodebox.util.ottobot.genProgram


import nodebox.util.QTSupport
QTSupport = nodebox.util.QTSupport

# from nodebox import graphics
import nodebox.graphics
graphics = nodebox.graphics

# AppleScript enumerator codes for PDF and Quicktime export
PDF = 0x70646678 # 'pdfx'
QUICKTIME = 0x71747878 # 'qt  '


black = NSColor.blackColor()
VERY_LIGHT_GRAY = black.blendedColorWithFraction_ofColor_(0.95,
                                                          NSColor.whiteColor())
DARKER_GRAY = black.blendedColorWithFraction_ofColor_(0.8,
                                                      NSColor.whiteColor())

# from nodebox.gui.mac.dashboard import *
# from nodebox.gui.mac.progressbar import ProgressBarController
import dashboard
DashboardController = dashboard.DashboardController

import progressbar
ProgressBarController = progressbar.ProgressBarController

class ExportCommand(NSScriptCommand):
    pass    

class OutputFile(object):

    def __init__(self, data, isErr=False):
        self.data = data
        self.isErr = isErr

    def write(self, data):
        if isinstance(data, str):
            try:
                data = unicode(data, "utf_8", "replace")
            except UnicodeDecodeError:
                data = "XXX " + repr(data)
        self.data.append((self.isErr, data))



# class defined in NodeBoxDocument.xib
class NodeBoxDocument(NSDocument):

    graphicsView = objc.IBOutlet()
    outputView = objc.IBOutlet() 
    textView = objc.IBOutlet()
    window = objc.IBOutlet()
    variablesController = objc.IBOutlet()
    dashboardController = objc.IBOutlet()
    animationSpinner = objc.IBOutlet()

    # The ExportImageAccessory adds:
    exportImageAccessory = objc.IBOutlet()
    exportImageFormat = objc.IBOutlet()
    exportImagePageCount = objc.IBOutlet()

    # The ExportMovieAccessory adds:
    exportMovieAccessory = objc.IBOutlet()
    exportMovieFrames = objc.IBOutlet()
    exportMovieFps = objc.IBOutlet()

    # When the PageCount accessory is loaded, we also add:
    pageCount = objc.IBOutlet()
    pageCountAccessory = objc.IBOutlet()

    # When the ExportSheet is loaded, we also add:
    exportSheet = objc.IBOutlet()
    exportSheetIndicator = objc.IBOutlet()

    path = None
    exportDir = None
    magicvar = None # Used for value ladders.
    _code = None
    vars = []
    movie = None

    def windowNibName(self):
        return "NodeBoxDocument"

    def init(self):
        self = super(NodeBoxDocument, self).init()
        nc = NSNotificationCenter.defaultCenter()
        nc.addObserver_selector_name_object_(self,
                                             "textFontChanged:",
                                             "PyDETextFontChanged",
                                             None)
        self.namespace = {}
        self.canvas = graphics.Canvas()
        self.context = graphics.Context(self.canvas, self.namespace)
        self.animationTimer = None
        self.__doc__ = {}
        self._pageNumber = 1
        self._frame = 150
        self.fullScreen = None
        self._seed = time.time()

        # this is None
        self.currentView = self.graphicsView
        return self

    def autosavesInPlace(self):
        return True

    def close(self):
        self.stopScript()
        super(NodeBoxDocument, self).close()

    def __del__(self):
        nc = NSNotificationCenter.defaultCenter()
        nc.removeObserver_name_object_(self, "PyDETextFontChanged", None)
        # text view has a couple of circular refs, it can let go of them now
        self.textView._cleanup()

    def textFontChanged_(self, notification):
        font = PyDETextView.getBasicTextAttributes()[NSFontAttributeName]
        self.outputView.setFont_(font)

    def readFromFile_ofType_(self, path, tp):
        if self.textView is None:
            # we're not yet fully loaded
            self.path = path
        else:
            # "revert"
            self.readFromUTF8_(path)
        return True

    def writeToFile_ofType_(self, path, tp):
        f = file(path, "w")
        text = self.textView.string()
        f.write(text.encode("utf8"))
        f.close()
        return True

    def windowControllerDidLoadNib_(self, controller):
        if self.path:
            self.readFromUTF8_(self.path)
        font = PyDETextView.getBasicTextAttributes()[NSFontAttributeName]
        self.outputView.setFont_(font)
        self.textView.window().makeFirstResponder_(self.textView)
        self.windowControllers()[0].setWindowFrameAutosaveName_("NodeBoxDocumentWindow")

        # switch off automatic substitutions
        try:
            self.textView.setAutomaticQuoteSubstitutionEnabled_( False )
            self.textView.setAutomaticDashSubstitutionEnabled_( False )

            # This does not work well with syntax coloring
            #self.textView.setAutomaticLinkDetectionEnabled_( True )
            #self.textView.setDisplaysLinkToolTips_( True )

            self.outputView.setAutomaticQuoteSubstitutionEnabled_( False )
            self.outputView.setAutomaticDashSubstitutionEnabled_( False )
            #self.outputView.setAutomaticLinkDetectionEnabled_( True )
            #self.outputView.setDisplaysLinkToolTips_( True )
        except Exception, err:
            pass

    def readFromUTF8_(self, path):
        f = file(path)
        text = unicode(f.read(), "utf_8")
        f.close()
        self.textView.setString_(text)
        self.textView.usesTabs = "\t" in text
        
    def cleanRun_newSeed_buildInterface_(self, fn, newSeed, buildInterface):
        self.animationSpinner.startAnimation_(None)

        # Prepare everything for running the script
        self.prepareRun()

        # Run the actual script
        success = self.fastRun_newSeed_(fn, newSeed)
        self.animationSpinner.stopAnimation_(None)

        if success and buildInterface:

            # Build the interface
            self.vars = self.namespace["_ctx"]._vars
            if len(self.vars) > 0:
                self.buildInterface_(None)

        return success

    def prepareRun(self):

        # Compile the script
        success, output = self.boxedRun_args_(self._compileScript, [])
        self.flushOutput_(output)
        if not success:
            return False

        # Initialize the namespace
        self._initNamespace()
        
        # Reset the pagenum
        self._pageNum = 1
        
        # Reset the frame
        self._frame = 1

        self.speed = self.canvas.speed = None

    def fastRun_newSeed_(self, fn, newSeed = False):
        """This is the old signature. Dispatching to the new with args"""
        return self.fastRun_newSeed_args_( fn, newSeed, [])


    def fastRun_newSeed_args_(self, fn, newSeed = False, args=[]):
        # Check if there is code to run
        if self._code is None:
            return False

        # Clear the canvas
        self.canvas.clear()

        # Generate a new seed, if needed
        if newSeed:
            self._seed = time.time()
        random.seed(self._seed)

        # Set the mouse position
        
        # kw fix
        if not self.currentView:
            self.currentView = self.graphicsView

        window = self.currentView.window()
        pt = window.mouseLocationOutsideOfEventStream()
        mx, my = window.contentView().convertPoint_toView_(pt, self.currentView)
        # Hack: mouse coordinates are flipped vertically in FullscreenView.
        # This flips them back.
        if isinstance(self.currentView, FullscreenView):
            my = self.currentView.bounds()[1][1] - my
        if self.fullScreen is None:
            mx /= self.currentView.zoom
            my /= self.currentView.zoom
        self.namespace["MOUSEX"], self.namespace["MOUSEY"] = mx, my
        self.namespace["mousedown"] = self.currentView.mousedown
        self.namespace["keydown"] = self.currentView.keydown
        self.namespace["key"] = self.currentView.key
        self.namespace["keycode"] = self.currentView.keycode
        self.namespace["scrollwheel"] = self.currentView.scrollwheel
        self.namespace["wheeldelta"] = self.currentView.wheeldelta

        # Reset the context
        self.context._resetContext()

        # Initalize the magicvar
        self.namespace[MAGICVAR] = self.magicvar

        # Set the pagenum
        self.namespace['PAGENUM'] = self._pageNumber
        
        # Set the frame
        self.namespace['FRAME'] = self._frame

        # Run the script
        success, output = self.boxedRun_args_(fn, args)
        self.flushOutput_(output)
        if not success:
            return False

        # Display the output of the script
        self.currentView.setCanvas_(self.canvas)

        return True
        

    @objc.IBAction
    def clearMessageArea_(self, sender):
        # pp( dir(self.outputView.textStorage()))
        self.outputView.textStorage().mutableString().setString_(u"")

    @objc.IBAction
    def runFullscreen_(self, sender):
        if self.fullScreen is not None:
            return
        # self.clearMessageArea_( None )
        self.stopScript()
        self.currentView = FullscreenView.alloc().init()
        self.currentView.canvas = None
        fullRect = NSScreen.mainScreen().frame()
        self.fullScreen = FullscreenWindow.alloc().initWithRect_(fullRect)
        self.fullScreen.setContentView_(self.currentView)
        self.fullScreen.makeKeyAndOrderFront_(self)
        self.fullScreen.makeFirstResponder_(self.currentView)
        NSMenu.setMenuBarVisible_(False)
        NSCursor.hide()
        self._runScript()

    @objc.IBAction
    def runScript_(self, sender):
        # self.clearMessageArea_( None )
        self.runScript()
        
    def runScript(self, compile=True, newSeed=True):
        if self.fullScreen is not None: return
        self.currentView = self.graphicsView
        self._runScript(compile, newSeed)

    def _runScript(self, compile=True, newSeed=True):
        if not self.cleanRun_newSeed_buildInterface_(self._execScript, True, True):
            pass

        # Check whether we are dealing with animation
        if self.canvas.speed is not None:
            if not self.namespace.has_key("draw"):
                errorAlert("Not a proper NodeBox animation",
                    "NodeBox animations should have at least a draw() method.")
                return

            # Check if animationTimer is already running
            if self.animationTimer is not None:
                self.stopScript()

            self.speed = self.canvas.speed

            # Run setup routine
            if self.namespace.has_key("setup"):
                self.fastRun_newSeed_(self.namespace["setup"], False)
            window = self.currentView.window()
            window.makeFirstResponder_(self.currentView)

            # Start the timer
            timer = NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_
            self.animationTimer = timer(1.0 / self.speed,
                                        self,
                                        objc.selector(self.doFrame, signature="v@:@"),
                                        None,
                                        True)

            # Start the spinner
            self.animationSpinner.startAnimation_(None)

    def runScriptFast(self):        
        if self.animationTimer is None:
            self.fastRun_newSeed_(self._execScript, False)
        else:
            # XXX: This can be sped up. We just run _execScript to get the
            # method with __MAGICVAR__ into the namespace, and execute
            # that, so it should only be called once for animations.
            self.fastRun_newSeed_(self._execScript, False)
            self.fastRun_newSeed_(self.namespace["draw"], False)

    def doFrame(self):
        self.fastRun_newSeed_(self.namespace["draw"], True)
        self._frame += 1
        
    def source(self):
        return self.textView.string()

    def setSource_(self, source):
        self.textView.setString_(source)

    @objc.IBAction
    def stopScript_(self, sender=None):
        self.stopScript()
        
    def stopScript(self):
        if self.namespace.has_key("stop"):
            success, output = self.boxedRun_args_(self.namespace["stop"], [])
            self.flushOutput_(output)
        self.animationSpinner.stopAnimation_(None)
        if self.animationTimer is not None:
            self.animationTimer.invalidate()
            self.animationTimer = None
        if self.fullScreen is not None:
            self.currentView = self.graphicsView
            self.fullScreen = None
            NSMenu.setMenuBarVisible_(True)
        NSCursor.unhide()
        self.textView.hideValueLadder()
        window = self.textView.window()
        window.makeFirstResponder_(self.textView)

    def _compileScript(self, source=None):
        if source is None:
            source = self.textView.string()

        # if this is activated, all unicode carrying scripts NEED a "encoding"
        # line
        # OTOH if this is on, NB accepts scripts with an encoding line.
        # currently an error
        # source = source.encode("utf-8")
        self._code = None
        self._code = compile(source + "\n\n",
                             self.scriptName.encode('ascii', 'ignore'),
                             "exec")

    def _initNamespace(self):

        self.namespace.clear()
        # Add everything from the namespace
        for name in graphics.__all__:
{'fraction_non_alphanumeric': 0.08150812512043162, 'fraction_numerical': 0.002761898644742758, 'mean_word_length': 2.402425699300699, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '489318', 'n_tokens_mistral': 8789, 'n_tokens_neox': 8512, 'n_words': 1983}