Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add --tui Flag to Open TUI-mode on File Argument #548

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"strings"
"time"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/glamour"
Expand All @@ -31,6 +32,7 @@ var (
readmeNames = []string{"README.md", "README"}
configFile string
pager bool
tui bool
style string
width uint
showAllFiles bool
Expand Down Expand Up @@ -140,6 +142,7 @@ func validateOptions(cmd *cobra.Command) error {
localOnly = viper.GetBool("local")
mouse = viper.GetBool("mouse")
pager = viper.GetBool("pager")
tui = viper.GetBool("tui")

// validate the glamour style
style = viper.GetString("style")
Expand Down Expand Up @@ -219,6 +222,16 @@ func execute(cmd *cobra.Command, args []string) error {
return runTUI(p, false)
}
}

useTUI := tui || cmd.Flags().Changed("tui")
if err == nil && useTUI && !info.IsDir() {
// Is file; open in TUI-mode
p, err := filepath.Abs(args[0])
if err == nil {
return runTUI(p, false, true)
}
}

fallthrough

// CLI
Expand Down Expand Up @@ -313,7 +326,29 @@ func executeCLI(cmd *cobra.Command, src *source, w io.Writer) error {
return nil
}

func runTUI(workingDirectory string, stashedOnly bool) error {
func runTUI(path string, stashedOnly bool, withFile ...bool) error {
var (
workingDirectory string
filePath string
createdAt time.Time
)

if len(withFile) == 1 && withFile[0] == true {
// Open TUI-mode with file
workingDirectory = filepath.Dir(path)
filePath = path
fileInfo, err := os.Stat(filePath)
if err != nil {
createdAt = time.Now()
} else {
createdAt = fileInfo.ModTime()
}
} else {
workingDirectory = path
filePath = ""
createdAt = time.Now()
}

// Read environment to get debugging stuff
var cfg ui.Config
if err := babyenv.Parse(&cfg); err != nil {
Expand All @@ -330,6 +365,8 @@ func runTUI(workingDirectory string, stashedOnly bool) error {
}

cfg.WorkingDirectory = workingDirectory
cfg.FilePath = filePath
cfg.FileCreatedAt = createdAt
cfg.DocumentTypes = ui.NewDocTypeSet()
cfg.ShowAllFiles = showAllFiles
cfg.GlamourMaxWidth = width
Expand Down Expand Up @@ -372,6 +409,7 @@ func init() {
// "Glow Classic" cli arguments
rootCmd.PersistentFlags().StringVar(&configFile, "config", "", fmt.Sprintf("config file (default %s)", defaultConfigFile))
rootCmd.Flags().BoolVarP(&pager, "pager", "p", false, "display with pager")
rootCmd.Flags().BoolVarP(&tui, "tui", "t", false, "display with TUI-mode")
rootCmd.Flags().StringVarP(&style, "style", "s", "auto", "style name or JSON path")
rootCmd.Flags().UintVarP(&width, "width", "w", 0, "word-wrap at width")
rootCmd.Flags().BoolVarP(&showAllFiles, "all", "a", false, "show system files and directories (TUI-mode only)")
Expand Down
6 changes: 6 additions & 0 deletions ui/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ui

import "time"

// Config contains TUI-specific configuration.
type Config struct {
ShowAllFiles bool
Expand All @@ -12,6 +14,10 @@ type Config struct {
// Which directory should we start from?
WorkingDirectory string

// (Optional) If not "", open TUI-mode with this file open
FilePath string
FileCreatedAt time.Time

// Which document types shall we show?
DocumentTypes DocTypeSet

Expand Down
42 changes: 35 additions & 7 deletions ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ func NewProgram(cfg Config) *tea.Program {
log.Println("Bubble Tea now initializing...")
debug = true
}

config = cfg

opts := []tea.ProgramOption{tea.WithAltScreen()}
if cfg.EnableMouse {
opts = append(opts, tea.WithMouseCellMotion())
}
return tea.NewProgram(newModel(cfg), opts...)

m := newModel(cfg)

program := tea.NewProgram(m, opts...)

return program
}

type errMsg struct{ err error }
Expand Down Expand Up @@ -220,13 +227,22 @@ func newModel(cfg Config) tea.Model {
filesStashing: make(map[ksuid.KSUID]struct{}),
}

return model{
m := model{
common: &common,
state: stateShowStash,
keygenState: keygenUnstarted,
pager: newPagerModel(&common),
stash: newStashModel(&common),
}

if cfg.FilePath != "" {
// Open file passed in with TUI-mode flag
m.pager.currentDocument = *localFileToMarkdown(cfg.WorkingDirectory, cfg.FilePath, cfg.FileCreatedAt, true) // TODO: Fix time
m.state = stateShowDocument
m.pager.update(keyEnter)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hacky solution, but works.

}

return m
}

func (m model) Init() tea.Cmd {
Expand Down Expand Up @@ -359,6 +375,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {

case fetchedMarkdownMsg:
// We've loaded a markdown file's contents for rendering
println("Update markdown!")
m.pager.currentDocument = *msg
msg.Body = string(utils.RemoveFrontmatter([]byte(msg.Body)))
cmds = append(cmds, renderWithGlamour(m.pager, msg.Body))
Expand All @@ -383,7 +400,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, cmd

case foundLocalFileMsg:
newMd := localFileToMarkdown(m.common.cwd, gitcha.SearchResult(msg))
res := gitcha.SearchResult(msg)
newMd := localFileToMarkdown(m.common.cwd, res.Path, res.Info.ModTime())
m.stash.addMarkdowns(newMd)
if m.stash.filterApplied() {
newMd.buildFilterValue()
Expand Down Expand Up @@ -723,13 +741,23 @@ func waitForStatusMessageTimeout(appCtx applicationContext, t *time.Timer) tea.C
// Convert a Gitcha result to an internal representation of a markdown
// 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 {
func localFileToMarkdown(cwd string, path string, createdAt time.Time, loadBody ...bool) *markdown {
body := ""
if len(loadBody) == 1 && loadBody[0] {
content, err := os.ReadFile(path)
if err == nil {
// Convert the byte slice to a string
body = string(content)
}
}

md := &markdown{
docType: LocalDoc,
localPath: res.Path,
localPath: path,
Markdown: charm.Markdown{
Note: stripAbsolutePath(res.Path, cwd),
CreatedAt: res.Info.ModTime(),
Body: body,
Note: stripAbsolutePath(path, cwd),
CreatedAt: createdAt,
},
}

Expand Down