diff --git a/cli/mklink/facade/facade.go b/cli/mklink/facade/facade.go index 223d47a..51ef043 100644 --- a/cli/mklink/facade/facade.go +++ b/cli/mklink/facade/facade.go @@ -7,7 +7,6 @@ import ( "os" "runtime" - isatty "github.com/mattn/go-isatty" "github.com/spf13/cobra" "github.com/spiegel-im-spiegel/gocli" "github.com/spiegel-im-spiegel/mklink" @@ -65,8 +64,16 @@ var rootCmd = &cobra.Command{ defer file.Close() log = file } - lnk := makelink.New(style, cui.Writer(), log) + if interactiveFlag { + i, err := interactive.New(style, log) + if err != nil { + return err + } + return i.Run() + } + + lnk := makelink.New(style, cui.Writer(), log) if len(args) > 0 { for _, arg := range args { err := lnk.MakeLink(arg) @@ -74,11 +81,6 @@ var rootCmd = &cobra.Command{ return err } } - } else if isatty.IsTerminal(os.Stdin.Fd()) { - if interactiveFlag { - interactive.New(style, log).Run() - } - return nil } else { scanner := bufio.NewScanner(cui.Reader()) for scanner.Scan() { diff --git a/cli/mklink/interactive/interractive.go b/cli/mklink/interactive/interractive.go index 68498c1..52bbb77 100644 --- a/cli/mklink/interactive/interractive.go +++ b/cli/mklink/interactive/interractive.go @@ -5,43 +5,82 @@ import ( "fmt" "io" "os" + "strings" + isatty "github.com/mattn/go-isatty" + "github.com/pkg/errors" "github.com/spiegel-im-spiegel/mklink" "github.com/spiegel-im-spiegel/mklink/cli/mklink/makelink" ) const ( - header = "Press Ctrl+C to stop" - prompt = "mklink> " + headerStr = "Input 'q' or 'quit' to stop" + promptStr = "mklink> " ) //Context class is context for making link type Context struct { *makelink.Context + scanner *bufio.Scanner + writer io.Writer } //New returns new Context instance -func New(s mklink.Style, log io.Writer) *Context { - return &Context{makelink.New(s, os.Stdout, log)} +func New(s mklink.Style, log io.Writer) (*Context, error) { + if !isTerminal() { + return nil, errors.New("not terminal (or pipe?)") + } + cxt := &Context{Context: makelink.New(s, os.Stdout, log), scanner: bufio.NewScanner(os.Stdin), writer: os.Stdout} + cxt.EnableClipboard() + return cxt, nil +} + +func isTerminal() bool { + if !isatty.IsTerminal(os.Stdin.Fd()) && !isatty.IsCygwinTerminal(os.Stdin.Fd()) { + return false + } + if !isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()) { + return false + } + return true } //Run is running interactive mode -func (c *Context) Run() { - reader := os.Stdin - writer := os.Stdout - fmt.Fprintln(writer, header) - fmt.Fprint(writer, prompt) - - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - err := c.MakeLink(scanner.Text()) - if err != nil { - fmt.Fprintln(os.Stderr, err) +func (c *Context) Run() error { + if c == nil { + return errors.New("nil pointer in interactive.Context.Run() function") + } + + fmt.Fprintln(c.writer, headerStr) + for true { + res, ok := c.prompt() + if !ok { + break } - fmt.Fprint(writer, prompt) + if err := c.MakeLink(res); err != nil { + fmt.Fprintln(c.writer, err) + } + } + + if err := c.scanner.Err(); err != nil { + return err } - if err := scanner.Err(); err != nil { - fmt.Fprintln(os.Stderr, err) - return + return nil +} + +func (c *Context) prompt() (string, bool) { + if c == nil { + return "", false + } + fmt.Fprint(c.writer, promptStr) + if c.scanner.Scan() { + res := strings.Trim(c.scanner.Text(), "\t ") + switch res { + case "q", "quit": + return res, false + default: + return res, true + } } + return "", false } diff --git a/cli/mklink/makelink/makelink.go b/cli/mklink/makelink/makelink.go index 3a7dc9c..17f9083 100644 --- a/cli/mklink/makelink/makelink.go +++ b/cli/mklink/makelink/makelink.go @@ -6,23 +6,28 @@ import ( "io" "github.com/atotto/clipboard" + "github.com/pkg/errors" "github.com/spiegel-im-spiegel/mklink" ) //Context class is context for making link type Context struct { - linkStyle mklink.Style - writer io.Writer - log io.Writer + linkStyle mklink.Style + writer io.Writer + log io.Writer + clipbrdFlag bool } //New returns new Context instance func New(s mklink.Style, writer io.Writer, log io.Writer) *Context { - return &Context{linkStyle: s, writer: writer, log: log} + return &Context{linkStyle: s, writer: writer, log: log, clipbrdFlag: false} } //MakeLink is making link func (c *Context) MakeLink(url string) error { + if c == nil { + return errors.New("nil pointer in makelink.Context.MakeLink() function") + } lnk, err := mklink.New(url) if err != nil { return err @@ -32,9 +37,25 @@ func (c *Context) MakeLink(url string) error { buf := new(bytes.Buffer) io.Copy(c.writer, io.TeeReader(r, buf)) strLink := buf.String() - clipboard.WriteAll(strLink) + if c.clipbrdFlag { + clipboard.WriteAll(strLink) + } if c.log != nil { fmt.Fprint(c.log, strLink) } return nil } + +//EnableClipboard is enabling to clipboard +func (c *Context) EnableClipboard() { + if c != nil { + c.clipbrdFlag = true + } +} + +//DisableClipboard is disabling to clipboard +func (c *Context) DisableClipboard() { + if c != nil { + c.clipbrdFlag = false + } +} diff --git a/cli/mklink/makelink/makelink_test.go b/cli/mklink/makelink/makelink_test.go index b64d5c3..8aece02 100644 --- a/cli/mklink/makelink/makelink_test.go +++ b/cli/mklink/makelink/makelink_test.go @@ -11,6 +11,7 @@ func TestMakeLink(t *testing.T) { outBuf := new(bytes.Buffer) logBuf := new(bytes.Buffer) cxt := New(mklink.StyleMarkdown, outBuf, logBuf) + cxt.EnableClipboard() err := cxt.MakeLink("https://git.io/vFR5M") if err != nil { t.Errorf("MakeLink() = \"%v\", want nil error.", err) @@ -48,3 +49,18 @@ func TestMakeLinkErr(t *testing.T) { t.Error("MakeLink() = nil error, not want nil error.") } } + +func TestClipbrdflag(t *testing.T) { + cxt := New(mklink.StyleMarkdown, nil, nil) + if cxt.clipbrdFlag { + t.Errorf("clipbrdFlag = %v, want false.", cxt.clipbrdFlag) + } + cxt.EnableClipboard() + if !cxt.clipbrdFlag { + t.Errorf("clipbrdFlag = %v, want true.", cxt.clipbrdFlag) + } + cxt.DisableClipboard() + if cxt.clipbrdFlag { + t.Errorf("clipbrdFlag = %v, want false.", cxt.clipbrdFlag) + } +} diff --git a/mklink.go b/mklink.go index 41dc2df..47cebb1 100644 --- a/mklink.go +++ b/mklink.go @@ -22,8 +22,8 @@ type Link struct { //New returns new Link instance func New(url string) (*Link, error) { - link := &Link{URL: url} - doc, err := goquery.NewDocument(url) + link := &Link{URL: strings.Trim(url, "\t \n")} + doc, err := goquery.NewDocument(link.URL) if err != nil { return link, err } @@ -31,11 +31,11 @@ func New(url string) (*Link, error) { doc.Find("head").Each(func(_ int, s *goquery.Selection) { s.Find("title").Each(func(_ int, s *goquery.Selection) { - link.Title = s.Text() + link.Title = strings.Trim(s.Text(), "\t \n") }) s.Find("meta[name='description']").Each(func(_ int, s *goquery.Selection) { if v, ok := s.Attr("content"); ok { - link.Description = v + link.Description = strings.Trim(v, "\t \n") } }) }) @@ -59,6 +59,9 @@ func (lnk *Link) JSON() (io.Reader, error) { //TitleName returns string of title name func (lnk *Link) TitleName() string { + if lnk == nil { + return "" + } if len(lnk.Title) > 0 { return lnk.Title } @@ -67,6 +70,9 @@ func (lnk *Link) TitleName() string { //Encode returns string (io.Reader) with other style func (lnk *Link) Encode(t Style) io.Reader { + if lnk == nil { + return ioutil.NopCloser(bytes.NewReader(nil)) + } buf := new(bytes.Buffer) switch t { case StyleMarkdown: @@ -82,8 +88,9 @@ func (lnk *Link) Encode(t Style) io.Reader { } func (lnk *Link) String() string { + if lnk == nil { + return "" + } r, _ := lnk.JSON() - buf := new(bytes.Buffer) - io.Copy(buf, r) - return buf.String() + return fmt.Sprint(r) }