Skip to content

Commit

Permalink
feat: Add -0 flag to ignored, managed, and unmanaged commands
Browse files Browse the repository at this point in the history
  • Loading branch information
twpayne committed Feb 20, 2025
1 parent 84c5790 commit 7df7c58
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 13 deletions.
4 changes: 4 additions & 0 deletions assets/chezmoi.io/docs/reference/commands/ignored.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Print the list of entries ignored by chezmoi.

## Common flags

### `-0`, `--nul-path-separator`

--8<-- "common-flags/nul-path-separator.md"

### `-t`, `--tree`

--8<-- "common-flags/tree.md"
Expand Down
4 changes: 4 additions & 0 deletions assets/chezmoi.io/docs/reference/commands/managed.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ the destination directory in alphabetical order.

--8<-- "common-flags/include.md"

### `-0`, `--nul-path-separator`

--8<-- "common-flags/nul-path-separator.md"

### `-p`, `--path-style` *style*

--8<-- "common-flags/path-style.md:all"
Expand Down
4 changes: 4 additions & 0 deletions assets/chezmoi.io/docs/reference/commands/unmanaged.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ It is an error to supply *path*s that are not found on the file system.

## Common flags

### `-0`, `--nul-path-separator`

--8<-- "common-flags/nul-path-separator.md"

### `-p`, `--path-style` *style*

--8<-- "common-flags/path-style.md:no-source-tree"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Separate paths with the NUL character instead of a newline.
2 changes: 1 addition & 1 deletion internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var (

deDuplicateErrorRx = regexp.MustCompile(`:\s+`)
trailingSpaceRx = regexp.MustCompile(` +\n`)
helpFlagsRx = regexp.MustCompile("^### (?:`-([a-zA-Z])`, )?`--([a-zA-Z-]+)`")
helpFlagsRx = regexp.MustCompile("^### (?:`-([0-9A-Za-z])`, )?`--([-0-9A-Za-z]+)`")

helps = make(map[string]*help)
)
Expand Down
10 changes: 8 additions & 2 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2848,17 +2848,23 @@ func (c *Config) writeOutput(data []byte) error {
}

type writePathsOptions struct {
tree bool
nulPathSeparator bool
tree bool
}

func (c *Config) writePaths(paths []string, options writePathsOptions) error {
pathSeparator := byte('\n')
if options.nulPathSeparator {
pathSeparator = '\x00'
}
builder := strings.Builder{}
if options.tree {
newPathListTreeFromPathsSlice(paths).writeChildren(&builder, "", " ")
} else {
slices.Sort(paths)
for _, path := range paths {
fmt.Fprintln(&builder, path)
builder.WriteString(path)
builder.WriteByte(pathSeparator)
}
}
return c.writeOutputString(builder.String())
Expand Down
8 changes: 6 additions & 2 deletions internal/cmd/ignoredcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

type ignoredCmdConfig struct {
tree bool
nulPathSeparator bool
tree bool
}

func (c *Config) newIgnoredCmd() *cobra.Command {
Expand All @@ -24,12 +25,15 @@ func (c *Config) newIgnoredCmd() *cobra.Command {
}

ignoredCmd.Flags().BoolVarP(&c.ignored.tree, "tree", "t", c.ignored.tree, "Print paths as a tree")
ignoredCmd.Flags().
BoolVarP(&c.ignored.nulPathSeparator, "nul-path-separator", "0", c.ignored.nulPathSeparator, "Use the NUL character as a path separator")

return ignoredCmd
}

func (c *Config) runIgnoredCmd(cmd *cobra.Command, args []string, sourceState *chezmoi.SourceState) error {
return c.writePaths(stringersToStrings(sourceState.Ignored()), writePathsOptions{
tree: c.ignored.tree,
nulPathSeparator: c.ignored.nulPathSeparator,
tree: c.ignored.tree,
})
}
14 changes: 9 additions & 5 deletions internal/cmd/managedcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
)

type managedCmdConfig struct {
filter *chezmoi.EntryTypeFilter
format *choiceFlag
pathStyle *choiceFlag
tree bool
filter *chezmoi.EntryTypeFilter
format *choiceFlag
nulPathSeparator bool
pathStyle *choiceFlag
tree bool
}

