func main() { var err error var st int defer func() { os.Exit(st) }() if envvar := os.Getenv("GOMAXPROCS"); envvar == "" { runtime.GOMAXPROCS(runtime.NumCPU()) } opts := &cmdOptions{} p := flags.NewParser(opts, flags.PrintErrors) args, err := p.Parse() if err != nil { showHelp() st = 1 return } if opts.OptLayout != "" { if !peco.IsValidLayoutType(opts.OptLayout) { fmt.Fprintf(os.Stderr, "Unknown layout: '%s'\n", opts.OptLayout) st = 1 return } } if opts.OptHelp { showHelp() return } if opts.OptVersion { fmt.Fprintf(os.Stderr, "peco: %s\n", version) return } var in *os.File // receive in from either a file or Stdin switch { case len(args) > 0: in, err = os.Open(args[0]) if err != nil { st = 1 fmt.Fprintln(os.Stderr, err) return } case !peco.IsTty(os.Stdin.Fd()): in = os.Stdin default: fmt.Fprintln(os.Stderr, "You must supply something to work with via filename or stdin") st = 1 return } ctx := peco.NewCtx(opts) defer func() { if err := recover(); err != nil { st = 1 fmt.Fprintf(os.Stderr, "Error:\n%s", err) } if result := ctx.Result(); result != nil { for _, match := range result { line := match.Output() if line[len(line)-1] != '\n' { line = line + "\n" } fmt.Fprint(os.Stdout, line) } } }() if opts.OptRcfile == "" { file, err := peco.LocateRcfile() if err == nil { opts.OptRcfile = file } } // Default matcher is IgnoreCase ctx.SetCurrentMatcher(peco.IgnoreCaseMatch) if opts.OptRcfile != "" { err = ctx.ReadConfig(opts.OptRcfile) if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } } // Deprecated. --no-ignore-case options will be removed in later. if opts.OptNoIgnoreCase { ctx.SetCurrentMatcher(peco.CaseSensitiveMatch) } if len(opts.OptInitialMatcher) > 0 { ctx.SetCurrentMatcher(opts.OptInitialMatcher) } // Try waiting for something available in the source stream // before doing any terminal initialization (also done by termbox) reader := ctx.NewBufferReader(in) ctx.AddWaitGroup(1) go reader.Loop() // This channel blocks until we receive something from `in` <-reader.InputReadyCh() err = peco.TtyReady() if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } defer peco.TtyTerm() err = termbox.Init() if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } defer termbox.Close() // Windows handle Esc/Alt self if runtime.GOOS == "windows" { termbox.SetInputMode(termbox.InputEsc | termbox.InputAlt) } view := ctx.NewView() filter := ctx.NewFilter() input := ctx.NewInput() sig := ctx.NewSignalHandler() loopers := []interface { Loop() }{ view, filter, input, sig, } for _, looper := range loopers { ctx.AddWaitGroup(1) go looper.Loop() } if len(opts.OptQuery) > 0 { ctx.SetQuery([]rune(opts.OptQuery)) ctx.ExecQuery() } else { view.Refresh() } if len(opts.OptPrompt) > 0 { ctx.SetPrompt([]rune(opts.OptPrompt)) } ctx.WaitDone() st = ctx.ExitStatus }
func main() { var err error var st int defer func() { os.Exit(st) }() if envvar := os.Getenv("GOMAXPROCS"); envvar == "" { runtime.GOMAXPROCS(runtime.NumCPU()) } opts := &cmdOptions{} p := flags.NewParser(opts, flags.PrintErrors) args, err := p.Parse() if err != nil { showHelp() st = 1 return } if opts.Help { showHelp() return } if opts.Version { fmt.Fprintf(os.Stderr, "peco: %s\n", version) return } var in *os.File // receive in from either a file or Stdin if len(args) > 0 { in, err = os.Open(args[0]) if err != nil { st = 1 return } } else if !peco.IsTty() { in = os.Stdin } ctx := peco.NewCtx(opts.ContextSep) defer func() { if err := recover(); err != nil { st = 1 fmt.Fprintf(os.Stderr, "Error:\n%s", err) } if result := ctx.Result(); result != nil { for _, match := range result { line := match.Output() if line[len(line)-1] != '\n' { line = line + "\n" } fmt.Fprint(os.Stdout, line) } } }() if opts.Rcfile == "" { file, err := peco.LocateRcfile() if err == nil { opts.Rcfile = file } } // Default matcher is IgnoreCase ctx.SetCurrentMatcher(peco.IgnoreCaseMatch) if opts.Rcfile != "" { err = ctx.ReadConfig(opts.Rcfile) if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } } if opts.NoIgnoreCase { ctx.SetCurrentMatcher(peco.CaseSensitiveMatch) } if err = ctx.ReadBuffer(in); err != nil { // Nothing to process, bail out fmt.Fprintln(os.Stderr, "You must supply something to work with via filename or stdin") st = 1 return } err = peco.TtyReady() if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } defer peco.TtyTerm() err = termbox.Init() if err != nil { fmt.Fprintln(os.Stderr, err) st = 1 return } defer termbox.Close() // Windows handle Esc/Alt self if runtime.GOOS == "windows" { termbox.SetInputMode(termbox.InputEsc | termbox.InputAlt) } view := ctx.NewView() filter := ctx.NewFilter() input := ctx.NewInput() // AddWaitGroup must be called in this main thread sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) ctx.AddWaitGroup(4) go view.Loop() go filter.Loop() go input.Loop() go ctx.SignalHandlerLoop(sigCh) if len(opts.Query) > 0 { ctx.SetQuery([]rune(opts.Query)) ctx.ExecQuery(opts.Query) } else { view.Refresh() } ctx.WaitDone() st = ctx.ExitStatus }