Skip to content

Commit

Permalink
feat(cli): add arg to specify the output file (#122)
Browse files Browse the repository at this point in the history
Fixes #119

Signed-off-by: Xavier Coulon <[email protected]>
  • Loading branch information
xcoulon authored Jun 1, 2018
1 parent efbdd39 commit d402c2d
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 30 deletions.
75 changes: 54 additions & 21 deletions cmd/libasciidoc/root_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"io"
"os"
"strings"

Expand All @@ -16,6 +17,7 @@ import (
// NewRootCmd returns the root command
func NewRootCmd() *cobra.Command {
var noHeaderFooter bool
var outputName string
var logLevel string
rootCmd := &cobra.Command{
Use: "libasciidoc FILE...",
Expand All @@ -29,30 +31,23 @@ If more than 1 file is specified, then output is written to ".html" file alongsi
RunE: func(cmd *cobra.Command, args []string) error {
var err error
if len(args) == 0 {
_, err = libasciidoc.ConvertToHTML(context.Background(), os.Stdin, cmd.OutOrStdout(), renderer.IncludeHeaderFooter(!noHeaderFooter))
} else if len(args) == 1 {
_, err = libasciidoc.ConvertFileToHTML(context.Background(), args[0], cmd.OutOrStdout(), renderer.IncludeHeaderFooter(!noHeaderFooter)) //renderer.IncludeHeaderFooter(true)
out, close := getOut(cmd, "", outputName)
if out != nil {
defer close()
_, err = libasciidoc.ConvertToHTML(context.Background(), os.Stdin, out, renderer.IncludeHeaderFooter(!noHeaderFooter))
}
} else {
for _, source := range args {
path, _ := filepath.Abs(source)
log.Debugf("Starting to process file %v", path)
outname := strings.TrimSuffix(path, filepath.Ext(path)) + ".html"
outfile, e := os.Create(outname)
if e != nil {
log.Warnf("Cannot create output file - %v, skipping", outname)
continue
}
defer func() {
e = outfile.Close()
out, close := getOut(cmd, source, outputName)
if out != nil {
defer close()
path, _ := filepath.Abs(source)
log.Debugf("Starting to process file %v", path)
_, e := libasciidoc.ConvertFileToHTML(context.Background(), source, out, renderer.IncludeHeaderFooter(!noHeaderFooter)) //renderer.IncludeHeaderFooter(true)
if e != nil {
log.Errorf("Cannot close output file: %v", outname)
log.Errorf("error while rendering file ", err)
err = e
}
}()
_, e = libasciidoc.ConvertFileToHTML(context.Background(), source, outfile, renderer.IncludeHeaderFooter(!noHeaderFooter)) //renderer.IncludeHeaderFooter(true)
if e == nil {
log.Infof("File %v created", outname)
} else {
err = e
}
}
}
Expand All @@ -70,7 +65,45 @@ If more than 1 file is specified, then output is written to ".html" file alongsi
},
}
flags := rootCmd.Flags()
flags.BoolVarP(&noHeaderFooter, "no-header-footer", "s", false, "Do not render header/footer (Default: false)")
flags.BoolVarP(&noHeaderFooter, "no-header-footer", "s", false, "Do not render header/footer (default: false)")
flags.StringVarP(&outputName, "out-file", "o", "", "output file (default: based on path of input file); use - to output to STDOUT")
rootCmd.PersistentFlags().StringVar(&logLevel, "log", "warning", "log level to set {debug, info, warning, error, fatal, panic}")
return rootCmd
}

type closeFunc func() error

func defaultCloseFunc() closeFunc {
return func() error { return nil }
}

func newCloseFileFunc(c io.Closer) closeFunc {
return func() error {
return c.Close()
}
}

func getOut(cmd *cobra.Command, source, outputName string) (io.Writer, closeFunc) {
if outputName == "-" {
// outfile is STDOUT
return cmd.OutOrStdout(), defaultCloseFunc()
} else if outputName != "" {
// outfile is specified in the command line
outfile, e := os.Create(outputName)
if e != nil {
log.Warnf("Cannot create output file - %v, skipping", outputName)
}
return outfile, newCloseFileFunc(outfile)
} else if source != "" {
// outfile is based on source
path, _ := filepath.Abs(source)
outname := strings.TrimSuffix(path, filepath.Ext(path)) + ".html"
outfile, err := os.Create(outname)
if err != nil {
log.Warnf("Cannot create output file - %v, skipping", outname)
return nil, nil
}
return outfile, newCloseFileFunc(outfile)
}
return cmd.OutOrStdout(), defaultCloseFunc()
}
31 changes: 22 additions & 9 deletions cmd/libasciidoc/root_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,35 @@ import (
var _ = Describe("root cmd", func() {
RegisterFailHandler(Fail)

It("ok", func() {
It("render with STDOUT output", func() {
// given
root := main.NewRootCmd()
buf := new(bytes.Buffer)
root.SetOutput(buf)
root.SetArgs([]string{"test/test.adoc"})
root.SetArgs([]string{"-o", "-", "test/test.adoc"})
// when
err := root.Execute()
// then
require.NoError(GinkgoT(), err)
require.NotEmpty(GinkgoT(), buf)
})

It("should fail to parse bad log level", func() {
It("render with file output", func() {
// given
root := main.NewRootCmd()
buf := new(bytes.Buffer)
root.SetOutput(buf)
root.SetArgs([]string{"test/test.adoc"})
// when
err := root.Execute()
// then
require.NoError(GinkgoT(), err)
content, err := ioutil.ReadFile("test/test.html")
require.NoError(GinkgoT(), err)
require.NotEmpty(GinkgoT(), content)
})

It("fail to parse bad log level", func() {
// given
root := main.NewRootCmd()
buf := new(bytes.Buffer)
Expand All @@ -43,12 +58,12 @@ var _ = Describe("root cmd", func() {
require.Error(GinkgoT(), err)
})

It("should render without header/footer", func() {
It("render without header/footer", func() {
// given
root := main.NewRootCmd()
buf := new(bytes.Buffer)
root.SetOutput(buf)
root.SetArgs([]string{"-s", "test/test.adoc"})
root.SetArgs([]string{"-s", "-o", "-", "test/test.adoc"})
// when
err := root.Execute()
// then
Expand All @@ -57,7 +72,7 @@ var _ = Describe("root cmd", func() {
Expect(buf.String()).ToNot(ContainSubstring(`<div id="footer">`))
})

It("should process stdin", func() {
It("process stdin", func() {
// given
root := main.NewRootCmd()
buf := new(bytes.Buffer)
Expand All @@ -77,19 +92,17 @@ var _ = Describe("root cmd", func() {
oldstdin := os.Stdin
os.Stdin = tmpfile
defer func() { os.Stdin = oldstdin }()

root.SetArgs([]string{})
// when
err = root.Execute()

//then
GinkgoT().Logf("command output: %v", buf.String())
Expect(buf.String()).To(ContainSubstring(content))
require.NoError(GinkgoT(), err)
require.NotEmpty(GinkgoT(), buf)
})

It("should render multiple files", func() {
It("render multiple files", func() {
// given
root := main.NewRootCmd()
root.SetArgs([]string{"-s", "test/admonition.adoc", "test/test.adoc"})
Expand Down

0 comments on commit d402c2d

Please sign in to comment.