diff --git a/cmd/block.go b/cmd/block.go deleted file mode 100644 index 98f3612..0000000 --- a/cmd/block.go +++ /dev/null @@ -1,29 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "os" - - "github.com/spf13/cobra" -) - -var blockOutput string - -var blockCmd = &cobra.Command{ - Use: "block", - Short: "Process a block", - Run: func(cmd *cobra.Command, args []string) { - data, err := io.ReadAll(os.Stdin) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - fmt.Print(string(data)) - }, -} - -func init() { - blockCmd.Flags().StringVarP(&blockOutput, "output", "o", "", "output format") - rootCmd.AddCommand(blockCmd) -} diff --git a/cmd/block_test.go b/cmd/block_test.go deleted file mode 100644 index 001509b..0000000 --- a/cmd/block_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package cmd_test - -import "testing" - -func TestBlockCommand(t *testing.T) { - runScript(t, "testdata/script/block.txtar") -} diff --git a/cmd/file.go b/cmd/file.go index d0c78d4..e146666 100644 --- a/cmd/file.go +++ b/cmd/file.go @@ -3,26 +3,62 @@ package cmd import ( "fmt" "os" + "path/filepath" "litdoc/internal" "github.com/spf13/cobra" ) +var fileWrite bool + var fileCmd = &cobra.Command{ Use: "file ", Short: "Process a file", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - data, err := internal.ProcessFile(args[0]) + path := args[0] + data, err := internal.ProcessFile(path) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } + if fileWrite { + if err := writeFileAtomic(path, data); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + return + } fmt.Print(data) }, } +func writeFileAtomic(path, data string) error { + info, err := os.Stat(path) + if err != nil { + return err + } + tmp, err := os.CreateTemp(filepath.Dir(path), ".litdoc-*") + if err != nil { + return err + } + tmpName := tmp.Name() + defer os.Remove(tmpName) + if _, err := tmp.WriteString(data); err != nil { + tmp.Close() + return err + } + if err := tmp.Close(); err != nil { + return err + } + if err := os.Chmod(tmpName, info.Mode().Perm()); err != nil { + return err + } + return os.Rename(tmpName, path) +} + func init() { + fileCmd.Flags().BoolVarP(&fileWrite, "write", "w", false, "rewrite the file in place") rootCmd.AddCommand(fileCmd) } diff --git a/cmd/file_test.go b/cmd/file_test.go index 62200d7..4f17d2d 100644 --- a/cmd/file_test.go +++ b/cmd/file_test.go @@ -1,34 +1,19 @@ package cmd_test -import ( - "fmt" - "os" - "testing" - - "litdoc/cmd" - - "github.com/rogpeppe/go-internal/testscript" -) - -func TestMain(m *testing.M) { - testscript.Main(m, map[string]func(){ - "litdoc": func() { - if err := cmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - }, - }) -} +import "testing" func TestFileCommand(t *testing.T) { runScript(t, "testdata/script/file.txtar") } -func runScript(t *testing.T, script string) { - t.Helper() +func TestFileWriteFlag(t *testing.T) { + runScript(t, "testdata/script/file_write.txtar") +} + +func TestFileCommandNoArgs(t *testing.T) { + runScript(t, "testdata/script/file_no_args.txtar") +} - testscript.Run(t, testscript.Params{ - Files: []string{script}, - }) +func TestFileCommandMissingPath(t *testing.T) { + runScript(t, "testdata/script/file_missing_path.txtar") } diff --git a/cmd/testdata/script/block.txtar b/cmd/testdata/script/block.txtar deleted file mode 100644 index 0e01080..0000000 --- a/cmd/testdata/script/block.txtar +++ /dev/null @@ -1,6 +0,0 @@ -stdin input.md -exec litdoc block -o text -stdout 'code' - --- input.md -- -code diff --git a/cmd/testdata/script/file_missing_path.txtar b/cmd/testdata/script/file_missing_path.txtar new file mode 100644 index 0000000..48fda56 --- /dev/null +++ b/cmd/testdata/script/file_missing_path.txtar @@ -0,0 +1,2 @@ +! exec litdoc file does_not_exist.md +stderr 'reading source file' \ No newline at end of file diff --git a/cmd/testdata/script/file_no_args.txtar b/cmd/testdata/script/file_no_args.txtar new file mode 100644 index 0000000..dbebcd8 --- /dev/null +++ b/cmd/testdata/script/file_no_args.txtar @@ -0,0 +1,2 @@ +! exec litdoc file +stderr 'accepts 1 arg' \ No newline at end of file diff --git a/cmd/testdata/script/file_write.txtar b/cmd/testdata/script/file_write.txtar new file mode 100644 index 0000000..615b956 --- /dev/null +++ b/cmd/testdata/script/file_write.txtar @@ -0,0 +1,6 @@ +exec litdoc file -w input.md +! stdout . +grep '# Hello' input.md + +-- input.md -- +# Hello diff --git a/cmd/testscript_test.go b/cmd/testscript_test.go new file mode 100644 index 0000000..32680b4 --- /dev/null +++ b/cmd/testscript_test.go @@ -0,0 +1,30 @@ +package cmd_test + +import ( + "fmt" + "os" + "testing" + + "litdoc/cmd" + + "github.com/rogpeppe/go-internal/testscript" +) + +func TestMain(m *testing.M) { + testscript.Main(m, map[string]func(){ + "litdoc": func() { + if err := cmd.Execute(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + }, + }) +} + +func runScript(t *testing.T, script string) { + t.Helper() + + testscript.Run(t, testscript.Params{ + Files: []string{script}, + }) +}