Skip to content

Commit

Permalink
Merge pull request #887 from lmorg/develop
Browse files Browse the repository at this point in the history
v6.4
  • Loading branch information
lmorg authored Nov 22, 2024
2 parents c037883 + 7328719 commit 95be39e
Show file tree
Hide file tree
Showing 123 changed files with 3,284 additions and 986 deletions.
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ const Name = "murex"
// Format of version string should be "$(Major).$(Minor).$(Revision) ($Branch)"
const (
Major = 6
Minor = 3
Revision = 4225
Minor = 4
Revision = 373
Branch = "develop"
BuildDate = "2024-09-18 22:09:49"
BuildDate = "2024-11-22 22:18:43"
)

// Copyright is the copyright owner string
Expand Down
19 changes: 7 additions & 12 deletions builtins/core/element/element_doc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,39 +62,34 @@
» config -> [[ \|shell\|syntax-highlighting\|Data-Type ]]
bool
» config -> [[ >shell>syntax-highlighting>Data-Type ]]
» config -> [[ 😅shell😅syntax-highlighting😅Data-Type ]]
bool
```
However there are a few of caveats:
1. Currently **element** does not support unicode separators. All separators
must be 1 byte characters. This limitation is highlighted as a bug, albeit
a low priority one. If this limitation does directly affect you then raise
an issue on GitHub to get the priority bumped up.
2. Any shell tokens (eg pipe `|`, `;`, `}`, etc) will need to be escaped. For
1. Any shell tokens (eg pipe `|`, `;`, `}`, etc) will need to be escaped. For
readability reasons it is recommended not to use such characters even
though it is technically possible to.
```
```
# Would fail because the semi-colon is an unescaped / unquoted shell token
config -> [[ ;shell-syntax-highlighting;Data-Type ]]
```
```
3. Please also make sure you don't use a character that is also used inside
2. Please also make sure you don't use a character that is also used inside
key names because keys _cannot_ be escaped. For example both of the
following would fail:
```
```
# Would fail because 'syntax-highlighting' and 'Data-Type' both also contain
# the separator character
config -> [[ -shell-syntax-highlighting-Data-Type ]]
# Would fail because you cannot escape key names (escaping happens at the
# shell parser level rather than command parameter level)
config -> [[ -shell-syntax\-highlighting-Data\-Type ]]
```
```
### Quoting parameters
Expand Down
42 changes: 0 additions & 42 deletions builtins/core/io/file.go → builtins/core/io/pt.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import (

func init() {
lang.DefineMethod("pt", cmdPipeTelemetry, types.Any, types.Any)
lang.DefineMethod(">", cmdWriteFile, types.Any, types.Null)
lang.DefineMethod("fwrite", cmdWriteFile, types.Any, types.Null)
lang.DefineMethod(">>", cmdAppendFile, types.Any, types.Null)
lang.DefineMethod("fappend", cmdAppendFile, types.Any, types.Null)
}

func cmdPipeTelemetry(p *lang.Process) error {
Expand Down Expand Up @@ -54,41 +50,3 @@ func cmdPipeTelemetry(p *lang.Process) error {
stats()
return err
}

func cmdWriteFile(p *lang.Process) error {
p.Stdout.SetDataType(types.Null)

name, err := p.Parameters.String(0)
if err != nil {
return err
}

file, err := os.Create(name)
if err != nil {
return err
}

defer file.Close()

_, err = io.Copy(file, p.Stdin)
return err
}

func cmdAppendFile(p *lang.Process) error {
p.Stdout.SetDataType(types.Null)

name, err := p.Parameters.String(0)
if err != nil {
return err
}

file, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0664)
if err != nil {
return err
}

defer file.Close()

_, err = io.Copy(file, p.Stdin)
return err
}
37 changes: 0 additions & 37 deletions builtins/core/io/file_doc.yaml → builtins/core/io/pt_doc.yaml
Original file line number Diff line number Diff line change
@@ -1,40 +1,3 @@
- DocumentID: file-truncate
Title: >+
Truncate File (`>`)
CategoryID: parser
SubCategoryIDs: [ commands.fs, parser.pipes ]
Summary: >-
Writes stdin to disk - overwriting contents if file already exists
Description: |-
Redirects output to file.
If a file already exists, the contents will be truncated (overwritten).
Otherwise a new file is created.
Usage: |-
```
<stdin> |> filename
```
Examples: |-
```
g * |> files.txt
```
Detail:
Synonyms:
- ">"
- "|>"
- "fwrite"
Related:
- file-append
- pipe
- g
- tmp
- pipe-arrow
- pipe-posix
- namedpipe
- pipe-err



- DocumentID: pt
Title: >+
Get Pipe Status (`pt`)
Expand Down
18 changes: 18 additions & 0 deletions builtins/core/io/pt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io_test

import (
"testing"

"github.com/lmorg/murex/test"
)

func TestPipeTelemetry(t *testing.T) {
tests := []test.MurexTest{
{
Block: `tout * 12345 -> pt`,
Stdout: `12345`,
},
}

test.RunMurexTests(tests, t)
}
123 changes: 123 additions & 0 deletions builtins/core/io/write.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package io

import (
"bytes"
"fmt"
"io"
"os"

"github.com/lmorg/murex/lang"
"github.com/lmorg/murex/lang/state"
"github.com/lmorg/murex/lang/types"
"github.com/lmorg/murex/utils/lists"
)

func init() {
lang.DefineMethod(">", cmdTruncateFile, types.Any, types.Null)
lang.DefineMethod("fwrite", cmdTruncateFile, types.Any, types.Null)
lang.DefineMethod(">>", cmdAppendFile, types.Any, types.Null)
lang.DefineMethod("fappend", cmdAppendFile, types.Any, types.Null)
}

const (
_WAIT_EOF_SHORT = "-w"
_WAIT_EOF_LONG = "--wait-for-eof"
_IGNORE_PIPELINE_SHORT = "-i"
_IGNORE_PIPELINE_LONG = "--ignore-pipeline-check"
)

func cmdTruncateFile(p *lang.Process) error { return writeFile(p, truncateFile) }
func cmdAppendFile(p *lang.Process) error { return writeFile(p, appendFile) }

func writeFile(p *lang.Process, fn func(io.Reader, string) error) error {
p.Stdout.SetDataType(types.Null)

filename, err := p.Parameters.String(0)
if err != nil {
return err
}

if !p.IsMethod {
// nothing to write
return fn(bytes.NewBuffer([]byte{}), filename)
}

if filename == _IGNORE_PIPELINE_SHORT || filename == _IGNORE_PIPELINE_LONG {
parameter2, err := p.Parameters.String(1)
if err == nil {
return fn(p.Stdin, parameter2)
}
// no second parameter so lets assume the flag was actually a file name
}

wait := filename == _WAIT_EOF_SHORT || filename == _WAIT_EOF_LONG

if wait {
parameter2, err := p.Parameters.String(1)
if err == nil {
filename = parameter2

} else {
// no second parameter so lets assume the flag was actually a file name
wait = false
}
}

if !wait {
wait = isFileOpen(p, filename)
if wait {
_, _ = p.Stderr.Writeln([]byte(fmt.Sprintf("warning: '%s' appears as a parameter elsewhere in the pipeline so I'm going to cache the file in RAM before writing to disk.\n : This message can be suppressed using `%s` or `%s`.", filename, _WAIT_EOF_LONG, _IGNORE_PIPELINE_LONG)))
}
}

if !wait {
return fn(p.Stdin, filename)
}

b, err := p.Stdin.ReadAll()
if err != nil {
return err
}

return fn(bytes.NewReader(b), filename)
}

func isFileOpen(p *lang.Process, filename string) bool {
p = p.Previous
for {
if p.State.Get() < state.Executing {
continue
}
if lists.Match(p.Parameters.StringArray(), filename) {
return true
}
if !p.IsMethod || p.Id == lang.ShellProcess.Id {
return false
}
p = p.Previous
}
}

func truncateFile(reader io.Reader, filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}

defer file.Close()

_, err = io.Copy(file, reader)
return err
}

func appendFile(reader io.Reader, filename string) error {
file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0664)
if err != nil {
return err
}

defer file.Close()

_, err = io.Copy(file, reader)
return err
}
Loading

0 comments on commit 95be39e

Please sign in to comment.