Skip to content

Wrong TCL String representation for Go Built-ins #21

@gtarcea

Description

@gtarcea

Hi,

This is a really great project. I've run into an issue in version version v0.0.0-20260119183325-601d6c2067cd, that doesn't occur in version v0.0.0-20251227222940-8b153391b49e. Specifically the handling of go types when I do feather.OK() call.

In version v0.0.0-20251227222940-8b153391b49e if I have a list of strings they are properly represented as TCL strings. For example:

{name: "file1.txt" path: "/home/gtarcea/proj/Aging/cliuptest/file1.txt" type: "file" size: 37 mtime: 2026-02-02T15:36:37Z ctime: 2026-02-02T15:36:37Z} {name: "subdir" path: "/home/gtarcea/proj/Aging/cliuptest/subdir" type: "directory" size: 4096 mtime: 2026-02-02T15:36:49Z ctime: 2026-02-02T15:36:49Z}

In version v0.0.0-20260119183325-601d6c2067cd, they aren't converted, but instead are shown in the go "%v" format. For example:

[name: "file1.txt" path: "/home/gtarcea/proj/Aging/cliuptest/file1.txt" type: "file" size: 37 mtime: 2026-02-02T15:36:37Z ctime: 2026-02-02T15:36:37Z name: "subdir" path: "/home/gtarcea/proj/Aging/cliuptest/subdir" type: "directory" size: 4096 mtime: 2026-02-02T15:36:49Z ctime: 2026-02-02T15:36:49Z]

Specifically I'm creating a list of strings like:

       var items []string
	for _, item := range files {
		i := item.(map[string]any)
		lsItem, err := decoder.DecodeMapStrict[lsResponse](i)
		if err != nil {
			return feather.Error(fmt.Errorf("failed to decode lsResponse: %v", err))
		}
		items = append(items, fmt.Sprintf("name: %q path: %q type: %q size: %d mtime: %s ctime: %s",
			lsItem.Name, lsItem.Path, lsItem.Type, lsItem.Size,
			lsItem.Mtime.Format(time.RFC3339), lsItem.Ctime.Format(time.RFC3339)))
	}

It looks like feather.OK() has changed. In the v0.0.0-20260119183325-601d6c2067cd version its:

func OK(v any) Result {
	if o, ok := v.(*Obj); ok {
		return Result{code: ResultOK, obj: o, hasObj: true}
	}
	// For simple types, don't quote - just convert to string
	switch val := v.(type) {
	case string:
		return Result{code: ResultOK, val: val}
	case int:
		return Result{code: ResultOK, val: fmt.Sprintf("%d", val)}
	case int64:
		return Result{code: ResultOK, val: fmt.Sprintf("%d", val)}
	case float64:
		return Result{code: ResultOK, val: fmt.Sprintf("%g", val)}
	case bool:
		if val {
			return Result{code: ResultOK, val: "1"}
		}
		return Result{code: ResultOK, val: "0"}
	default:
		return Result{code: ResultOK, val: fmt.Sprintf("%v", v)}
	}
}

The default case is the reason for the go representation of []string.

In the v0.0.0-20251227222940-8b153391b49e version feather.OK() is implemented as:

func OK(v any) Result {
	if o, ok := v.(*Obj); ok {
		return Result{code: ResultOK, obj: o, hasObj: true}
	}
	return Result{code: ResultOK, val: toTclString(v)}
}

The toTclString() is handling the formatting. Is this an intentional change? If so what should I use to convert my types to a TCL String without writing my own version of toTclString?

For now I've copied your toTclString into my project and I'm making use of it. I had originally reverted to the 2025 version, but I noticed there are API changes and I want to use the latest version.

Let me know if you'd like a pull request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions