<commit_before>documentation = """
============
RoboREPL 0.1
============

An interactive Python interpreter for RoboFont.
You type some code in it and it will be executed.

Namespace Injections
--------------------
help : This.
settings : An editor settings manager. Type "settings.help" for documentation.
""".strip()

# This was inspired by the PyObjC Interpreter demo.

import sys
from code import InteractiveConsole
from defcon.tools.notifications import NotificationCenter
from AppKit import *
import vanilla
from vanilla.vanillaTextEditor import VanillaTextEditorDelegate
from defconAppKit.windows.baseWindow import BaseWindowController

try:
    sys.ps1
except AttributeError:
    sys.ps1 = ">>> "
try:
    sys.ps2
except AttributeError:
    sys.ps2 = "... "

try:
    import mojo
    inRoboFont = True
except ImportError:
    inRoboFont = False

# --------
# Settings
# --------

defaultStartupCode = """
# This script will be executed when the interpreter is started.
# It will be executed in the same namespace as your later code
# will be executed in, so you can define variables, import
# modules and anything else that you want.
""".lstrip()

if inRoboFont:
    defaultStartupCode += """
CF = CurrentFont
CG = CurrentGlyph
AF = AllFonts
OF = OpenFont
NF = NewFont
"""

defaultSettings = dict(
    bannerGreeting="Welcome to RoboREPL! Type \"help\" for help.",
    windowWidth=80,
    windowHeight=24,
    tabString="  ",
    fontName="Menlo-Regular",
    fontSize=20,
    startupCode=defaultStartupCode,
    userThemes={}
)

defaultThemes = dict(
    default=dict(
        colorCode=(0, 0, 0, 1),
        colorStderr=(1, 0, 0, 1),
        colorStdout=(0, 0, 1, 1),
        colorBackground=(1, 1, 1, 1)
    ),
    classic=dict(
        colorCode=(0, 1, 0, 1),
        colorStderr=(1, 0, 0, 1),
        colorStdout=(1, 1, 1, 1),
        colorBackground=(0, 0, 0, 0.8)
    ),
    robofog=dict(
        colorCode=(0, 0, 0, 1),
        colorStderr=(0, 0, 0, 1),
        colorStdout=(0, 0, 0, 1),
        colorBackground=(1, 1, 1, 1)
    )
)

defaultSettings.update(defaultThemes["default"])


class PyREPLSettingsError(Exception): pass


def settingsStringValidator(value):
    return isinstance(value, basestring)

def settingsNumberValidator(value):
    return isinstance(value, (int, float))

def settingsPositiveNumberValidator(value):
    if not settingsNumberValidator(value):
        return False
    return value >= 0

def settingsWindowSizeValidator(value):
    if not isinstance(value, int):
        return False
    return value > 0

def settingsColorValidator(value):
    if not isinstance(value, (tuple, list)):
        return False
    if len(value) != 4:
        return False
    for v in value:
        if not settingsPositiveNumberValidator(v):
            return False
        if v < 0 or v > 1:
            return False
    return True

class settingsProperty(object):

    def __init__(self, key, validator=None, doc=""):
        self.key = key
        self.validator = validator
        self.__doc__ = doc

    def __get__(self, obj, cls):
        return getDefaultValue(self.key)

    def __set__(self, obj, value):
        if self.validator is not None:
            valid = self.validator(value)
            if not valid:
                raise PyREPLSettingsError("%s must be the right value type." % self.key)
        setDefaultValue(self.key, value)
        obj.postNotification(data={self.key : value})


settingsManagerDoc = """
=========================
RoboREPL Settings Manager
=========================

Attributes
----------
help : This.
tabString : Whitespace to insert when the tab key is pressed. Must be a string.
windowWidth : The number of characters per line. Must be a positive integer.
windowHeight : The number of rows per window. Must be a positive integer.
fontName : The font name. Must be a string.
fontSize : The font size. Must be a positive number.
colorCode : The color for code text. Must be a color tuple.
colorStdout : The color for stdout text. Must be a color tuple*.
colorStderr : The color for stderr text. Must be a color tuple*.
colorBackground : The background color. Must be a color tuple*.
bannerGreeting** : The message displayed at startup. Must be a string.
startupCode** : Python code to be executed at startup. Must be a string.
availableFonts : Names of avaiable monospaced fonts. This is read only.

Methods
-------
editStartupCode() : Edit the startup code.
loadTheme("name") : Load a theme. The defaults are "default", "classic" and "robofog".
saveTheme("name") : Save the current theme. This can then be loaded with "settings.loadTheme".

*Color tuples are tuples containing four positive numbers between 0 and 1.
**Only applies to new windows.
""".strip()


class PyREPLSettings(object):<commit_msg>Better documentation.<commit_after>documentation = """
============
RoboREPL 0.1
============

An interactive Python interpreter for RoboFont.
You type some code in it and it will be executed.

To get help, type `help`, but you already figured that out.
To learn about changing settings, type `settings.help`.
""".strip()

# This was inspired by the PyObjC Interpreter demo.

import sys
from code import InteractiveConsole
from defcon.tools.notifications import NotificationCenter
from AppKit import *
import vanilla
from vanilla.vanillaTextEditor import VanillaTextEditorDelegate
from defconAppKit.windows.baseWindow import BaseWindowController

