resedit 1.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1b2afae945b0bfe8559010f9de3ecd21889a036
4
+ data.tar.gz: 9ec879c124f71706f9d5e90b988c88a1a7576457
5
+ SHA512:
6
+ metadata.gz: 85ac7bb3ccf16019f0314d6ffed992c47636ebe0a20451e4988a3afde9e03d67dea91dee2c0a003e619b018189538f962e45398bf6d058efde2796abdb85f6ea
7
+ data.tar.gz: 9cbbafcba61f4bc3fef2787a70f9c4e971d80edf508e56b979ee13e891a54431c110d0a1d94dd6dd7e2b1dd9980547a319c643a0c1ae36417468e2bfa5be59c5
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'resedit'
4
+
5
+ class App < Resedit::App
6
+ def initialize()
7
+ super('resedit',Resedit::VERSION, nil, true, "by bjfn (c) old-games.ru, 2017")
8
+ end
9
+ end
10
+
11
+ App.new().run()
@@ -0,0 +1,17 @@
1
+
2
+ require 'resedit/font/font'
3
+ require 'resedit/font/font_char'
4
+ require 'resedit/image/image_factory'
5
+ require 'resedit/text/escaper'
6
+ require 'resedit/text/text'
7
+ require 'resedit/app/app'
8
+ require 'resedit/text/huffman'
9
+ require 'resedit/app/font_convert'
10
+ require 'resedit/app/text_convert'
11
+ require 'resedit/convert/bitconv'
12
+ require 'resedit/mz/mz'
13
+
14
+
15
+ module Resedit
16
+ VERSION = "1.3.1"
17
+ end
@@ -0,0 +1,160 @@
1
+ require 'resedit/app/std_commands'
2
+ require 'resedit/app/mz_command'
3
+ require 'resedit/app/colorizer'
4
+ require 'logger'
5
+ require 'readline'
6
+
7
+ module Resedit
8
+
9
+ class App
10
+ HIST_FILE = "~/.resedithist"
11
+ attr_reader :name, :version, :commands, :logger, :copyright, :cmdInterface, :shell, :col
12
+
13
+ def self.get()
14
+ return @@instance
15
+ end
16
+
17
+ def initialize(name, version, commands, cmdInterface=true, copyright="(c) old-games.ru")
18
+ @@instance = self
19
+ @name, @version, @copyright = name, version, copyright
20
+ @cmdInterface = cmdInterface
21
+ @logger = Logger.new(STDOUT)
22
+ @logger.level= Logger::INFO
23
+ logger.formatter = proc { |severity, datetime, progname, msg|
24
+ msg
25
+ }
26
+ @shell = nil;
27
+ @commands = []
28
+ @commands += commands if commands
29
+ @commands += [HelpCommand.new(), VersionCommand.new(), ExitCommand.new(),
30
+ ScriptCommand.new(), MZCommand.new(), ShellCommand.new()]
31
+ @cmds={}
32
+ @commands.each{|c|
33
+ c.names.each{|n|
34
+ @cmds[n] = c;
35
+ }
36
+ }
37
+ @col = Colorizer.new(false)
38
+ end
39
+
40
+
41
+ def logd(fmt, *args)
42
+ @logger.debug(@col.gray(sprintf(fmt+"\n",*args)))
43
+ end
44
+ def log(fmt, *args)
45
+ @logger.info(sprintf(fmt+"\n",*args))
46
+ end
47
+ def loge(fmt, *args)
48
+ @logger.error(@col.red(sprintf(fmt+"\n",*args)))
49
+ end
50
+
51
+
52
+ def quit
53
+ begin
54
+ strt = Readline::HISTORY.length-64
55
+ open(File.expand_path(HIST_FILE),"w"){|f|
56
+ Readline::HISTORY.each.with_index{|ln,i|
57
+ f.write(ln+"\n") if i > strt
58
+ }
59
+ }
60
+ rescue
61
+ end
62
+ @stop=true
63
+ end
64
+
65
+ def setShell(sname)
66
+ sname=nil if sname.length==0
67
+ raise "Unknown shell: "+sname if sname && !@cmds[sname]
68
+ @shell = sname
69
+ end
70
+
71
+ def parseCommand(string)
72
+ cmd = []
73
+ string.split().each {|w|
74
+ if w[0]=='-' && w.length()>2 && w[1]!='-'
75
+ w[1..-1].each_char{|c|
76
+ cmd+=["-#{c}"]
77
+ }
78
+ else
79
+ cmd+=[w]
80
+ end
81
+ }
82
+ logd("parsing command #{cmd.to_s}")
83
+ return nil if cmd.length()==0 || cmd[0][0]=='#'
84
+ c = @cmds[cmd[0]]
85
+ raise "Unknown command: #{cmd[0]}" if !c
86
+ res=[]
87
+ prms = c.parseParams(cmd[1..-1])
88
+ return c,prms
89
+ end
90
+
91
+
92
+ def runCommand(string)
93
+ if @shell
94
+ cmd=string.split()[0]
95
+ if !@cmds[cmd] || !['Resedit::ExitCommand','Resedit::ShellCommand'].include?(@cmds[cmd].class.name)
96
+ string = @shell+" "+string
97
+ end
98
+ end
99
+ logd("running command %s", string)
100
+ cmd = parseCommand(string)
101
+ cmd[0].run(cmd[1])
102
+ end
103
+
104
+
105
+ def commandInterface()
106
+ @cmds['version'].run('')
107
+ begin
108
+ open(File.expand_path(HIST_FILE),"r").each_line {|ln|
109
+ ln.chomp!
110
+ Readline::HISTORY.push(ln) if ln.length>0
111
+ }
112
+ rescue
113
+ end
114
+ @stop=false
115
+ while(!@stop)
116
+ sh=@shell ? " "+@shell : ""
117
+ begin
118
+ cmd = Readline.readline("#{@name}#{sh}>", true)
119
+ Readline::HISTORY.pop if cmd=='' || (Readline::HISTORY.length>1 && cmd==Readline::HISTORY[-2])
120
+ runCommand(cmd)
121
+ rescue StandardError => e
122
+ puts @col.red("Error: #{e.to_s()}")
123
+ puts e.backtrace if App::get().logger.level == Logger::DEBUG
124
+ end
125
+ end
126
+ return 0
127
+ end
128
+
129
+
130
+ def run()
131
+ begin
132
+ if ARGV.length()==0
133
+ commandInterface() if @cmdInterface
134
+ if !@cmdInterface
135
+ puts "Command not specified. Known commands are:"
136
+ runCommand('help')
137
+ end
138
+ else
139
+ if (@cmds[ARGV[0]])
140
+ #check command
141
+ runCommand(ARGV.join(' '))
142
+ commandInterface() if @shell
143
+ elsif ARGV.length()==1 && File.exists?(ARGV[0])
144
+ #check script
145
+ runCommand('script '+ARGV[0])
146
+ else
147
+ raise "unknown command #{ARGV[0]}"
148
+ end
149
+ end
150
+ exit(0)
151
+ rescue StandardError => e
152
+ puts "Error: #{e.to_s()}"
153
+ puts e.backtrace
154
+ exit(1)
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ end
@@ -0,0 +1,100 @@
1
+ module Resedit
2
+
3
+ class AppCommand
4
+ attr_reader :names, :type, :params
5
+ def initialize(names, type=:std)
6
+ @names, @continue = names, type
7
+ @names = [@names] if not @names.kind_of?(Array)
8
+ @opts = {}
9
+ @params = []
10
+ @ohash = {}
11
+ addOption('verbose','v',false, 'verbose output')
12
+ addOption('unverbose',nil,false, 'unverbose output')
13
+ addOption('quiet','q',false, 'supress output')
14
+ addOption('color',nil,false, 'set colored output')
15
+ addOption('uncolor',nil,false, 'unset colored output')
16
+ end
17
+
18
+ def addParam(name, descr, default = nil, type=:std)
19
+ @params +=[{:name => name, :def => default, :descr => descr}]
20
+ end
21
+
22
+ def addOption(longname, shortname, param, descr, type = :std, setter= proc{|val, opt| val})
23
+ @opts[longname] = {:name => longname, :param => param, :descr => descr, :type => type, :setter => setter}
24
+ @ohash[shortname] = longname if shortname
25
+ end
26
+
27
+ def parseParams(params)
28
+ res = {}
29
+ pidx = 0
30
+ idx=0
31
+ @params.each{|p|
32
+ res[p[:name]] = p[:def]
33
+ }
34
+ @opts.each{|k,o|
35
+ res[k] = o[:param]
36
+ }
37
+ while idx<params.length
38
+ p = params[idx]
39
+ idx+=1
40
+ if p[0]=='-'
41
+ val = true
42
+ s=p.split('=')
43
+ if s.length==2
44
+ val=s[1]
45
+ p=s[0]
46
+ end
47
+ if (p[1]=='-')
48
+ opt = @opts[p[2..-1]]
49
+ else
50
+ opt = @opts[@ohash[p[1..-1]]] || @opts[p[1..-1]]
51
+ end
52
+ raise "Unknown option #{p}" if !opt
53
+ if opt[:param]!=false and val==true
54
+ raise "No option #{p} value" if idx>=params.length
55
+ val = params[idx]
56
+ idx+=1
57
+ end
58
+ proc = opt[:setter]
59
+ res[opt[:name]] = proc.call(val, opt)
60
+ else
61
+ raise "Unknown param #{p}" if !@params[pidx]
62
+ if (@params[pidx][:type] == :text)
63
+ p = params[idx-1..-1]
64
+ idx=params.length
65
+ end
66
+ res[@params[pidx][:name]] = p
67
+ pidx+=1
68
+ end
69
+ end
70
+ @params.each{|p|
71
+ raise "Expected parameter #{p[:name]}" if res[p[:name]]==nil
72
+ }
73
+ return res
74
+ end
75
+
76
+ def run(params)
77
+ App::get().logger.level = Logger::DEBUG if params['verbose']
78
+ App::get().logger.level = Logger::INFO if params['unverbose']
79
+ App::get().logger.level = Logger::ERROR if params['quiet']
80
+ App::get().col.on = true if params['color']
81
+ App::get().col.on = false if params['uncolor']
82
+ job(params)
83
+ end
84
+
85
+ def job(params)
86
+ raise "Unimplemented command #{@names[0]}"
87
+ end
88
+
89
+ def logd(fmt, *args)
90
+ App::get().logd(fmt,*args)
91
+ end
92
+ def log(fmt, *args)
93
+ App::get().log(fmt,*args)
94
+ end
95
+ def loge(fmt, *args)
96
+ App::get().loge(fmt,*args)
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,34 @@
1
+ module Resedit
2
+
3
+ class Colorizer
4
+ GRAY = 90
5
+ RED = 91
6
+ GREEN = 92
7
+ YELLOW = 93
8
+ BLUE = 94
9
+ PURPLE = 95
10
+ CYAN = 96
11
+ WHITE = 97
12
+
13
+ attr_accessor :on
14
+
15
+ def initialize(on=true)
16
+ @on = on;
17
+ end
18
+
19
+ def color(col, text)
20
+ return text if !@on
21
+ return "\033[#{col}m#{text}\033[0m"
22
+ end
23
+
24
+ def gray(text) color(GRAY, text) end
25
+ def red(text) color(RED, text) end
26
+ def green(text) color(GREEN, text) end
27
+ def yellow(text) color(YELLOW, text) end
28
+ def blue(text) color(BLUE, text) end
29
+ def deep(text) color(PURPLE, text) end
30
+ def cyan(text) color(CYAN, text) end
31
+ def white(text) color(WHITE, text) end
32
+
33
+ end
34
+ end
@@ -0,0 +1,54 @@
1
+ require 'resedit/app/io_commands'
2
+
3
+ module Resedit
4
+
5
+ class FontConvertCommand < ConvertCommand
6
+
7
+ def initialize(fname)
8
+ super('font', fname)
9
+ @font = nil
10
+ end
11
+
12
+ def import(inname)
13
+ logd("importing font #{inname} to #{@resname}")
14
+ back = backup()
15
+ File.open(back,"rb"){|file|
16
+ @font = mkfont(file)
17
+ @font.load(inname+'.png')
18
+ StringIO.open("","w+b"){|stream|
19
+ pack(file, stream)
20
+ stream.seek(0)
21
+ File.open(@resname,"wb"){|out|
22
+ out.write(stream.read())
23
+ }
24
+ }
25
+ }
26
+ end
27
+
28
+
29
+ def export(outname)
30
+ logd("exporting font #{@resname} to #{outname}")
31
+ File.open(@resname, "rb"){|file|
32
+ @font = mkfont(file)
33
+ unpack(file) if @font
34
+ }
35
+ raise "Font not unpacked" if !@font
36
+ @font.save(outname+'.png')
37
+ end
38
+
39
+
40
+ def mkfont(file)
41
+ raise "Not implemented."
42
+ end
43
+
44
+ def pack(file, outstream)
45
+ raise "Not implemented."
46
+ end
47
+
48
+ def unpack(file)
49
+ raise "Not implemented."
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,74 @@
1
+ require 'resedit/app/app_command'
2
+ require 'fileutils'
3
+
4
+ module Resedit
5
+
6
+ class ExportCommand < AppCommand
7
+ def initialize(name)
8
+ super([name])
9
+ end
10
+ def job(params)
11
+ raise 'Not implemented'
12
+ end
13
+ end
14
+
15
+
16
+ class ImportCommand < AppCommand
17
+ def initialize(name)
18
+ super([name])
19
+ end
20
+ def job(params)
21
+ raise 'Not implemented'
22
+ end
23
+ end
24
+
25
+
26
+ class ConvertCommand < AppCommand
27
+
28
+ attr_reader :fname
29
+
30
+
31
+ def initialize(name, fname)
32
+ super([name])
33
+ addParam('action','import/export action')
34
+ addParam('file','file to import/export')
35
+ addOption('output','o',nil,'converted file name')
36
+ @fname=fname
37
+ end
38
+
39
+
40
+ def getOutName()
41
+ return File.basename(@resname,File.extname(@resname))
42
+ end
43
+
44
+ def backup()
45
+ bname=@resname+'.bak'
46
+ FileUtils.cp(@resname,bname) if ! File.exist?(bname)
47
+ return bname
48
+ end
49
+
50
+ def job(params)
51
+ @params=params
52
+ @resname=params['file']
53
+ fname = getOutName()
54
+ fname = params['output'] if params['output']
55
+ if params['action']=='import'
56
+ import(fname)
57
+ elsif params['action']=='export'
58
+ export(fname)
59
+ else
60
+ raise "Unknown action #{params['action']}. import or export expected."
61
+ end
62
+
63
+ end
64
+
65
+ def import(infile)
66
+ raise 'Not implemented'
67
+ end
68
+
69
+ def export(outfile)
70
+ raise 'Not implemented'
71
+ end
72
+ end
73
+
74
+ end