This commit is contained in:
2025-03-24 06:44:39 +01:00
parent 0df10f5cb3
commit 598b312140
371 changed files with 8238 additions and 9082 deletions

View File

@@ -1,4 +1,3 @@
module code
pub type Value = string

View File

@@ -3,23 +3,23 @@ module code
import freeflowuniverse.herolib.core.pathlib
pub interface IFolder {
name string
files []IFile
name string
files []IFile
modules []Module
write(string, WriteOptions) !
}
pub struct Folder {
pub:
name string
files []IFile
name string
files []IFile
folders []IFolder
modules []Module
}
pub fn (f Folder) write(path string, options WriteOptions) ! {
mut dir := pathlib.get_dir(
path: '${path}/${f.name}'
path: '${path}/${f.name}'
empty: options.overwrite
)!
@@ -36,4 +36,4 @@ pub fn (f Folder) write(path string, options WriteOptions) ! {
for mod in f.modules {
mod.write(dir.path, options)!
}
}
}

View File

@@ -3,7 +3,14 @@ module code
// Code is a list of statements
// pub type Code = []CodeItem
pub type CodeItem = Alias | Comment | CustomCode | Function | Import | Struct | Sumtype | Interface
pub type CodeItem = Alias
| Comment
| CustomCode
| Function
| Import
| Struct
| Sumtype
| Interface
// item for adding custom code in
pub struct CustomCode {

View File

@@ -11,7 +11,7 @@ pub fn parse_const(code_ string) !Const {
return error('code <${code_}> is not of const')
}
return Const{
name: code.split('=')[0].trim_space()
name: code.split('=')[0].trim_space()
value: code.split('=')[1].trim_space()
}
}

View File

