all repos

viye @ f677b32

my shot at reimplementing xiki
11 files changed, 26 insertions(+), 45 deletions(-)
strip body of ": "
Author: Oleksandr Smirnov olexsmir@gmail.com
Committed at: 2026-08-27 23:21:11 +0300
Authored at: 2026-08-27 23:20:08 +0300
Change ID: vuvrlxmmwytluotqsqzuqlqyxvqlvrqq
Parent: 503d76b
M internal/plumbing/config/config.go
···
        21
        21
         	if len(c.Body) > 0 {

      
        22
        22
         		seen := make(map[string]bool, len(c.Body))

      
        23
        23
         		for _, line := range c.Body {

      
        24
        
        -			line = strings.TrimPrefix(line, ": ")

      
        25
        24
         			key, val, ok := strings.Cut(line, " = ")

      
        26
        25
         			if !ok {

      
        27
        26
         				continue

      
M internal/plumbing/config/config_test.go
···
        43
        43
         

      
        44
        44
         		got, err := (Tool{}).Execute(&viye.Context{

      
        45
        45
         			Path: []string{"config"},

      
        46
        
        -			Body: []string{": name = olex"},

      
        
        46
        +			Body: []string{"name = olex"},

      
        47
        47
         		})

      
        48
        48
         		is.Err(t, err, nil)

      
        49
        49
         		is.Equal(t, ": name = olex\n\n", got)

      ···
        58
        58
         

      
        59
        59
         		got, err := (Tool{}).Execute(&viye.Context{

      
        60
        60
         			Path: []string{"config"},

      
        61
        
        -			Body: []string{": a = updated"},

      
        
        61
        +			Body: []string{"a = updated"},

      
        62
        62
         		})

      
        63
        63
         		is.Err(t, err, nil)

      
        64
        64
         		is.Equal(t, ": a = updated\n\n", got)

      ···
        70
        70
         

      
        71
        71
         		_, err := (Tool{}).Execute(&viye.Context{

      
        72
        72
         			Path: []string{"config"},

      
        73
        
        -			Body: []string{": my key = val"},

      
        
        73
        +			Body: []string{"my key = val"},

      
        74
        74
         		})

      
        75
        75
         		is.Err(t, err, `contains spaces`)

      
        76
        76
         	})

      
M internal/plumbing/curl/curl.go
···
        18
        18
         	defer cancel()

      
        19
        19
         

      
        20
        20
         	args := append([]string{"-sSL"}, c.Args...)

      
        21
        
        -	args = append(args, viye.ParseData(c.Body)...)

      
        
        21
        +	args = append(args, c.Body...)

      
        22
        22
         	cmd := exec.CommandContext(ctx, "curl", args...)

      
        23
        23
         	cmd.Dir = c.Dir

      
        24
        24
         

      
M internal/plumbing/curl/curl_test.go
···
        33
        33
         		got, err := (Tool{}).Execute(&viye.Context{

      
        34
        34
         			Cmd:  "curl",

      
        35
        35
         			Args: []string{"--version"},

      
        36
        
        -			Body: []string{": --help"},

      
        
        36
        +			Body: []string{"--help"},

      
        37
        37
         			Dir:  ".",

      
        38
        38
         		})

      
        39
        39
         		is.Err(t, err, nil)

      
M internal/plumbing/http/http.go
···
        28
        28
         		return "", errors.New("please provide an url")

      
        29
        29
         	}

      
        30
        30
         

      
        31
        
        -	headers, body, err := parseBody(viye.ParseData(c.Body))

      
        
        31
        +	headers, body, err := parseBody(c.Body)

      
        32
        32
         	if err != nil {

      
        33
        33
         		return "", fmt.Errorf("body parsing error: %v", err)

      
        34
        34
         	}

      
M internal/plumbing/http/http_test.go
···
        68
        68
         		got, err := (Tool{}).Execute(&viye.Context{

      
        69
        69
         			Cmd:  "post",

      
        70
        70
         			Args: []string{server.URL},

      
        71
        
        -			Body: []string{": test body"},

      
        
        71
        +			Body: []string{"test body"},

      
        72
        72
         		})

      
        73
        73
         		is.Err(t, err, nil)

      
        74
        74
         		is.Equal(t, "| 201\tcreated\n", got)

      ···
        84
        84
         		_, err := (Tool{}).Execute(&viye.Context{

      
        85
        85
         			Cmd:  "get",

      
        86
        86
         			Args: []string{server.URL},

      
        87
        
        -			Body: []string{": Accept: application/json"},

      
        
        87
        +			Body: []string{"Accept: application/json"},

      
        88
        88
         		})

      
        89
        89
         		is.Err(t, err, nil)

      
        90
        90
         	})

      