try:
    sys.ps1
except AttributeError:
    sys.ps1 = ">>> "
try:
    sys.ps2
except AttributeError:
    sys.ps2 = "... "

try:
    import mojo
    inRoboFont = True
except ImportError:
    inRoboFont = False

# --------
# Settings
# --------

defaultStartupCode = """
# This script will be executed when the interpreter is started.
# It will be executed in the same namespace as your later code
# will be executed in, so you can define variables, import
# modules and anything else that you want.
""".lstrip()

if inRoboFont:
    defaultStartupCode += """
CF = CurrentFont
CG = CurrentGlyph
AF = AllFonts
OF = OpenFont
NF = NewFont
"""

defaultSettings = dict(
    bannerGreeting="Welcome to RoboREPL! Type \"help\" for help.",
    windowWidth=80,
    windowHeight=24,
    tabString="  ",
    fontName="Menlo-Regular",
    fontSize=20,
    startupCode=defaultStartupCode,
    userThemes={}
)

defaultThemes = dict(
    default=dict(
        colorCode=(0, 0, 0, 1),
        colorStderr=(1, 0, 0, 1),
        colorStdout=(0, 0, 1, 1),
        colorBackground=(1, 1, 1, 1)
    ),
    classic=dict(
        colorCode=(0, 1, 0, 1),
        colorStderr=(1, 0, 0, 1),
        colorStdout=(1, 1, 1, 1),
        colorBackground=(0, 0, 0, 0.8)
    ),
    robofog=dict(
        colorCode=(0, 0, 0, 1),
        colorStderr=(0, 0, 0, 1),
        colorStdout=(0, 0, 0, 1),
        colorBackground=(1, 1, 1, 1)
    )
)

defaultSettings.update(defaultThemes["default"])


class PyREPLSettingsError(Exception): pass


def settingsStringValidator(value):
    return isinstance(value, basestring)

def settingsNumberValidator(value):
    return isinstance(value, (int, float))

def settingsPositiveNumberValidator(value):
    if not settingsNumberValidator(value):
        return False
    return value >= 0

def settingsWindowSizeValidator(value):
    if not isinstance(value, int):
        return False
    return value > 0

def settingsColorValidator(value):
    if not isinstance(value, (tuple, list)):
        return False
    if len(value) != 4:
        return False
    for v in value:
        if not settingsPositiveNumberValidator(v):
            return False
        if v < 0 or v > 1:
            return False
    return True

class settingsProperty(object):

    def __init__(self, key, validator=None, doc=""):
        self.key = key
        self.validator = validator
        self.__doc__ = doc

    def __get__(self, obj, cls):
        return getDefaultValue(self.key)

    def __set__(self, obj, value):
        if self.validator is not None:
            valid = self.validator(value)
            if not valid:
                raise PyREPLSettingsError("%s must be the right value type." % self.key)
        setDefaultValue(self.key, value)
        obj.postNotification(data={self.key : value})


settingsManagerDoc = """
=================
RoboREPL Settings
=================

All settings are handled through the `settings` object.
You get a setting like this:

>>> settings.fontSize
20

You set a settings like this:

>>> settings.fontSize = 15

Available Settings
------------------

- Window Settings
settings.windowWidth : The number of characters per line. Must be a positive integer.
settings.windowHeight : The number of rows per window. Must be a positive integer.

- Fonts
settings.fontName : The font name. Must be a string.
settings.fontSize : The font size. Must be a positive number.
settings.availableFonts : Names of installed monospaced fonts. This is read only.

- Colors
settings.colorCode : The color for code text. Must be a color tuple.
settings.colorStdout : The color for stdout text. Must be a color tuple*.
settings.colorStderr : The color for stderr text. Must be a color tuple*.
settings.colorBackground : The background color. Must be a color tuple*.

- Themes
loadTheme("name") : Load a theme. The defaults are "default", "classic" and "robofog".
saveTheme("name") : Save the current theme. This can then be loaded with "settings.loadTheme".

- Text
settings.tabString : Whitespace to insert when the tab key is pressed. Must be a string.
settings.bannerGreeting** : The message displayed at startup. Must be a string.

- Startup Code
settings.startupCode** : Python code to be executed at startup. Must be a string.
editStartupCode() : Edit the startup code.

*Color tuples are tuples containing four positive numbers between 0 and 1.
**Only applies to new windows.

Example
-------
>>> settings.loadTheme("classic")
>>> settings.colorCode = (0, 0, 1, 1)
>>> settings.colorStdrr
(1, 0, 0, 1)
>>> settings.saveTheme("mine")
>>> settings.availableFonts
Menlo-Regular
MyOwnMono-Regular
>>> settings.fontName = "MyOwnMono-Regular"
>>> settings.fontSize
20
>>> settings.fontSize = 12
""".strip()


class PyREPLSettings(object):
{'fraction_non_alphanumeric': 0.11621966794380588, 'fraction_numerical': 0.014932704587877002, 'mean_word_length': 3.243434764485202, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2959704', 'n_tokens_mistral': 3062, 'n_tokens_neox': 2917, 'n_words': 1072}