aboutsummaryrefslogtreecommitdiffstats
path: root/session.moon
blob: a4ad5e7000daf049d1d610fbb9957a965122954a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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
}