func (c *Config) newManagedCmd() *cobra.Command {
Expand All @@ -33,6 +34,8 @@ func (c *Config) newManagedCmd() *cobra.Command {
managedCmd.Flags().VarP(c.managed.filter.Exclude, "exclude", "x", "Exclude entry types")
managedCmd.Flags().VarP(c.managed.format, "format", "f", "Format")
managedCmd.Flags().VarP(c.managed.filter.Include, "include", "i", "Include entry types")
managedCmd.Flags().
BoolVarP(&c.managed.nulPathSeparator, "nul-path-separator", "0", c.managed.nulPathSeparator, "Use the NUL character as a path separator")
managedCmd.Flags().VarP(c.managed.pathStyle, "path-style", "p", "Path style")
must(managedCmd.RegisterFlagCompletionFunc("path-style", c.managed.pathStyle.FlagCompletionFunc()))
managedCmd.Flags().BoolVarP(&c.managed.tree, "tree", "t", c.managed.tree, "Print paths as a tree")
Expand Down Expand Up @@ -116,7 +119,8 @@ func (c *Config) runManagedCmd(cmd *cobra.Command, args []string, sourceState *c
}
}
return c.writePaths(paths, writePathsOptions{
tree: c.managed.tree,
nulPathSeparator: c.managed.nulPathSeparator,
tree: c.managed.tree,
})
case pathStyleAll:
allEntryPathsMap := make(map[string]*entryPaths, len(allEntryPaths))
Expand Down
13 changes: 13 additions & 0 deletions internal/cmd/managedcmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ func TestManagedCmd(t *testing.T) {
".file",
),
},
{
name: "nul_path_separator",
root: map[string]any{
"/home/user/.local/share/chezmoi": map[string]any{
"dot_file1": "# contents of .file1\n",
"dot_file2": "# contents of .file2\n",
},
},
args: []string{
"-0",
},
expectedOutput: ".file1\x00.file2\x00",
},
{
name: "template",
root: map[string]any{
Expand Down
10 changes: 7 additions & 3 deletions internal/cmd/unmanagedcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import (
)

type unmanagedCmdConfig struct {
pathStyle *choiceFlag
tree bool
nulPathSeparator bool
pathStyle *choiceFlag
tree bool
}

func (c *Config) newUnmanagedCmd() *cobra.Command {
Expand All @@ -29,6 +30,8 @@ func (c *Config) newUnmanagedCmd() *cobra.Command {
),
}

unmanagedCmd.Flags().
BoolVarP(&c.unmanaged.nulPathSeparator, "nul-path-separator", "0", c.unmanaged.nulPathSeparator, "Use the NUL character as a path separator")
unmanagedCmd.Flags().VarP(c.unmanaged.pathStyle, "path-style", "p", "Path style")
must(unmanagedCmd.RegisterFlagCompletionFunc("path-style", c.unmanaged.pathStyle.FlagCompletionFunc()))
unmanagedCmd.Flags().BoolVarP(&c.unmanaged.tree, "tree", "t", c.unmanaged.tree, "Print paths as a tree")
Expand Down Expand Up @@ -112,6 +115,7 @@ func (c *Config) runUnmanagedCmd(cmd *cobra.Command, args []string, sourceState
}

return c.writePaths(stringersToStrings(paths), writePathsOptions{
tree: c.unmanaged.tree,
nulPathSeparator: c.unmanaged.nulPathSeparator,
tree: c.unmanaged.tree,
})
}
14 changes: 14 additions & 0 deletions internal/cmd/unmanagedcmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ func TestUnmanagedCmd(t *testing.T) {
".unmanaged",
),
},
{
name: "nul_path_separator",
root: map[string]any{
"/home/user": map[string]any{
".file": "",
".local/share/chezmoi/dot_file": "# contents of .file\n",
".unmanaged": "",
},
},
args: []string{
"-0",
},
expectedOutput: ".local\x00.unmanaged\x00",
},
{
name: "private_subdir",
root: map[string]any{
Expand Down

0 comments on commit 7df7c58

Please # to comment.