From b40015deb7e383eb2cbf6050d31af538627999b7 Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Wed, 6 Mar 2024 12:56:44 -0300 Subject: [PATCH] first preliminary version of obiscript. Former-commit-id: 0d2c0fc5e33e0873ba5c04aca4cf7dd69aa83c90 --- cmd/obitools/obiscript/main.go | 57 ++++++++ go.mod | 18 ++- go.sum | 72 +++++++++++ go.work.sum | 5 +- pkg/obilua/lua.go | 140 ++++++++++++++++++++ pkg/obilua/lua_push_interface.go | 193 ++++++++++++++++++++++++++++ pkg/obilua/obilib.go | 7 + pkg/obilua/obiseq.go | 154 ++++++++++++++++++++++ pkg/obitools/obiscript/obiscript.go | 14 ++ pkg/obitools/obiscript/options.go | 83 ++++++++++++ 10 files changed, 739 insertions(+), 4 deletions(-) create mode 100644 cmd/obitools/obiscript/main.go create mode 100644 pkg/obilua/lua.go create mode 100644 pkg/obilua/lua_push_interface.go create mode 100644 pkg/obilua/obilib.go create mode 100644 pkg/obilua/obiseq.go create mode 100644 pkg/obitools/obiscript/obiscript.go create mode 100644 pkg/obitools/obiscript/options.go diff --git a/cmd/obitools/obiscript/main.go b/cmd/obitools/obiscript/main.go new file mode 100644 index 0000000..224c947 --- /dev/null +++ b/cmd/obitools/obiscript/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "os" + + log "github.com/sirupsen/logrus" + + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiscript" +) + +func main() { + + defer obiseq.LogBioSeqStatus() + + // go tool pprof -http=":8000" ./obipairing ./cpu.pprof + // f, err := os.Create("cpu.pprof") + // if err != nil { + // log.Fatal(err) + // } + // pprof.StartCPUProfile(f) + // defer pprof.StopCPUProfile() + + // go tool trace cpu.trace + // ftrace, err := os.Create("cpu.trace") + // if err != nil { + // log.Fatal(err) + // } + // trace.Start(ftrace) + // defer trace.Stop() + + optionParser := obioptions.GenerateOptionParser(obiscript.OptionSet) + + _, args := optionParser(os.Args) + + if obiscript.CLIAskScriptTemplate() { + fmt.Print(obiscript.CLIScriptTemplate()) + os.Exit(0) + } + + sequences, err := obiconvert.CLIReadBioSequences(args...) + + if err != nil { + log.Errorf("Cannot open file (%v)", err) + os.Exit(1) + } + + annotator := obiscript.CLIScriptPipeline() + obiconvert.CLIWriteBioSequences(sequences.Pipe(annotator), true) + + obiiter.WaitForLastPipe() + +} diff --git a/go.mod b/go.mod index 1d5efa2..a91c367 100644 --- a/go.mod +++ b/go.mod @@ -23,10 +23,22 @@ require ( ) require ( + github.com/alecthomas/chroma v0.10.0 // indirect + github.com/alexeyco/binder v0.0.0-20180729220023-2a21303f588a // indirect + github.com/chzyer/readline v1.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.2.1 // indirect - github.com/kr/text v0.1.0 // indirect + github.com/dlclark/regexp2 v1.11.0 // indirect + github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect + golang.org/x/text v0.13.0 // indirect ) require ( @@ -39,7 +51,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/ulikunitz/xz v0.5.11 golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/term v0.13.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c ) diff --git a/go.sum b/go.sum index dc745ab..65969e2 100644 --- a/go.sum +++ b/go.sum @@ -4,22 +4,48 @@ github.com/PaesslerAG/gval v1.2.2 h1:Y7iBzhgE09IGTt5QgGQ2IdaYYYOU134YGHBThD+wm9E github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac= github.com/PaesslerAG/jsonpath v0.1.0 h1:gADYeifvlqK3R3i2cR5B4DGgxLXIPb3TRTH1mGi0jPI= github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8= +github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= +github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= +github.com/alexeyco/binder v0.0.0-20180729220023-2a21303f588a h1:eVFBuipE7TEjIyfrbnQUTG3dBYEtqrRKXSInpyLv41Y= +github.com/alexeyco/binder v0.0.0-20180729220023-2a21303f588a/go.mod h1:uxLp5y9OziDVlIADUk/fpPnEM479nk3gNNZEotIoKoA= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/chen3feng/stl4go v0.1.1 h1:0L1+mDw7pomftKDruM23f1mA7miavOj6C6MZeadzN2Q= github.com/chen3feng/stl4go v0.1.1/go.mod h1:5ml3psLgETJjRJnMbPE+JiHLrCpt+Ajc2weeTECXzWU= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/daichi-m/go18ds v1.12.1 h1:Pjc3IApmN4qtDiovGP9MvMpIzgZle3SHUcNaA5j46bg= github.com/daichi-m/go18ds v1.12.1/go.mod h1:wc2dURUr8aMxxC4Mn5ObJGVM7uIKU8JagY4nhtonXq8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM= +github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= @@ -27,12 +53,22 @@ github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -43,6 +79,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rrethy/ahocorasick v1.0.0 h1:YKkCB+E5PXc0xmLfMrWbfNht8vG9Re97IHSWZk/Lk8E= github.com/rrethy/ahocorasick v1.0.0/go.mod h1:nq8oScE7Vy1rOppoQxpQiiDmPHuKCuk9rXrNcxUV3R0= github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE= @@ -62,23 +99,58 @@ github.com/traefik/yaegi v0.15.1/go.mod h1:AVRxhaI2G+nUsaM1zyktzwXn69G3t/AuTDrCi github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.work.sum b/go.work.sum index c2c7d5c..be52f59 100644 --- a/go.work.sum +++ b/go.work.sum @@ -2,6 +2,9 @@ git.sr.ht/~sbinet/gg v0.3.1 h1:LNhjNn8DerC8f9DHLz6lS0YYul/b602DUxDgGkd/Aik= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780 h1:tFh1tRc4CA31yP6qDcu+Trax5wW5GuMxvkIba07qVLY= github.com/go-fonts/liberation v0.3.0 h1:3BI2iaE7R/s6uUUtzNCjo3QijJu3aS4wmrMgfSpYQ+8= github.com/go-fonts/liberation v0.3.0/go.mod h1:jdJ+cqF+F4SUL2V+qxBth8fvBpBDS7yloUL5Fi8GTGY= @@ -19,6 +22,7 @@ github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcM github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= @@ -26,7 +30,6 @@ golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= diff --git a/pkg/obilua/lua.go b/pkg/obilua/lua.go new file mode 100644 index 0000000..a64ea27 --- /dev/null +++ b/pkg/obilua/lua.go @@ -0,0 +1,140 @@ +package obilua + +import ( + "bytes" + "os" + + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" + log "github.com/sirupsen/logrus" + lua "github.com/yuin/gopher-lua" + "github.com/yuin/gopher-lua/parse" +) + +func NewInterpreter() *lua.LState { + lua := lua.NewState() + + RegisterObilib(lua) + + return lua +} + +func Compile(program []byte, name string) (*lua.FunctionProto, error) { + + reader := bytes.NewReader(program) + chunk, err := parse.Parse(reader, name) + if err != nil { + return nil, err + } + + proto, err := lua.Compile(chunk, name) + if err != nil { + return nil, err + } + return proto, nil +} + +func CompileScript(filePath string) (*lua.FunctionProto, error) { + program, err := os.ReadFile(filePath) + + if err != nil { + return nil, err + } + + return Compile(program, filePath) +} + +func LuaWorker(proto *lua.FunctionProto) obiseq.SeqWorker { + interpreter := NewInterpreter() + lfunc := interpreter.NewFunctionFromProto(proto) + + f := func(sequence *obiseq.BioSequence) (obiseq.BioSequenceSlice, error) { + interpreter.SetGlobal("sequence", obiseq2Lua(interpreter, sequence)) + interpreter.Push(lfunc) + err := interpreter.PCall(0, lua.MultRet, nil) + + return obiseq.BioSequenceSlice{sequence}, err + } + + return f +} + +func LuaProcessor(iterator obiiter.IBioSequence, name, program string, breakOnError bool, nworkers int) obiiter.IBioSequence { + newIter := obiiter.MakeIBioSequence() + + if nworkers <= 0 { + nworkers = obioptions.CLIParallelWorkers() + } + + newIter.Add(nworkers) + + go func() { + newIter.WaitAndClose() + }() + + bp := []byte(program) + proto, err := Compile(bp, name) + + if err != nil { + log.Fatalf("Cannot compile script %s : %v", name, err) + } + + ff := func(iterator obiiter.IBioSequence) { + w := LuaWorker(proto) + sw := obiseq.SeqToSliceWorker(w, false) + + // iterator = iterator.SortBatches() + + for iterator.Next() { + seqs := iterator.Get() + slice := seqs.Slice() + ns, err := sw(slice) + + if err != nil { + if breakOnError { + log.Fatalf("Error during Lua sequence processing : %v", err) + } else { + log.Warnf("Error during Lua sequence processing : %v", err) + } + } + + newIter.Push(obiiter.MakeBioSequenceBatch(seqs.Order(), ns)) + seqs.Recycle(false) + } + + newIter.Done() + } + + for i := 1; i < nworkers; i++ { + go ff(iterator.Split()) + } + + go ff(iterator) + + if iterator.IsPaired() { + newIter.MarkAsPaired() + } + + return newIter + +} + +func LuaPipe(name, program string, breakOnError bool, nworkers int) obiiter.Pipeable { + + f := func(input obiiter.IBioSequence) obiiter.IBioSequence { + return LuaProcessor(input, name, program, breakOnError, nworkers) + } + + return f +} + +func LuaScriptPipe(filename string, breakOnError bool, nworkers int) obiiter.Pipeable { + program, err := os.ReadFile(filename) + + if err != nil { + log.Fatalf("Cannot read script file %s", filename) + } + + return LuaPipe(filename, string(program), breakOnError, nworkers) +} diff --git a/pkg/obilua/lua_push_interface.go b/pkg/obilua/lua_push_interface.go new file mode 100644 index 0000000..a561860 --- /dev/null +++ b/pkg/obilua/lua_push_interface.go @@ -0,0 +1,193 @@ +package obilua + +import ( + "log" + + lua "github.com/yuin/gopher-lua" +) + +// pushInterfaceToLua converts a Go interface{} value to an equivalent Lua value and pushes it onto the stack. +// +// L *lua.LState: the Lua state onto which the value will be pushed. +// val interface{}: the Go interface value to be converted and pushed. This can be a basic type such as string, bool, int, float64, +// or slices and maps of these basic types. Custom complex types will be converted to userdata with a predefined metatable. +// +// No return values. This function operates directly on the Lua state stack. +func pushInterfaceToLua(L *lua.LState, val interface{}) { + switch v := val.(type) { + case string: + L.Push(lua.LString(v)) + case bool: + L.Push(lua.LBool(v)) + case int: + L.Push(lua.LNumber(v)) + case float64: + L.Push(lua.LNumber(v)) + // Add other cases as needed for different types + case map[string]int: + pushMapStringIntToLua(L, v) + case map[string]string: + pushMapStringStringToLua(L, v) + case map[string]bool: + pushMapStringBoolToLua(L, v) + case map[string]float64: + pushMapStringFloat64ToLua(L, v) + case []string: + pushSliceStringToLua(L, v) + case []int: + pushSliceIntToLua(L, v) + case []float64: + pushSliceFloat64ToLua(L, v) + case []bool: + pushSliceBoolToLua(L, v) + case nil: + L.Push(lua.LNil) + default: + log.Fatalf("Cannot deal with value Mv", val) + } +} + +// pushMapStringIntToLua creates a new Lua table and iterates over the Go map to set key-value pairs in the Lua table. It then pushes the Lua table onto the stack. +// +// L *lua.LState - the Lua state +// m map[string]int - the Go map containing string to int key-value pairs +func pushMapStringIntToLua(L *lua.LState, m map[string]int) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go map and set the key-value pairs in the Lua table + for key, value := range m { + L.SetField(luaTable, key, lua.LNumber(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushMapStringStringToLua creates a new Lua table and sets key-value pairs from the Go map, then pushes the Lua table onto the stack. +// +// L *lua.LState, m map[string]string. No return value. +func pushMapStringStringToLua(L *lua.LState, m map[string]string) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go map and set the key-value pairs in the Lua table + for key, value := range m { + L.SetField(luaTable, key, lua.LString(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushMapStringBoolToLua creates a new Lua table, iterates over the Go map, sets the key-value pairs in the Lua table, and then pushes the Lua table onto the stack. +// +// Parameters: +// +// L *lua.LState - the Lua state +// m map[string]bool - the Go map +// +// Return type(s): None +func pushMapStringBoolToLua(L *lua.LState, m map[string]bool) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go map and set the key-value pairs in the Lua table + for key, value := range m { + L.SetField(luaTable, key, lua.LBool(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushMapStringFloat64ToLua pushes a map of string-float64 pairs to a Lua table on the stack. +// +// L *lua.LState - the Lua state +// m map[string]float64 - the map to be pushed to Lua +func pushMapStringFloat64ToLua(L *lua.LState, m map[string]float64) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go map and set the key-value pairs in the Lua table + for key, value := range m { + // Use lua.LNumber since Lua does not differentiate between float and int + L.SetField(luaTable, key, lua.LNumber(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushSliceIntToLua creates a new Lua table and sets the elements of a Go slice in the Lua table. Then, it pushes the Lua table onto the stack. +// +// L *lua.LState, slice []int +// None +func pushSliceIntToLua(L *lua.LState, slice []int) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go slice and set the elements in the Lua table + for _, value := range slice { + // Append the value to the Lua table + // Lua is 1-indexed, so we use the length of the table + 1 as the next index + luaTable.Append(lua.LNumber(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushSliceStringToLua creates a new Lua table and sets the elements in the table from the given Go slice. It then pushes the Lua table onto the stack. +// +// L *lua.LState - The Lua state +// slice []string - The Go slice of strings +func pushSliceStringToLua(L *lua.LState, slice []string) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go slice and set the elements in the Lua table + for _, value := range slice { + // Append the value to the Lua table + luaTable.Append(lua.LString(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushSliceBoolToLua creates a new Lua table and pushes the boolean values from the given slice onto the Lua stack. +// +// L *lua.LState - the Lua state +// slice []bool - the Go slice containing boolean values +func pushSliceBoolToLua(L *lua.LState, slice []bool) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go slice and insert each boolean into the Lua table + for _, value := range slice { + // Lua is 1-indexed, so we use the length of the table + 1 as the next index + luaTable.Append(lua.LBool(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} + +// pushSliceFloat64ToLua creates a new Lua table and pushes it onto the stack. +// +// L *lua.LState - the Lua state +// slice []float64 - the Go slice to be inserted into the Lua table +func pushSliceFloat64ToLua(L *lua.LState, slice []float64) { + // Create a new Lua table + luaTable := L.NewTable() + + // Iterate over the Go slice and insert each float64 into the Lua table + for _, value := range slice { + // Lua is 1-indexed, so we append the value to the Lua table + luaTable.Append(lua.LNumber(value)) + } + + // Push the Lua table onto the stack + L.Push(luaTable) +} diff --git a/pkg/obilua/obilib.go b/pkg/obilua/obilib.go new file mode 100644 index 0000000..a08301a --- /dev/null +++ b/pkg/obilua/obilib.go @@ -0,0 +1,7 @@ +package obilua + +import lua "github.com/yuin/gopher-lua" + +func RegisterObilib(luaState *lua.LState) { + RegisterObiSeq(luaState) +} diff --git a/pkg/obilua/obiseq.go b/pkg/obilua/obiseq.go new file mode 100644 index 0000000..b1395cd --- /dev/null +++ b/pkg/obilua/obiseq.go @@ -0,0 +1,154 @@ +package obilua + +import ( + log "github.com/sirupsen/logrus" + + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" + lua "github.com/yuin/gopher-lua" +) + +func RegisterObiSeq(luaState *lua.LState) { + registerBioSequenceType(luaState) +} + +const luaBioSequenceTypeName = "BioSequence" + +func registerBioSequenceType(luaState *lua.LState) { + bioSequenceType := luaState.NewTypeMetatable(luaBioSequenceTypeName) + luaState.SetGlobal(luaBioSequenceTypeName, bioSequenceType) + luaState.SetField(bioSequenceType, "new", luaState.NewFunction(newObiSeq)) + + luaState.SetField(bioSequenceType, "__index", + luaState.SetFuncs(luaState.NewTable(), + bioSequenceMethods)) +} + +func obiseq2Lua(interpreter *lua.LState, + sequence *obiseq.BioSequence) lua.LValue { + ud := interpreter.NewUserData() + ud.Value = sequence + interpreter.SetMetatable(ud, interpreter.GetTypeMetatable(luaBioSequenceTypeName)) + + return ud +} +func newObiSeq(luaState *lua.LState) int { + seqid := luaState.CheckString(1) + seq := []byte(luaState.CheckString(2)) + + definition := "" + if luaState.GetTop() > 2 { + definition = luaState.CheckString(3) + } + + sequence := obiseq.NewBioSequence(seqid, seq, definition) + + luaState.Push(obiseq2Lua(luaState, sequence)) + return 1 +} + +var bioSequenceMethods = map[string]lua.LGFunction{ + "id": bioSequenceGetSetId, + "sequence": bioSequenceGetSetSequence, + "definition": bioSequenceGetSetDefinition, + "count": bioSequenceGetSetCount, + "taxid": bioSequenceGetSetTaxid, + "attribute": bioSequenceGetSetAttribute, +} + +// checkBioSequence checks if the first argument in the Lua stack is a *obiseq.BioSequence. +// +// This function accepts a pointer to the Lua state and attempts to retrieve a userdata +// that holds a pointer to a BioSequence. If the conversion is successful, it returns +// the *BioSequence. If the conversion fails, it raises a Lua argument error. +// Returns a pointer to obiseq.BioSequence or nil if the argument is not of the expected type. +func checkBioSequence(L *lua.LState) *obiseq.BioSequence { + ud := L.CheckUserData(1) + if v, ok := ud.Value.(*obiseq.BioSequence); ok { + return v + } + L.ArgError(1, "obiseq.BioSequence expected") + return nil +} + +// bioSequenceGetSetId gets the ID of a biosequence or sets a new ID if provided. +// +// This function expects a *lua.LState pointer as its only parameter. +// If a second argument is provided, it sets the new ID for the biosequence. +// It returns 0 if a new ID is set, or 1 after pushing the current ID onto the stack. +func bioSequenceGetSetId(luaState *lua.LState) int { + s := checkBioSequence(luaState) + if luaState.GetTop() == 2 { + s.SetId(luaState.CheckString(2)) + return 0 + } + luaState.Push(lua.LString(s.Id())) + return 1 +} + +func bioSequenceGetSetSequence(luaState *lua.LState) int { + s := checkBioSequence(luaState) + if luaState.GetTop() == 2 { + s.SetSequence([]byte(luaState.CheckString(2))) + return 0 + } + luaState.Push(lua.LString(s.String())) + return 1 +} + +func bioSequenceGetSetDefinition(luaState *lua.LState) int { + s := checkBioSequence(luaState) + if luaState.GetTop() == 2 { + s.SetDefinition(luaState.CheckString(2)) + return 0 + } + luaState.Push(lua.LString(s.Definition())) + return 1 +} + +func bioSequenceGetSetCount(luaState *lua.LState) int { + s := checkBioSequence(luaState) + if luaState.GetTop() == 2 { + s.SetCount(luaState.CheckInt(2)) + return 0 + } + luaState.Push(lua.LNumber(s.Count())) + return 1 +} + +func bioSequenceGetSetTaxid(luaState *lua.LState) int { + s := checkBioSequence(luaState) + if luaState.GetTop() == 2 { + s.SetTaxid(luaState.CheckInt(2)) + return 0 + } + luaState.Push(lua.LNumber(s.Taxid())) + return 1 +} + +func bioSequenceGetSetAttribute(luaState *lua.LState) int { + s := checkBioSequence(luaState) + attName := luaState.CheckString(2) + + if luaState.GetTop() == 3 { + ud := luaState.CheckAny(3) + + log.Infof("ud : %v [%v]", ud, ud.Type()) + // + // Perhaps the code needs some type checking on ud.Value + // It's a first test + // + + s.SetAttribute(attName, ud) + return 0 + } + + value, ok := s.GetAttribute(attName) + + if !ok { + luaState.Push(lua.LNil) + } else { + pushInterfaceToLua(luaState, value) + } + + return 1 +} diff --git a/pkg/obitools/obiscript/obiscript.go b/pkg/obitools/obiscript/obiscript.go new file mode 100644 index 0000000..f2e61ce --- /dev/null +++ b/pkg/obitools/obiscript/obiscript.go @@ -0,0 +1,14 @@ +package obiscript + +import ( + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiiter" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obilua" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obioptions" +) + +func CLIScriptPipeline() obiiter.Pipeable { + + pipe := obilua.LuaScriptPipe(CLIScriptFilename(), true, obioptions.CLIParallelWorkers()) + + return pipe +} diff --git a/pkg/obitools/obiscript/options.go b/pkg/obitools/obiscript/options.go new file mode 100644 index 0000000..5f64ae3 --- /dev/null +++ b/pkg/obitools/obiscript/options.go @@ -0,0 +1,83 @@ +package obiscript + +import ( + "log" + "os" + + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obiconvert" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obitools/obigrep" + "github.com/DavidGamba/go-getoptions" +) + +var _script = "" +var _askTemplate = false + +func ScriptOptionSet(options *getoptions.GetOpt) { + + options.StringVar(&_script, "script", _script, + options.Description("The script to execute."), + options.Alias("S"), + options.Description("Name of a map attribute.")) + + options.BoolVar(&_askTemplate, "template", _askTemplate, + options.Description("Print on the standard output a script template."), + ) +} + +func OptionSet(options *getoptions.GetOpt) { + ScriptOptionSet(options) + obiconvert.OptionSet(options) + obigrep.SequenceSelectionOptionSet(options) +} + +func CLIScriptFilename() string { + return _script +} + +func CLIScript() string { + file, err := os.ReadFile(_script) // Reads the script + if err != nil { + log.Fatalf("cannot read the script file : %s", _script) + } + return string(file) +} + +func CLIAskScriptTemplate() bool { + return _askTemplate +} + +func CLIScriptTemplate() string { + return ` + import { + "sync" + "git.metabarcoding.org/obitools/obitools4/obitools4/pkg/obiseq" + } + // + // Begin function run before the first sequence being processed + // + + func Begin(environment *sync.Map) { + + } + + // + // Begin function run after the last sequence being processed + // + + func End(environment *sync.Map) { + + } + + // + // Worker function run for each sequence validating the selection predicat as specified by + // the command line options. + // + // The function must return the altered sequence. + // If the function returns nil, the sequence is discarded from the output + func Worker(sequence *obiseq.BioSequence, environment *sync.Map) *obiseq.BioSequence { + + + return sequence + } + ` +}