M internal/plumbing/json/json.go
···
        20
        20
         

      
        21
        21
         	m := make(map[string]string)

      
        22
        22
         	for _, line := range c.Body {

      
        23
        
        -		line = strings.TrimPrefix(line, ": ")

      
        24
        23
         		before, after, ok := strings.Cut(line, ":")

      
        25
        24
         		if !ok {

      
        26
        25
         			continue

      
M internal/plumbing/json/json_test.go
···
        21
        21
         		"no body":          {want: ": name: your name\n: age: 0\n"},

      
        22
        22
         		"empty body slice": {want: ": name: your name\n: age: 0\n"},

      
        23
        23
         		"single key": {

      
        24
        
        -			body: []string{": name: olex"},

      
        
        24
        +			body: []string{"name: olex"},

      
        25
        25
         			want: `| {"name":"olex"}` + "\n",

      
        26
        26
         		},

      
        27
        27
         		"multiple keys": {

      
        28
        
        -			body: []string{": name: olex", ": age: 30"},

      
        
        28
        +			body: []string{"name: olex", "age: 30"},

      
        29
        29
         			want: `| {"age":"30","name":"olex"}` + "\n",

      
        30
        30
         		},

      
        31
        31
         		"values with spaces": {

      
        32
        
        -			body: []string{": title: hello world"},

      
        
        32
        +			body: []string{"title: hello world"},

      
        33
        33
         			want: `| {"title":"hello world"}` + "\n",

      
        34
        34
         		},

      
        35
        35
         		"keys with spaces": {

      
        36
        
        -			body: []string{": my key: value"},

      
        
        36
        +			body: []string{"my key: value"},

      
        37
        37
         			want: `| {"my key":"value"}` + "\n",

      
        38
        38
         		},

      
        39
        39
         		"line without colon separator": {

      
        40
        
        -			body: []string{": justtext"},

      
        
        40
        +			body: []string{"justtext"},

      
        41
        41
         			want: `| {}` + "\n",

      
        42
        42
         		},

      
        43
        43
         		"line without : prefix": {

      ···
        45
        45
         			want: `| {"name":"olex"}` + "\n",

      
        46
        46
         		},

      
        47
        47
         		"mixed valid and invalid": {

      
        48
        
        -			body: []string{": name: olex", "garbage", ": age: 30"},

      
        
        48
        +			body: []string{"name: olex", "garbage", "age: 30"},

      
        49
        49
         			want: `| {"age":"30","name":"olex"}` + "\n",

      
        50
        50
         		},

      
        51
        51
         		"empty key": {

      
        52
        
        -			body: []string{": : value"},

      
        
        52
        +			body: []string{": value"},

      
        53
        53
         			want: `| {}` + "\n",

      
        54
        54
         		},

      
        55
        55
         		"trailing whitespace in key": {

      
        56
        
        -			body: []string{": name  : olex"},

      
        
        56
        +			body: []string{"name  : olex"},

      
        57
        57
         			want: `| {"name":"olex"}` + "\n",

      
        58
        58
         		},

      
        59
        59
         		"trailing whitespace in value": {

      
        60
        
        -			body: []string{": name: olex  "},

      
        
        60
        +			body: []string{"name: olex  "},

      
        61
        61
         			want: `| {"name":"olex"}` + "\n",

      
        62
        62
         		},

      
        63
        63
         		"empty value": {

      
        64
        
        -			body: []string{": name: "},

      
        
        64
        +			body: []string{"name: "},

      
        65
        65
         			want: `| {"name":""}` + "\n",

      
        66
        66
         		},

      
        67
        67
         	}

      
M internal/viye/format.go
···
        33
        33
         	}

      
        34
        34
         	return strings.Join(s, "\n")

      
        35
        35
         }

      
        36
        
        -

      
        37
        
        -func ParseData(body []string) []string {

      
        38
        
        -	var res []string

      
        39
        
        -	for _, line := range body {

      
        40
        
        -		res = append(res, strings.TrimPrefix(line, ": "))

      
        41
        
        -	}

      
        42
        
        -	return res

      
        43
        
        -}

      
