git.s-ol.nu watch-cad / master session.moon
master

Tree @master (Download .tar.gz)

session.moon @masterraw · history · blame

lfs = require 'lfs'
utf8 = require 'utf8'
moon = require 'moonscript.base'

{ graphics: lg } = love
trace = (msg) -> debug.traceback msg, 2

class Script
  new: (file='scratch.moon') =>
    @file = "library/#{file}"
    @last_modification = 0
    @func = ->

  commit: =>
    export COMMIT
    COMMIT = true

    return unless @func

    ok, msg = xpcall @func, trace, STATE.root
    if not ok
      @error = at: 'commit', :msg
      return

    COMMIT = false

  reload_and_run: =>
    func = @reload!
    @func = func if func

    ok, msg = xpcall @func, trace, STATE.root
    if not ok
      @error = at: 'exec', :msg

    @print_error!

  print_error: =>
    if @error
      switch @error.at
        when 'parse'  do print "--- ERROR PARSING SCRIPT #{@file} ---"
        when 'load'   do print "--- ERROR LOADING SCRIPT: #{@file} ---"
        when 'exec'   do print "--- ERROR EXECUTING SCRIPT: #{@file} ---"
        when 'commit' do print "--- ERROR COMMITTING SCRIPT: #{@file} ---"

      print @error.msg

  reload: =>
    { :mode, :modification } = (lfs.attributes @file) or {}
    if mode != 'file'
      @error = at: 'parse', msg: "script doesn't exist or is not a file: '#{@file}'"
      return

    if @last_modification < modification
      @last_modification = modification
      module, msg = if @file\match '%.moon$' then moon.loadfile @file else loadfile @file
      if not module
        @error = at: 'parse', :msg
        return

      ok, msg = xpcall module, trace
      if not msg
        @error = at: 'load', :msg
        return

      @error = nil
      msg

import Object from require 'object'

class Session
  FONTSIZE = 20
  new: (scriptfile) =>
    @objects = {}

    if scriptfile
      @script = Script scriptfile

    @font = lg.newFont 'font/FantasqueSansMono-Regular.ttf', 20
    @ex = false

  exec: (command) =>
    switch command\match '^(%w+)'
      when 'quit'
        love.event.quit!
      when 'run'
        arg = command\match '^run%s+(.+)'
        @script = Script arg

  frame: =>
    lg.setColor 1, 1, 1
    for obj in *@objects
      obj\draw!

    if INPUT\key_down 'escape'
      STATE\reset!

    w,h = lg.getDimensions!
    lg.setFont @font

    if @script
      lg.setColor .5, .5, .5
      depth = lg.getStackDepth!

      @script\reload_and_run!

      if INPUT\key_down 'space'
        @script\commit!
        STATE\reset!

      while lg.getStackDepth! > depth
        lg.pop!
        
      lg.setColor 1, 1, 1
      lg.print "script: #{@script.file}", 10, 10

    if (INPUT\key_down ':') or (INPUT\key_down ';') and INPUT\key_held 'lshift'
      INPUT\text_capture!
      @ex = true

    if @ex
      lg.setColor 1, 1, 1
      lg.print ":#{INPUT.text}", 10, h - 10 - FONTSIZE
      
      apply = INPUT\key_down 'return'
      input = if apply or INPUT\key_down 'escape'
        @ex = nil
        apply and @exec INPUT\text_release!

      @exec input if input

{
  :Script
  :Session
}