v / cmd / tools
Raw file | 146 loc (137 sloc) | 3.83 KB | Latest commit hash 017ace6ea
1module main
2
3import os
4import flag
5import strings
6
7const (
8 tool_version = '0.0.4'
9 tool_description = 'Converts a list of arbitrary files into a single v module file.'
10)
11
12struct Context {
13mut:
14 files []string
15 prefix string
16 show_help bool
17 module_name string
18 write_file string
19}
20
21fn (context Context) header() string {
22 mut header_s := ''
23 header_s += 'module ${context.module_name}\n'
24 header_s += '\n'
25 allfiles := context.files.join(' ')
26 mut options := []string{}
27 if context.prefix.len > 0 {
28 options << '-p ${context.prefix}'
29 }
30 if context.module_name.len > 0 {
31 options << '-m ${context.module_name}'
32 }
33 if context.write_file.len > 0 {
34 options << '-w ${context.write_file}'
35 }
36 soptions := options.join(' ')
37 header_s += '// File generated by:\n'
38 header_s += '// v bin2v ${allfiles} ${soptions}\n'
39 header_s += '// Please, do not edit this file.\n'
40 header_s += '// Your changes may be overwritten.\n'
41 header_s += 'const (\n'
42 return header_s
43}
44
45fn (context Context) footer() string {
46 return ')\n'
47}
48
49fn (context Context) file2v(bname string, fbytes []u8, bn_max int) string {
50 mut sb := strings.new_builder(1000)
51 bn_diff_len := bn_max - bname.len
52 sb.write_string('\t${bname}_len' + ' '.repeat(bn_diff_len - 4) + ' = ${fbytes.len}\n')
53 fbyte := fbytes[0]
54 bnmae_line := '\t${bname}' + ' '.repeat(bn_diff_len) + ' = [u8(${fbyte}), '
55 sb.write_string(bnmae_line)
56 mut line_len := bnmae_line.len + 3
57 for i := 1; i < fbytes.len; i++ {
58 b := int(fbytes[i]).str()
59 if line_len > 94 {
60 sb.go_back(1)
61 sb.write_string('\n\t\t')
62 line_len = 8
63 }
64 if i == fbytes.len - 1 {
65 sb.write_string(b)
66 line_len += b.len
67 } else {
68 sb.write_string('${b}, ')
69 line_len += b.len + 2
70 }
71 }
72 sb.write_string(']!\n')
73 return sb.str()
74}
75
76fn (context Context) bname_and_bytes(file string) !(string, []u8) {
77 fname := os.file_name(file)
78 fname_escaped := fname.replace_each(['.', '_', '-', '_'])
79 byte_name := '${context.prefix}${fname_escaped}'.to_lower()
80 fbytes := os.read_bytes(file) or { return error('Error: ${err.msg()}') }
81 return byte_name, fbytes
82}
83
84fn (context Context) max_bname_len(bnames []string) int {
85 mut max := 0
86 for n in bnames {
87 if n.len > max {
88 max = n.len
89 }
90 }
91 // Add 4 to max due to "_len" suffix
92 return max + 4
93}
94
95fn main() {
96 mut context := Context{}
97 mut fp := flag.new_flag_parser(os.args[1..])
98 fp.application('v bin2v')
99 fp.version(tool_version)
100 fp.description(tool_description)
101 fp.arguments_description('FILE [FILE]...')
102 context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
103 context.module_name = fp.string('module', `m`, 'binary', 'Name of the generated module.')
104 context.prefix = fp.string('prefix', `p`, '', 'A prefix put before each resource name.')
105 context.write_file = fp.string('write', `w`, '', 'Write directly to a file with the given name.')
106 if context.show_help {
107 println(fp.usage())
108 exit(0)
109 }
110 files := fp.finalize() or {
111 eprintln('Error: ${err.msg()}')
112 exit(1)
113 }
114 real_files := files.filter(it != 'bin2v')
115 if real_files.len == 0 {
116 println(fp.usage())
117 exit(0)
118 }
119 context.files = real_files
120 if context.write_file != '' && os.file_ext(context.write_file) !in ['.vv', '.v'] {
121 context.write_file += '.v'
122 }
123 mut file_byte_map := map[string][]u8{}
124 for file in real_files {
125 bname, fbytes := context.bname_and_bytes(file) or {
126 eprintln(err.msg())
127 exit(1)
128 }
129 file_byte_map[bname] = fbytes
130 }
131 max_bname := context.max_bname_len(file_byte_map.keys())
132 if context.write_file.len > 0 {
133 mut out_file := os.create(context.write_file)!
134 out_file.write_string(context.header())!
135 for bname, fbytes in file_byte_map {
136 out_file.write_string(context.file2v(bname, fbytes, max_bname))!
137 }
138 out_file.write_string(context.footer())!
139 } else {
140 print(context.header())
141 for bname, fbytes in file_byte_map {
142 print(context.file2v(bname, fbytes, max_bname))
143 }
144 print(context.footer())
145 }
146}