@@ -5,8 +5,8 @@ import freeflowuniverse.herolib.core.pathlib
import os
pub interface IFile {
write(string, WriteOptions) !
name string
write(string, WriteOptions) !
}
pub struct File {
@@ -30,7 +30,6 @@ pub fn (f File) typescript(path string, params WriteOptions) ! {
}
}
pub struct VFile {
pub mut:
name string
@@ -44,7 +43,7 @@ pub mut:
pub fn new_file(config VFile) VFile {
return VFile{
...config
mod: texttools.name_fix(config.mod)
mod: texttools.name_fix(config.mod)
items: config.items
}
}
@@ -85,11 +84,13 @@ pub fn (code VFile) write(path string, options WriteOptions) ! {
}
mut file := pathlib.get_file(
path: filepath.path
path: filepath.path
create: true
)!
mod_stmt := if code.mod == '' {''} else {
mod_stmt := if code.mod == '' {
''
} else {
'module ${code.mod}'
}
@@ -128,4 +129,4 @@ pub fn (file VFile) functions() []Function {
pub fn (file VFile) structs() []Struct {
return file.items.filter(it is Struct).map(it as Struct)
}
}

View File

@@ -3,23 +3,23 @@ module code
import freeflowuniverse.herolib.core.pathlib
pub interface IBasicFolder {
name string
files []IFile
name string
files []IFile
modules []Module
write(string, WriteOptions) !
}
pub struct BasicFolder {
pub:
name string
files []IFile
name string
files []IFile
folders []IBasicFolder
modules []Module
}
pub fn (f BasicFolder) write(path string, options WriteOptions) ! {
mut dir := pathlib.get_dir(
path: '${path}/${f.name}'
path: '${path}/${f.name}'
empty: options.overwrite
)!
@@ -36,4 +36,4 @@ pub fn (f BasicFolder) write(path string, options WriteOptions) ! {
for mod in f.modules {
mod.write(dir.path, options)!
}
}
}

View File

@@ -4,60 +4,62 @@ import freeflowuniverse.herolib.core.texttools
pub struct Function {
pub:
name string @[omitempty]
receiver Param @[omitempty]
is_pub bool @[omitempty]
mod string @[omitempty]
name string @[omitempty]
receiver Param @[omitempty]
is_pub bool @[omitempty]
mod string @[omitempty]
pub mut:
summary string @[omitempty]
description string @[omitempty]
params []Param @[omitempty]
body string @[omitempty]
summary string @[omitempty]
description string @[omitempty]
params []Param @[omitempty]
body string @[omitempty]
result Param @[omitempty]
has_return bool @[omitempty]
has_return bool @[omitempty]
}
// vgen_function generates a function statement for a function
pub fn (function Function) vgen(options WriteOptions) string {
mut params_ := function.params.clone()
optionals := function.params.filter(it.is_optional)
options_struct := Struct{
name: '${texttools.pascal_case(function.name)}Options'
attrs: [Attribute{
name: '${texttools.pascal_case(function.name)}Options'
attrs: [Attribute{
name: 'params'
}]
fields: optionals.map(StructField{
name: it.name
name: it.name
description: it.description
typ: it.typ
typ: it.typ
})
}
if optionals.len > 0 {
params_ << Param{
name: 'options'
typ: type_from_symbol(options_struct.name)
typ: type_from_symbol(options_struct.name)
}
}
params := params_.filter(!it.is_optional).map(it.vgen()).join(', ')
receiver_ := Param{
...function.receiver,
...function.receiver
typ: if function.receiver.typ is Result {
function.receiver.typ.typ
} else {function.receiver.typ}
} else {
function.receiver.typ
}
}
receiver := if receiver_.vgen().trim_space() != '' {
'(${receiver_.vgen()})'
} else {''}
} else {
''
}
name := texttools.name_fix(function.name)
result := function.result.typ.vgen()
mut function_str := $tmpl('templates/function/function.v.template')
// if options.format {
// result := os.execute_opt('echo "${function_str.replace('$', '\\$')}" | v fmt') or {
// panic('${function_str}\n${err}')
@@ -115,10 +117,10 @@ pub fn parse_function(code_ string) !Function {
body := if code.contains('{') { code.all_after('{').all_before_last('}') } else { '' }
return Function{
name: name
name: name
receiver: receiver
params: params
result: result
body: body
params: params
result: result
body: body
}
}
}

View File

@@ -14,7 +14,7 @@ pub fn parse_import(code_ string) Import {
code := code_.trim_space().trim_string_left('import').trim_space()
types_str := if code.contains(' ') { code.all_after(' ').trim('{}') } else { '' }
return Import{
mod: code.all_before(' ')
mod: code.all_before(' ')
types: if types_str != '' {
types_str.split(',').map(it.trim_space())
} else {

View File

@@ -1,4 +1,5 @@
module code
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.pathlib
import os
@@ -6,75 +7,71 @@ import log
pub struct Module {
pub mut:
name string
name string
description string
version string = '0.0.1'
license string = 'apache2'
vcs string = 'git'
files []IFile
folders []IFolder
modules []Module
in_src bool // whether mod will be generated in src folder
version string = '0.0.1'
license string = 'apache2'
vcs string = 'git'
files []IFile
folders []IFolder
modules []Module
in_src bool // whether mod will be generated in src folder
}
pub fn new_module(mod Module) Module {
return Module {
return Module{
...mod
files: mod.files.map(
if it is VFile {
IFile(VFile{...it, mod: mod.name})
} else {it}
)
files: mod.files.map(if it is VFile {
IFile(VFile{ ...it, mod: mod.name })
} else {
it
})
}
}
pub fn (mod Module) write(path string, options WriteOptions) ! {
mut module_dir := pathlib.get_dir(
path: if mod.in_src { '${path}/src' } else { '${path}/${mod.name}' }
path: if mod.in_src { '${path}/src' } else { '${path}/${mod.name}' }
empty: options.overwrite
)!
console.print_debug("write ${module_dir.path}")
console.print_debug('write ${module_dir.path}')
// pre:="v -n -w -enable-globals"
pre:="v -n -w -gc none -cc tcc -d use_openssl -enable-globals run"
pre := 'v -n -w -gc none -cc tcc -d use_openssl -enable-globals run'
if !options.overwrite && module_dir.exists() {
return
}
for file in mod.files {
console.print_debug("mod file write ${file.name}")
console.print_debug('mod file write ${file.name}')
file.write(module_dir.path, options)!
}
for folder in mod.folders {
console.print_debug("mod folder write ${folder.name}")
console.print_debug('mod folder write ${folder.name}')
folder.write('${path}/${mod.name}', options)!
}
for mod_ in mod.modules {
console.print_debug("mod write ${mod_.name}")
console.print_debug('mod write ${mod_.name}')
mod_.write('${path}/${mod.name}', options)!
}
if options.format {
console.print_debug("format ${module_dir.path}")
console.print_debug('format ${module_dir.path}')
os.execute('v fmt -w ${module_dir.path}')
}
if options.compile {
console.print_debug("compile shared ${module_dir.path}")
os.execute_opt('${pre} -shared ${module_dir.path}') or {
log.fatal(err.msg())
}
console.print_debug('compile shared ${module_dir.path}')
os.execute_opt('${pre} -shared ${module_dir.path}') or { log.fatal(err.msg()) }
}
if options.test {
console.print_debug("test ${module_dir.path}")
os.execute_opt('${pre} test ${module_dir.path}') or {
log.fatal(err.msg())
}
console.print_debug('test ${module_dir.path}')
os.execute_opt('${pre} test ${module_dir.path}') or { log.fatal(err.msg()) }
}
if options.document {
docs_path := '${path}/${mod.name}/docs'
console.print_debug("document ${module_dir.path}")
console.print_debug('document ${module_dir.path}')
os.execute('v doc -f html -o ${docs_path} ${module_dir.path}')
}

View File

@@ -4,18 +4,18 @@ import freeflowuniverse.herolib.core.texttools
pub struct Param {
pub mut:
required bool @[omitempty]
mutable bool @[omitempty]
is_shared bool @[omitempty]
is_optional bool @[omitempty]
is_result bool @[omitempty]
description string @[omitempty]
name string @[omitempty]
typ Type @[omitempty]
required bool @[omitempty]
mutable bool @[omitempty]
is_shared bool @[omitempty]
is_optional bool @[omitempty]
is_result bool @[omitempty]
description string @[omitempty]
name string @[omitempty]
typ Type @[omitempty]
}
@[params]
pub struct Params{
pub struct Params {
pub:
v string
}
@@ -37,7 +37,7 @@ pub fn (param Param) vgen() string {
pub fn (p Param) typescript() string {
name := texttools.camel_case(p.name)
suffix := if p.is_optional {'?'} else {''}
suffix := if p.is_optional { '?' } else { '' }
return '${name}${suffix}: ${p.typ.typescript()}'
}
@@ -45,9 +45,13 @@ pub fn parse_param(code_ string) !Param {
mut code := code_.trim_space()
if code == '!' {
return Param{is_result: true}
return Param{
is_result: true
}
} else if code == '?' {
return Param{is_optional: true}
return Param{
is_optional: true
}
}
is_mut := code.starts_with('mut ')
@@ -59,7 +63,7 @@ pub fn parse_param(code_ string) !Param {
if split.len == 1 {
// means anonymous param
return Param{
typ: type_from_symbol(split[0])
typ: type_from_symbol(split[0])
mutable: is_mut
}
}
@@ -67,8 +71,8 @@ pub fn parse_param(code_ string) !Param {
return error('invalid param format: ${code_}')
}
return Param{
name: split[0]
typ: type_from_symbol(split[1])
name: split[0]
typ: type_from_symbol(split[1])
mutable: is_mut
}
}

View File

@@ -33,7 +33,9 @@ pub fn (struct_ Struct) vgen() string {
comments := if struct_.description.trim_space() != '' {
'// ${struct_.description.trim_space()}'
} else {''}
} else {
''
}
priv_fields := struct_.fields.filter(!it.is_mut && !it.is_pub).map(it.vgen())
pub_fields := struct_.fields.filter(!it.is_mut && it.is_pub).map(it.vgen())
@@ -51,16 +53,15 @@ pub fn (struct_ Struct) vgen() string {
return struct_str
}
pub struct Interface {
pub mut:
name string
description string
is_pub bool
embeds []Interface @[str: skip]
embeds []Interface @[str: skip]
attrs []Attribute
fields []StructField
methods []Function
methods []Function
}
pub fn (iface Interface) vgen() string {
@@ -104,8 +105,8 @@ pub mut:
is_pub bool
is_mut bool
is_ref bool
anon_struct Struct @[str: skip] // sometimes fields may hold anonymous structs
structure Struct @[str: skip]
anon_struct Struct @[str: skip] // sometimes fields may hold anonymous structs
structure Struct @[str: skip]
}
pub fn (field StructField) vgen() string {
@@ -133,4 +134,4 @@ pub fn (s Struct) typescript() string {
name := texttools.pascal_case(s.name)
fields := s.fields.map(it.typescript()).join_lines()
return 'export interface ${name} {\n${fields}\n}'
}
}

View File

@@ -1,56 +1,65 @@
module code
struct Float {
bytes int
bytes int
}
// Integer types
pub const type_i8 = Integer{
bytes: 8
bytes: 8
}
pub const type_u8 = Integer{
bytes: 8
signed: false
bytes: 8
signed: false
}
pub const type_i16 = Integer{
bytes: 16
bytes: 16
}
pub const type_u16 = Integer{
bytes: 16
signed: false
bytes: 16
signed: false
}
pub const type_i32 = Integer{
bytes: 32
bytes: 32
}
pub const type_u32 = Integer{
bytes: 32
signed: false
bytes: 32
signed: false
}
pub const type_i64 = Integer{
bytes: 64
bytes: 64
}
pub const type_u64 = Integer{
bytes: 64
signed: false
bytes: 64
signed: false
}
// Floating-point types
pub const type_f32 = Float{
bytes: 32
bytes: 32
}
pub const type_f64 = Float{
bytes: 64
bytes: 64
}
pub type Type = Void | Map | Array | Object | Result | Integer | Alias | String | Boolean | Function
pub type Type = Void
| Map
| Array
| Object
| Result
| Integer
| Alias
| String
| Boolean
| Function
pub struct Alias {
pub:
@@ -59,12 +68,12 @@ pub:
typ Type
}
pub struct Boolean{}
pub struct Boolean {}
pub struct Void{}
pub struct Void {}
pub struct Integer {
bytes u8
bytes u8
signed bool = true
}
@@ -84,26 +93,44 @@ pub fn type_from_symbol(symbol_ string) Type {
pub fn (t Type) symbol() string {
return match t {
Array { '[]${t.typ.symbol()}' }
Object { t.name }
Result { '!${t.typ.symbol()}'}
Array {
'[]${t.typ.symbol()}'
}
Object {
t.name
}
Result {
'!${t.typ.symbol()}'
}
Integer {
mut str := ''
if !t.signed {
str += 'u'
}
if t.bytes != 0 {
'${str}${t.bytes}'
} else {
'${str}int'
}
}
Alias {t.name}
String {'string'}
Boolean {'bool'}
Map{'map[string]${t.typ.symbol()}'}
Function{'fn ()'}
Void {''}
mut str := ''
if !t.signed {
str += 'u'
}
if t.bytes != 0 {
'${str}${t.bytes}'
} else {
'${str}int'
}
}
Alias {
t.name
}
String {
'string'
}
Boolean {
'bool'
}
Map {
'map[string]${t.typ.symbol()}'
}
Function {
'fn ()'
}
Void {
''
}
}
}
@@ -131,16 +158,16 @@ pub:
pub fn (t Type) typescript() string {
return match t {
Map {'Record<string, ${t.typ.typescript()}>'}
Map { 'Record<string, ${t.typ.typescript()}>' }
Array { '${t.typ.typescript()}[]' }
Object { t.name }
Result { '${t.typ.typescript()}'}
Boolean { 'boolean'}
Result { '${t.typ.typescript()}' }
Boolean { 'boolean' }
Integer { 'number' }
Alias {t.name}
String {'string'}
Function {'func'}
Void {''}
Alias { t.name }
String { 'string' }
Function { 'func' }
Void { '' }
}
}
@@ -151,15 +178,39 @@ pub fn (t Type) vgen() string {
pub fn (t Type) empty_value() string {
return match t {
Map {'{}'}
Array { '[]${t.typ.symbol()}{}' }
Object { if t.name != '' {'${t.name}{}'} else {''} }
Result { t.typ.empty_value() }
Boolean { 'false' }
Integer { '0' }
Alias {''}
String {"''"}
Function {''}
Void {''}
Map {
'{}'
}
Array {
'[]${t.typ.symbol()}{}'
}
Object {
if t.name != '' {
'${t.name}{}'
} else {
''
}
}
Result {
t.typ.empty_value()
}
Boolean {
'false'
}
Integer {
'0'
}
Alias {
''
}
String {
"''"
}
Function {
''
}
Void {
''
}
}
}
}

View File

@@ -11,11 +11,10 @@ pub:
overwrite bool
document bool
prefix string
compile bool // whether to compile the written code
test bool // whether to test the written code
compile bool // whether to compile the written code
test bool // whether to test the written code
}
interface ICodeItem {
vgen() string
}
@@ -53,7 +52,6 @@ pub fn (import_ Import) vgen() string {
return 'import ${import_.mod} ${types_str}'
}
pub fn vgen_generics(generics map[string]string) string {
if generics.keys().len == 0 {
return ''
@@ -67,4 +65,4 @@ pub fn vgen_generics(generics map[string]string) string {
pub fn (custom CustomCode) vgen() string {
return custom.text
}
}

View File

@@ -20,9 +20,9 @@ pub mut:
path string
force bool
hasconfig bool = true
playonly bool
play_name string // e.g. docusaurus is what we look for
module_path string // e.g.freeflowuniverse.herolib.web.docusaurus
playonly bool
play_name string // e.g. docusaurus is what we look for
module_path string // e.g.freeflowuniverse.herolib.web.docusaurus
}
pub enum Cat {
@@ -83,5 +83,4 @@ fn args_get(path string) !GeneratorArgs {
}
}
return error("can't find hero_code.generate_client or hero_code.generate_installer in ${path}")
}

View File

@@ -9,18 +9,17 @@ pub mut:
reset bool // regenerate all, dangerous !!!
interactive bool // if we want to ask
path string
playonly bool
playonly bool
model ?GenModel
cat ?Cat
}
pub struct PlayArgs {
pub mut:
name string
modulepath string
name string
modulepath string
}
// the default to start with
//
// reset bool // regenerate all, dangerous !!!
@@ -29,8 +28,8 @@ pub mut:
// model ?GenModel
// cat ?Cat
//
// will return the module path where we need to execute a play command as well as the name of
pub fn do(args_ GenerateArgs) ! PlayArgs{
// will return the module path where we need to execute a play command as well as the name of
pub fn do(args_ GenerateArgs) !PlayArgs {
mut args := args_
console.print_header('Generate code for path: ${args.path} (reset:${args.reset}, interactive:${args.interactive})')
@@ -74,15 +73,13 @@ pub fn do(args_ GenerateArgs) ! PlayArgs{
console.print_debug(args)
//only generate if playonly is false and there is a classname
if !args.playonly && model.classname.len>0{
// only generate if playonly is false and there is a classname
if !args.playonly && model.classname.len > 0 {
generate(args)!
}
return PlayArgs{
name: model.play_name
modulepath: model.module_path
name: model.play_name
modulepath: model.module_path
}
}

View File

@@ -19,8 +19,8 @@ pub mut:
startupmanager bool = true
build bool = true
hasconfig bool = true
cat Cat // dont' set default
play_name string // e.g. docusaurus is what we look for
cat Cat // dont' set default
play_name string // e.g. docusaurus is what we look for
module_path string // e.g.freeflowuniverse.herolib.web.docusaurus
}
@@ -111,28 +111,26 @@ pub fn gen_model_get(path string, create bool) !GenModel {
model.play_name = model.name
pathsub:=path.replace('${os.home_dir()}/code/github/','')
model.module_path = pathsub.replace("/",".").replace(".lib.",".")
pathsub := path.replace('${os.home_dir()}/code/github/', '')
model.module_path = pathsub.replace('/', '.').replace('.lib.', '.')
// !!hero_code.play
// !!hero_code.play
// name:'docusaurus'
mut play_actions := plbook.find(filter: 'hero_code.play')!
if play_actions.len>1{
return error("should have max 1 hero_code.play action in ${config_path.path}")
if play_actions.len > 1 {
return error('should have max 1 hero_code.play action in ${config_path.path}')
}
if play_actions.len==1{
if play_actions.len == 1 {
mut p := play_actions[0].params
model.play_name = p.get_default('name',model.name)!
model.play_name = p.get_default('name', model.name)!
}
if model.module_path.contains("docusaurus"){
if model.module_path.contains('docusaurus') {
println(model)
println("4567ujhjk")
println('4567ujhjk')
exit(0)
}
return model
}

View File

@@ -10,7 +10,7 @@ pub mut:
reset bool // regenerate all, dangerous !!!
interactive bool // if we want to ask
path string
playonly bool
playonly bool
}
// scan over a set of directories call the play where
@@ -38,7 +38,12 @@ pub fn scan(args ScannerArgs) ! {
pparent := p.parent()!
path_module := pparent.path
if os.exists('${path_module}/.heroscript') {
do(interactive: args.interactive, path: path_module, reset: args.reset, playonly:args.playonly)!
do(
interactive: args.interactive
path: path_module
reset: args.reset
playonly: args.playonly
)!
}
}
}

View File

@@ -70,8 +70,8 @@ fn cmd_generator_execute(cmd Command) ! {
mut installer := cmd.flags.get_bool('installer') or { false }
mut path := cmd.flags.get_string('path') or { '' }
if playonly{
force=true
if playonly {
force = true
}
if path == '' {
@@ -86,7 +86,7 @@ fn cmd_generator_execute(cmd Command) ! {
}
if scan {
generic.scan(path: path, reset: reset, force: force, cat: cat, playonly:playonly)!
generic.scan(path: path, reset: reset, force: force, cat: cat, playonly: playonly)!
} else {
generic.generate(path: path, reset: reset, force: force, cat: cat)!
}

View File

@@ -52,7 +52,7 @@ pub fn get_dir(args_ GetArgs) !Path {
p2.check()
if args.delete {
p2.delete()!
}
}
p2.absolute()
if p2.exist == .no {
if args.create {
@@ -67,7 +67,6 @@ pub fn get_dir(args_ GetArgs) !Path {
if args.empty {
p2.empty()!
}
}
return p2
}

View File

@@ -61,5 +61,4 @@ pub fn (mut path Path) copy(args_ CopyArgs) ! {
dest.check()
}
}

View File

@@ -50,7 +50,9 @@ pub:
pub fn (mut q RedisRpc) call(args RPCArgs) !string {
timeout := if args.timeout == 0 {
u64(60000)
} else {args.timeout}
} else {
args.timeout
}
retqueue := rand.uuid_v4()
now := time.now().unix()
message := Message{
@@ -92,7 +94,7 @@ pub fn (mut q RedisRpc) result(timeout u64, retqueue string) !string {
pub struct ProcessParams {
pub:
interval time.Duration = time.millisecond * 10
timeout u64
timeout u64
}
// to be used by processor, to get request and execute, this is the server side of a RPC mechanism

View File

@@ -1,4 +1,4 @@
module texttools
module texttools
pub fn snake_case(s string) string {
return separate_words(s).join('_')
@@ -35,4 +35,4 @@ fn separate_words(s string) []string {
words << word.to_lower()
}
return words
}
}

View File

@@ -84,12 +84,11 @@ pub fn name_fix_no_underscore(name string) string {
return x
}
<<<<<<< HEAD
<<<<<<< HEAD
// remove underscores and extension
pub fn name_fix_no_underscore_no_ext(name_ string) string {
return name_fix_keepext(name_).all_before_last('.').replace('_', '')
=======
}
pub fn name_fix_snake_to_pascal(name string) string {
x := name.replace('_', ' ')
p := x.title().replace(' ', '')
@@ -122,19 +121,6 @@ pub fn name_fix_dot_notation_to_snake_case(name string) string {
return name.replace('.', '_')
}
// normalize a file path while preserving path structure
pub fn path_fix(path_ string) string {
if path_.len == 0 {
return ''
}
return "${path_.trim('/')}"
>>>>>>> development_ourdb_new
=======
// remove underscores and extension
pub fn name_fix_no_underscore_no_ext(name_ string) string {
return name_fix_keepext(name_).all_before_last('.').replace('_', '')
}
// Normalizes a path component (directory or file name without extension)
fn normalize_component(comp string) string {
mut result := comp.to_lower()
@@ -250,7 +236,6 @@ pub fn path_fix(path_ string) string {
}
return result
>>>>>>> development_actions007
}
// normalize a file path while preserving path structure