feat: add new --tui / -t flag (#679)

This commit is contained in:
Andrey Nering 2025-02-05 16:45:36 -03:00 committed by GitHub
commit e03817b2cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 59 additions and 15 deletions

24
main.go
View file

@ -33,6 +33,7 @@ var (
readmeNames = []string{"README.md", "README", "Readme.md", "Readme", "readme.md", "readme"}
configFile string
pager bool
tui bool
style string
width uint
showAllFiles bool
@ -159,9 +160,14 @@ func validateOptions(cmd *cobra.Command) error {
width = viper.GetUint("width")
mouse = viper.GetBool("mouse")
pager = viper.GetBool("pager")
tui = viper.GetBool("tui")
showAllFiles = viper.GetBool("all")
preserveNewLines = viper.GetBool("preserveNewLines")
if pager && tui {
return errors.New("glow: cannot use both pager and tui")
}
// validate the glamour style
style = viper.GetString("style")
if err := validateStyle(style); err != nil {
@ -298,7 +304,8 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
}
// display
if pager || cmd.Flags().Changed("pager") {
switch {
case pager || cmd.Flags().Changed("pager"):
pagerCmd := os.Getenv("PAGER")
if pagerCmd == "" {
pagerCmd = "less -r"
@ -309,13 +316,15 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
c.Stdin = strings.NewReader(out)
c.Stdout = os.Stdout
return c.Run()
case tui || cmd.Flags().Changed("tui"):
return runTUI(src.URL)
default:
_, err = fmt.Fprint(w, out)
return err
}
_, err = fmt.Fprint(w, out)
return err
}
func runTUI(workingDirectory string) error {
func runTUI(path string) error {
// Read environment to get debugging stuff
cfg, err := env.ParseAs[ui.Config]()
if err != nil {
@ -327,7 +336,7 @@ func runTUI(workingDirectory string) error {
cfg.GlamourStyle = style
}
cfg.WorkingDirectory = workingDirectory
cfg.Path = path
cfg.ShowAllFiles = showAllFiles
cfg.ShowLineNumbers = showLineNumbers
cfg.GlamourMaxWidth = width
@ -370,6 +379,7 @@ func init() {
// "Glow Classic" cli arguments
rootCmd.PersistentFlags().StringVar(&configFile, "config", "", fmt.Sprintf("config file (default %s)", viper.GetViper().ConfigFileUsed()))
rootCmd.Flags().BoolVarP(&pager, "pager", "p", false, "display with pager")
rootCmd.Flags().BoolVarP(&tui, "tui", "t", false, "display with tui")
rootCmd.Flags().StringVarP(&style, "style", "s", styles.AutoStyle, "style name or JSON path")
rootCmd.Flags().UintVarP(&width, "width", "w", 0, "word-wrap at width (set to 0 to disable)")
rootCmd.Flags().BoolVarP(&showAllFiles, "all", "a", false, "show system files and directories (TUI-mode only)")
@ -379,6 +389,8 @@ func init() {
_ = rootCmd.Flags().MarkHidden("mouse")
// Config bindings
_ = viper.BindPFlag("pager", rootCmd.Flags().Lookup("pager"))
_ = viper.BindPFlag("tui", rootCmd.Flags().Lookup("tui"))
_ = viper.BindPFlag("style", rootCmd.Flags().Lookup("style"))
_ = viper.BindPFlag("width", rootCmd.Flags().Lookup("width"))
_ = viper.BindPFlag("debug", rootCmd.Flags().Lookup("debug"))

View file

@ -11,8 +11,8 @@ type Config struct {
EnableMouse bool
PreserveNewLines bool
// Which directory should we start from?
WorkingDirectory string
// Working directory or file path
Path string
// For debugging the UI
HighPerformancePager bool `env:"GLOW_HIGH_PERFORMANCE_PAGER" envDefault:"true"`

View file

@ -144,17 +144,50 @@ func newModel(cfg Config) tea.Model {
cfg: cfg,
}
return model{
m := model{
common: &common,
state: stateShowStash,
pager: newPagerModel(&common),
stash: newStashModel(&common),
}
info, err := os.Stat(cfg.Path)
if err != nil {
log.Error("unable to stat file", "file", m.common.cfg.Path, "error", err)
m.fatalErr = err
return m
}
if info.IsDir() {
m.state = stateShowStash
} else {
cwd, _ := os.Getwd()
m.state = stateShowDocument
m.pager.currentDocument = markdown{
localPath: cfg.Path,
Note: stripAbsolutePath(cfg.Path, cwd),
Modtime: info.ModTime(),
}
}
return m
}
func (m model) Init() tea.Cmd {
cmds := []tea.Cmd{m.stash.spinner.Tick}
cmds = append(cmds, findLocalFiles(*m.common))
switch m.state {
case stateShowStash:
cmds = append(cmds, findLocalFiles(*m.common))
case stateShowDocument:
content, err := os.ReadFile(m.common.cfg.Path)
if err != nil {
log.Error("unable to read file", "file", m.common.cfg.Path, "error", err)
return func() tea.Msg { return errMsg{err} }
}
body := string(utils.RemoveFrontmatter(content))
cmds = append(cmds, renderWithGlamour(m.pager, body))
}
return tea.Batch(cmds...)
}
@ -314,7 +347,7 @@ func findLocalFiles(m commonModel) tea.Cmd {
return func() tea.Msg {
log.Info("findLocalFiles")
var (
cwd = m.cfg.WorkingDirectory
cwd = m.cfg.Path
err error
)
@ -380,17 +413,16 @@ func waitForStatusMessageTimeout(appCtx applicationContext, t *time.Timer) tea.C
// document. Note that we could be doing things like checking if the file is
// a directory, but we trust that gitcha has already done that.
func localFileToMarkdown(cwd string, res gitcha.SearchResult) *markdown {
md := &markdown{
return &markdown{
localPath: res.Path,
Note: stripAbsolutePath(res.Path, cwd),
Modtime: res.Info.ModTime(),
}
return md
}
func stripAbsolutePath(fullPath, cwd string) string {
return strings.ReplaceAll(fullPath, cwd+string(os.PathSeparator), "")
path, _ := filepath.Rel(cwd, fullPath)
return path
}
// Lightweight version of reflow's indent function.