carps 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +674 -0
- data/GEM_DESCRIPTION +10 -0
- data/History.txt +4 -0
- data/Manifest.txt +156 -0
- data/PostInstall.txt +20 -0
- data/README.rdoc +141 -0
- data/Rakefile +28 -0
- data/bin/carps +123 -0
- data/bin/carps_init +29 -0
- data/bin/carps_ipc_test +44 -0
- data/bin/carps_mod_saver_test +71 -0
- data/bin/carps_mod_test +62 -0
- data/config/website.yml +2 -0
- data/features/character_sheet.feature +40 -0
- data/features/crash.feature +15 -0
- data/features/crypt.feature +22 -0
- data/features/dice.feature +173 -0
- data/features/dm.feature +36 -0
- data/features/dmll.feature +51 -0
- data/features/edit.feature +10 -0
- data/features/email.feature +29 -0
- data/features/interface.feature +17 -0
- data/features/ipc.feature +10 -0
- data/features/mailbox.feature +33 -0
- data/features/mod.feature +31 -0
- data/features/parser.feature +9 -0
- data/features/persistent_protocol.feature +14 -0
- data/features/player.feature +22 -0
- data/features/player_turn.feature +29 -0
- data/features/random.feature +15 -0
- data/features/rule.feature +19 -0
- data/features/safety.feature +13 -0
- data/features/sessions.feature +16 -0
- data/features/start_dm.feature +18 -0
- data/features/start_player.feature +8 -0
- data/features/step_definitions/common_steps.rb +170 -0
- data/features/steps/character_sheet.rb +89 -0
- data/features/steps/crash.rb +27 -0
- data/features/steps/crypt.rb +166 -0
- data/features/steps/dice.rb +91 -0
- data/features/steps/dm.rb +147 -0
- data/features/steps/dmll.rb +47 -0
- data/features/steps/edit.rb +7 -0
- data/features/steps/email.rb +108 -0
- data/features/steps/general.rb +5 -0
- data/features/steps/interface.rb +64 -0
- data/features/steps/ipc.rb +22 -0
- data/features/steps/mailbox.rb +126 -0
- data/features/steps/mod.rb +25 -0
- data/features/steps/parser.rb +23 -0
- data/features/steps/persistent_protocol.rb +29 -0
- data/features/steps/player.rb +82 -0
- data/features/steps/player_turn.rb +56 -0
- data/features/steps/random.rb +47 -0
- data/features/steps/rule.rb +53 -0
- data/features/steps/safety.rb +17 -0
- data/features/steps/sessions.rb +37 -0
- data/features/steps/start_dm.rb +46 -0
- data/features/steps/start_player.rb +65 -0
- data/features/steps/timeout.rb +32 -0
- data/features/steps/type_verification.rb +36 -0
- data/features/steps/wizard.rb +123 -0
- data/features/support/common.rb +29 -0
- data/features/support/env.rb +14 -0
- data/features/support/matchers.rb +11 -0
- data/features/timeout.feature +11 -0
- data/features/type_verification.feature +48 -0
- data/features/wizard.feature +50 -0
- data/lib/carps/crypt/accept_handshake.rb +40 -0
- data/lib/carps/crypt/default_messages.rb +29 -0
- data/lib/carps/crypt/handshake.rb +41 -0
- data/lib/carps/crypt/mailbox.rb +265 -0
- data/lib/carps/crypt/mailer.rb +220 -0
- data/lib/carps/crypt/peer.rb +123 -0
- data/lib/carps/crypt/public_key.rb +60 -0
- data/lib/carps/crypt.rb +23 -0
- data/lib/carps/email/config.rb +122 -0
- data/lib/carps/email/imap.rb +156 -0
- data/lib/carps/email/smtp.rb +119 -0
- data/lib/carps/email/string.rb +30 -0
- data/lib/carps/email.rb +21 -0
- data/lib/carps/mod/action.rb +36 -0
- data/lib/carps/mod/answers.rb +76 -0
- data/lib/carps/mod/client_turn.rb +88 -0
- data/lib/carps/mod/dice.rb +360 -0
- data/lib/carps/mod/dm/interface.rb +160 -0
- data/lib/carps/mod/dm/mod.rb +409 -0
- data/lib/carps/mod/dm/reporter.rb +112 -0
- data/lib/carps/mod/dm/resource.rb +88 -0
- data/lib/carps/mod/dm/room.rb +33 -0
- data/lib/carps/mod/interface.rb +73 -0
- data/lib/carps/mod/launch.rb +108 -0
- data/lib/carps/mod/mod.rb +52 -0
- data/lib/carps/mod/player/interface.rb +76 -0
- data/lib/carps/mod/player/mod.rb +109 -0
- data/lib/carps/mod/question.rb +63 -0
- data/lib/carps/mod/rule.rb +112 -0
- data/lib/carps/mod/sheet/character.rb +82 -0
- data/lib/carps/mod/sheet/editor.rb +97 -0
- data/lib/carps/mod/sheet/new_sheet.rb +71 -0
- data/lib/carps/mod/sheet/schema.rb +84 -0
- data/lib/carps/mod/sheet/type.rb +161 -0
- data/lib/carps/mod/sheet/verifier.rb +41 -0
- data/lib/carps/mod/status_report.rb +51 -0
- data/lib/carps/mod.rb +40 -0
- data/lib/carps/protocol/keyword.rb +104 -0
- data/lib/carps/protocol/message.rb +138 -0
- data/lib/carps/protocol.rb +19 -0
- data/lib/carps/service/client_parser.rb +34 -0
- data/lib/carps/service/dm/config.rb +76 -0
- data/lib/carps/service/dm/mailer.rb +70 -0
- data/lib/carps/service/dm/new_game.rb +101 -0
- data/lib/carps/service/dm/start.rb +47 -0
- data/lib/carps/service/game.rb +101 -0
- data/lib/carps/service/interface.rb +174 -0
- data/lib/carps/service/invite.rb +79 -0
- data/lib/carps/service/mod.rb +43 -0
- data/lib/carps/service/player/config.rb +78 -0
- data/lib/carps/service/player/mailer.rb +49 -0
- data/lib/carps/service/player/start.rb +60 -0
- data/lib/carps/service/server_parser.rb +33 -0
- data/lib/carps/service/session.rb +96 -0
- data/lib/carps/service/start/config.rb +71 -0
- data/lib/carps/service/start/interface.rb +101 -0
- data/lib/carps/service/start/mailer.rb +46 -0
- data/lib/carps/service.rb +35 -0
- data/lib/carps/test.rb +34 -0
- data/lib/carps/ui/colour.rb +28 -0
- data/lib/carps/ui/error.rb +39 -0
- data/lib/carps/ui/highlight.rb +32 -0
- data/lib/carps/ui/question.rb +63 -0
- data/lib/carps/ui/warn.rb +37 -0
- data/lib/carps/ui.rb +21 -0
- data/lib/carps/util/config.rb +162 -0
- data/lib/carps/util/editor.rb +147 -0
- data/lib/carps/util/error.rb +75 -0
- data/lib/carps/util/files.rb +48 -0
- data/lib/carps/util/init.rb +93 -0
- data/lib/carps/util/process.rb +150 -0
- data/lib/carps/util/timeout.rb +31 -0
- data/lib/carps/util/windows.rb +29 -0
- data/lib/carps/util.rb +24 -0
- data/lib/carps/wizard/dm.rb +41 -0
- data/lib/carps/wizard/player.rb +40 -0
- data/lib/carps/wizard/steps.rb +494 -0
- data/lib/carps/wizard/wizard.rb +126 -0
- data/lib/carps/wizard.rb +21 -0
- data/lib/carps.rb +45 -0
- data/permission +16 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/tasks/readme_site.rake +28 -0
- data/test/test_carps.rb +11 -0
- data/test/test_helper.rb +3 -0
- data/website/index.html +271 -0
- metadata +304 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/ui/colour"
|
|
19
|
+
|
|
20
|
+
module CARPS
|
|
21
|
+
|
|
22
|
+
module UI
|
|
23
|
+
|
|
24
|
+
# Output an error message
|
|
25
|
+
#
|
|
26
|
+
# If the second parameter is true, the error message will begin with
|
|
27
|
+
# "Error:"
|
|
28
|
+
def UI::put_error msg, default_error=true
|
|
29
|
+
h = HighLine.new
|
|
30
|
+
prelude = ""
|
|
31
|
+
if default_error
|
|
32
|
+
prelude = "Error: "
|
|
33
|
+
end
|
|
34
|
+
$stderr.write h.color("#{prelude}#{msg}", :error)
|
|
35
|
+
puts "\a"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "highline"
|
|
19
|
+
|
|
20
|
+
module CARPS
|
|
21
|
+
|
|
22
|
+
module UI
|
|
23
|
+
|
|
24
|
+
# Highlight text
|
|
25
|
+
def UI::highlight text
|
|
26
|
+
h = HighLine.new
|
|
27
|
+
puts h.color text, :magenta, :bold
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "highline"
|
|
19
|
+
|
|
20
|
+
require "carps/ui/colour"
|
|
21
|
+
|
|
22
|
+
module CARPS
|
|
23
|
+
|
|
24
|
+
module UI
|
|
25
|
+
|
|
26
|
+
# Because we mess with the modes, and we're meant to run in a safe environment, need to hack highline.
|
|
27
|
+
HighLine::SystemExtensions.module_eval do
|
|
28
|
+
def restore_mode
|
|
29
|
+
@state.untaint
|
|
30
|
+
system "stty #{@state}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Ask a question, return a boolean
|
|
35
|
+
def UI::confirm question
|
|
36
|
+
h = HighLine.new
|
|
37
|
+
resp = h.ask h.color("#{question}\n(Type anything beginning with y to accept)", :green)
|
|
38
|
+
resp[0] == "y"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Ask a question. Get a string for an answer
|
|
42
|
+
#
|
|
43
|
+
# Calls untaint on the answer
|
|
44
|
+
def UI::question msg
|
|
45
|
+
h = HighLine.new
|
|
46
|
+
res = h.ask h.color(msg, :green)
|
|
47
|
+
# Trust the user
|
|
48
|
+
res.untaint
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Ask a question and don't echo what is typed.
|
|
52
|
+
#
|
|
53
|
+
# Calls untaint on the password
|
|
54
|
+
def UI::secret msg
|
|
55
|
+
h = HighLine.new
|
|
56
|
+
ooh = h.ask(h.color(msg, :green)) {|q| q.echo = "*"}
|
|
57
|
+
h.untaint
|
|
58
|
+
ooh
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/ui/colour"
|
|
19
|
+
|
|
20
|
+
module CARPS
|
|
21
|
+
|
|
22
|
+
module UI
|
|
23
|
+
|
|
24
|
+
# Print a warning message to stderr
|
|
25
|
+
def UI::warn reason, *msgs
|
|
26
|
+
h = HighLine.new
|
|
27
|
+
$stderr.write h.color("Warning:\n", :warning)
|
|
28
|
+
$stderr.write h.color(reason + "\n", :warning)
|
|
29
|
+
msgs.each do |msg|
|
|
30
|
+
$stderr.write msg + "\n"
|
|
31
|
+
end
|
|
32
|
+
puts "\a"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
data/lib/carps/ui.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/ui/error"
|
|
19
|
+
require "carps/ui/warn"
|
|
20
|
+
require "carps/ui/question"
|
|
21
|
+
require "carps/ui/highlight"
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/util/error"
|
|
19
|
+
|
|
20
|
+
require "carps/ui/warn"
|
|
21
|
+
|
|
22
|
+
require "yaml"
|
|
23
|
+
|
|
24
|
+
module CARPS
|
|
25
|
+
|
|
26
|
+
# Configuration files that read yaml
|
|
27
|
+
class YamlConfig
|
|
28
|
+
|
|
29
|
+
# Should we fail hard, quiting the program?
|
|
30
|
+
def fail_hard fatal
|
|
31
|
+
@fatal = fatal
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Read a resource using the subclass' parse_yaml.
|
|
35
|
+
#
|
|
36
|
+
# Then load this resource using the subclass' load_resource
|
|
37
|
+
def read filepath
|
|
38
|
+
filepath = $CONFIG + filepath
|
|
39
|
+
contents = ""
|
|
40
|
+
result = nil
|
|
41
|
+
# Try to read the file
|
|
42
|
+
begin
|
|
43
|
+
contents = File.read filepath
|
|
44
|
+
rescue
|
|
45
|
+
# On failure, write a message to stderr and exit
|
|
46
|
+
err "Could not read configuration file: " + filepath
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Try to parse the file
|
|
50
|
+
begin
|
|
51
|
+
conf = YAML.load contents
|
|
52
|
+
result = parse_yaml conf
|
|
53
|
+
rescue
|
|
54
|
+
err "Error parsing #{filepath}:\n#{$!}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if result
|
|
58
|
+
load_resources *result
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
protected
|
|
63
|
+
|
|
64
|
+
# Save as a YAML file
|
|
65
|
+
def save_file path
|
|
66
|
+
y = emit.to_yaml
|
|
67
|
+
begin
|
|
68
|
+
file = File.new $CONFIG + path, "w"
|
|
69
|
+
file.write y
|
|
70
|
+
file.close
|
|
71
|
+
rescue StandardError => e
|
|
72
|
+
UI::warn "Could not save #{self.class} as #{path}: #{e}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Emit as yaml
|
|
77
|
+
def emit
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Subclasses must create a method parse_yaml which takes YAML returns an array
|
|
81
|
+
def parse_yaml conf
|
|
82
|
+
[]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Subclasses may create a method load_resource
|
|
86
|
+
#
|
|
87
|
+
# This is called after parse_yaml - hence errors which occur here are not attributed to parsing the configuration file
|
|
88
|
+
#
|
|
89
|
+
# Takes each element of parse_yaml's return array as an argument, as in
|
|
90
|
+
# it is called with the result of parse_yaml, like so:
|
|
91
|
+
#
|
|
92
|
+
# load_resources *parse_yaml conf
|
|
93
|
+
def load_resources *forget
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Attempt to find field within the conf hash
|
|
97
|
+
#
|
|
98
|
+
# Untaints the field.
|
|
99
|
+
def read_conf conf, field
|
|
100
|
+
unless conf.include? field
|
|
101
|
+
raise "Could not find field: #{field}"
|
|
102
|
+
end
|
|
103
|
+
conf[field].untaint
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Raise error
|
|
107
|
+
def err msg
|
|
108
|
+
if @fatal
|
|
109
|
+
CARPS::fatal msg
|
|
110
|
+
else
|
|
111
|
+
raise StandardError, msg
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# User configurations, which may be stored in many files
|
|
118
|
+
# and which should not crash the system on an error
|
|
119
|
+
class UserConfig < YamlConfig
|
|
120
|
+
|
|
121
|
+
# Subclasses must call super
|
|
122
|
+
def initialize
|
|
123
|
+
fail_hard false
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Load a user file.
|
|
127
|
+
def self.load filepath
|
|
128
|
+
config = self.allocate
|
|
129
|
+
config.read filepath
|
|
130
|
+
config.fail_hard false
|
|
131
|
+
config
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# System configurations, which exist in strictly predefined locations
|
|
137
|
+
# and which should crash the system if they do not exist, because they
|
|
138
|
+
# are critical to its operation.
|
|
139
|
+
class SystemConfig < YamlConfig
|
|
140
|
+
|
|
141
|
+
# Subclasses must call super
|
|
142
|
+
def initialize
|
|
143
|
+
fail_hard true
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Load a system file.
|
|
147
|
+
def self.load
|
|
148
|
+
config = self.allocate
|
|
149
|
+
config.read self.filepath
|
|
150
|
+
config.fail_hard false
|
|
151
|
+
config
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Save the user config
|
|
155
|
+
def save
|
|
156
|
+
save_file self.class.filepath
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/util"
|
|
19
|
+
|
|
20
|
+
require "carps/ui/error"
|
|
21
|
+
|
|
22
|
+
require "carps/test"
|
|
23
|
+
|
|
24
|
+
require "fileutils"
|
|
25
|
+
|
|
26
|
+
require "tempfile"
|
|
27
|
+
|
|
28
|
+
module CARPS
|
|
29
|
+
|
|
30
|
+
# Expects a field called "launch_editor"
|
|
31
|
+
class Editor < SystemConfig
|
|
32
|
+
|
|
33
|
+
def Editor.filepath
|
|
34
|
+
"editor.yaml"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize editor, wait_for_confirm = false
|
|
38
|
+
@editor = editor
|
|
39
|
+
@wait_confirm = wait_for_confirm
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def parse_yaml config
|
|
43
|
+
@editor = read_conf config, "launch_editor"
|
|
44
|
+
@wait_confirm = read_conf config, "wait"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Edit a string
|
|
48
|
+
#
|
|
49
|
+
# Performs an untaint operation
|
|
50
|
+
#
|
|
51
|
+
# Not re-entrant
|
|
52
|
+
def edit msg
|
|
53
|
+
begin
|
|
54
|
+
dir = Dir.tmpdir.untaint
|
|
55
|
+
unless File.exists?(dir)
|
|
56
|
+
FileUtils.mkdir dir
|
|
57
|
+
end
|
|
58
|
+
file = Tempfile.new "carp_edit", dir
|
|
59
|
+
path = file.path
|
|
60
|
+
file.write "# Lines starting with # will be ignored.\n" + msg
|
|
61
|
+
file.close
|
|
62
|
+
contents = edit_file path
|
|
63
|
+
contents.untaint
|
|
64
|
+
lines = contents.split /\n/
|
|
65
|
+
lines.reject! do |line|
|
|
66
|
+
line[0] == '#'
|
|
67
|
+
end
|
|
68
|
+
lines.join "\n"
|
|
69
|
+
rescue StandardError => e
|
|
70
|
+
UI::put_error e.to_s
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
protected
|
|
76
|
+
|
|
77
|
+
def edit_file filepath
|
|
78
|
+
system @editor.gsub("%f", filepath)
|
|
79
|
+
|
|
80
|
+
if @wait_confirm
|
|
81
|
+
UI::question "Press enter when you are done editing."
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if File.exists? filepath
|
|
85
|
+
return File.read filepath
|
|
86
|
+
else
|
|
87
|
+
return ""
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Emit as hash
|
|
93
|
+
def emit
|
|
94
|
+
{
|
|
95
|
+
"launch_editor" => @editor,
|
|
96
|
+
"wait" => @wait_confirm
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
module Test
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# Testing for editor
|
|
106
|
+
module Editor
|
|
107
|
+
|
|
108
|
+
def Editor::load_fail
|
|
109
|
+
Editor::test_failed "The editor did not load the file correctly."
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def Editor::save_fail
|
|
113
|
+
Editor::test_failed "The editor did not save the file correctly."
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Test the editor
|
|
119
|
+
def Test::editor editor
|
|
120
|
+
puts "The editor should launch, then you should edit this paragraph:"
|
|
121
|
+
before = "Please edit me."
|
|
122
|
+
puts before
|
|
123
|
+
puts "Once you are done editing, save the file and close the editor."
|
|
124
|
+
if after = editor.edit(before)
|
|
125
|
+
if after == before
|
|
126
|
+
Test::multi_fail "Your editor is detaching itself into the background.", "You did not edit the paragraph. Do so!", "The editor did not save the file correctly.", "The editor did not load the file correctly."
|
|
127
|
+
else
|
|
128
|
+
before_good = UI::confirm "Before you starting editing, did the editor display this text?\n#{before}"
|
|
129
|
+
if before_good
|
|
130
|
+
after_good = UI::confirm "Did you change that to this?\n#{after}"
|
|
131
|
+
if after_good
|
|
132
|
+
return true
|
|
133
|
+
else
|
|
134
|
+
Editor::save_fail
|
|
135
|
+
end
|
|
136
|
+
else
|
|
137
|
+
Editor::load_fail
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
else
|
|
141
|
+
Editor::save_fail
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
require "carps/ui"
|
|
19
|
+
require "carps/util"
|
|
20
|
+
|
|
21
|
+
module CARPS
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Press enter to quit
|
|
25
|
+
def CARPS::enter_quit status=0
|
|
26
|
+
UI::question "Press enter to quit."
|
|
27
|
+
CARPS::shutdown_properly status
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Output an error message and quit with exit code 1
|
|
31
|
+
def CARPS::fatal msg
|
|
32
|
+
h = HighLine.new
|
|
33
|
+
$stderr.write h.color("\nFATAL ERROR\n#{msg}\n", :error)
|
|
34
|
+
puts "\a"
|
|
35
|
+
exit 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Kill all threads and exit with status
|
|
40
|
+
def CARPS::shutdown_properly status
|
|
41
|
+
# Stop all threads
|
|
42
|
+
Thread.list.each do |thr|
|
|
43
|
+
unless thr == Thread.main
|
|
44
|
+
Thread.kill thr
|
|
45
|
+
thr.join
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
exit status
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Catch errors and print out a stack trace if they occur.
|
|
52
|
+
#
|
|
53
|
+
# If wait is true, then wait for the user to press enter.
|
|
54
|
+
#
|
|
55
|
+
# Pass a block.
|
|
56
|
+
#
|
|
57
|
+
# Intented to be run at the top level (Eg by the binaries)
|
|
58
|
+
def CARPS::with_crash_report wait=false
|
|
59
|
+
begin
|
|
60
|
+
yield
|
|
61
|
+
rescue SystemExit => e
|
|
62
|
+
CARPS::shutdown_properly e.status
|
|
63
|
+
rescue Interrupt => e
|
|
64
|
+
CARPS::shutdown_properly 1
|
|
65
|
+
rescue Exception => e
|
|
66
|
+
UI::put_error "CRASHED!\n#{e.class} reports:\n #{e.message}\n\nStack trace:\n#{e.backtrace.join("\n")}", false
|
|
67
|
+
if wait
|
|
68
|
+
CARPS::enter_quit 1
|
|
69
|
+
else
|
|
70
|
+
CARPS::shutdown_properly 1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright 2010 John Morrice
|
|
2
|
+
|
|
3
|
+
# This file is part of CARPS.
|
|
4
|
+
|
|
5
|
+
# CARPS is free software: you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
# CARPS is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License
|
|
16
|
+
# along with CARPS. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
module CARPS
|
|
19
|
+
|
|
20
|
+
# Get the file names from inside a directory
|
|
21
|
+
def files dir
|
|
22
|
+
file_names = Dir.open(dir).entries.reject do |file|
|
|
23
|
+
file.untaint
|
|
24
|
+
file[0] == "." or File.ftype(dir + "/" + file) != "file"
|
|
25
|
+
end
|
|
26
|
+
file_names.map do |fn|
|
|
27
|
+
dir + "/" + fn
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Write contents into a new file in a directory with an arbitrary, unique name
|
|
32
|
+
#
|
|
33
|
+
# Returns the path
|
|
34
|
+
def write_file_in dir, contents
|
|
35
|
+
t = Time.now
|
|
36
|
+
valid_path = false
|
|
37
|
+
path = $CONFIG + dir + "/" + t.to_f.to_s.gsub(/(\.|@, \?!#'"~\(\))/, "")
|
|
38
|
+
until valid_path
|
|
39
|
+
path += "_"
|
|
40
|
+
valid_path = not(File.exists?(path))
|
|
41
|
+
end
|
|
42
|
+
file = File.new path, "w"
|
|
43
|
+
file.write contents
|
|
44
|
+
file.close
|
|
45
|
+
path
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|