M internal/viye/viye.go
···
        5
        5
         	"fmt"

      
        6
        6
         	"io"

      
        7
        7
         	"os"

      
        
        8
        +	"strings"

      
        8
        9
         	"time"

      
        9
        10
         )

      
        10
        11
         

      ···
        20
        21
         	Path []string // ancestor chain [root, ..., target]

      
        21
        22
         	Cmd  string

      
        22
        23
         	Args []string

      
        23
        
        -	Body []string // body lines from : children

      
        
        24
        +	Body []string // body lines, ": " prefix stripped

      
        24
        25
         

      
        25
        26
         	dispatch func(*Context) (string, error) // set by [Viye.dispatch] for tool chaining

      
        26
        27
         }

      ···
        114
        115
         

      
        115
        116
         // splitArgs builds path and body from args.

      
        116
        117
         // Everything before "--" is the path (each arg is one component).

      
        117
        
        -// Everything after "--" is the body (kept as-is, one element per line).

      
        
        118
        +// Everything after "--" is the body (one element per line, ": " prefix stripped).

      
        118
        119
         // If there's no "--", body is nil.

      
        119
        120
         func splitArgs(args []string) (path []string, body []string) {

      
        120
        121
         	sawSep := false

      ···
        126
        127
         		if !sawSep {

      
        127
        128
         			path = append(path, arg)

      
        128
        129
         		} else {

      
        129
        
        -			body = append(body, arg)

      
        
        130
        +			body = append(body, strings.TrimPrefix(arg, ": "))

      
        130
        131
         		}

      
        131
        132
         	}

      
        132
        133
         	return

      
M internal/viye/viye_test.go
···
        13
        13
         		{[]string{"./"}, []string{"./"}, nil},

      
        14
        14
         		{[]string{"././foo", "./bar"}, []string{"././foo", "./bar"}, nil},

      
        15
        15
         		{[]string{"demo"}, []string{"demo"}, nil},

      
        16
        
        -		{[]string{"demo", "--", ": name: olex"}, []string{"demo"}, []string{": name: olex"}},

      
        17
        
        -		{[]string{"demo", "--", ": name: olex", ": age: 30"}, []string{"demo"}, []string{": name: olex", ": age: 30"}},

      
        18
        
        -		{[]string{"--", ": body"}, nil, []string{": body"}},

      
        
        16
        +		{[]string{"demo", "--", ": name: olex"}, []string{"demo"}, []string{"name: olex"}},

      
        
        17
        +		{[]string{"demo", "--", ": name: olex", ": age: 30"}, []string{"demo"}, []string{"name: olex", "age: 30"}},

      
        
        18
        +		{[]string{"--", ": body"}, nil, []string{"body"}},

      
        
        19
        +		{[]string{"demo", "--", "raw body"}, []string{"demo"}, []string{"raw body"}},

      
        19
        20
         	}

      
        20
        21
         	for _, tt := range tests {

      
        21
        22
         		got, gotB := splitArgs(tt.args)

      ···
        47
        48
         		gotCmd, gotArgs := splitLeaf(tt.path)

      
        48
        49
         		is.Equal(t, tt.cmd, gotCmd)

      
        49
        50
         		is.Equal(t, tt.wantArgs, gotArgs)

      
        50
        
        -	}

      
        51
        
        -}

      
        52
        
        -

      
        53
        
        -func TestContext_ParseData(t *testing.T) {

      
        54
        
        -	for _, tt := range []struct{ inp, want []string }{

      
        55
        
        -		{[]string{": line1", ": line2"}, []string{"line1", "line2"}},

      
        56
        
        -		{[]string{": line1", "line2"}, []string{"line1", "line2"}},

      
        57
        
        -		{[]string{"line1", "line2"}, []string{"line1", "line2"}},

      
        58
        
        -		{[]string{"| not data", "| again not data"}, []string{"| not data", "| again not data"}},

      
        59
        
        -	} {

      
        60
        
        -		is.Equal(t, tt.want, ParseData(tt.inp))

      
        61
        51
         	}

      
        62
        52
         }

      
        63
        53