main.go (2970B)
1 package main 2 3 import ( 4 "encoding/json" 5 "errors" 6 // "fmt" 7 "log" 8 "os" 9 "os/exec" 10 "path" 11 "strconv" 12 "strings" 13 14 "github.com/gdamore/tcell/v2" 15 "github.com/rivo/tview" 16 ) 17 18 type Config struct { 19 NoteDirs []string `json:"noteDirs"` 20 TodoFiles []string `json:"todoFiles"` 21 } 22 23 func readConfig() Config { 24 25 configBase, err := os.UserConfigDir() 26 27 if err != nil { 28 log.Fatal(err) 29 } 30 31 appConfigDir := configBase + "/nt/" 32 33 // fmt.Println(configBase) 34 // fmt.Println(appConfigDir) 35 36 err = os.MkdirAll(appConfigDir, 0755) 37 38 if err != nil { 39 log.Fatal(err) 40 } 41 42 configFilePath := appConfigDir + "config.json" 43 44 configuration := &Config{ 45 NoteDirs: []string{"$HOME/.notes"}, 46 TodoFiles: []string{"$HOME/.todo/main.md"}, 47 } 48 49 if _, err := os.Stat(configFilePath); !errors.Is(err, os.ErrNotExist) { 50 configFileData, err := os.ReadFile(configFilePath) 51 52 if err != nil { 53 log.Fatal(err) 54 } 55 err = json.Unmarshal(configFileData, configuration) 56 if err != nil { 57 log.Fatal(err) 58 } 59 } else { 60 configBytes , err := json.MarshalIndent(configuration, "", " ") 61 if err != nil { 62 log.Fatal(err) 63 } 64 65 os.WriteFile(configFilePath, configBytes, 0644) 66 67 } 68 69 for idx, noteDir := range configuration.NoteDirs { 70 configuration.NoteDirs[idx] = os.ExpandEnv(noteDir) 71 os.MkdirAll(configuration.NoteDirs[idx], 0755) 72 } 73 74 for idx, noteDir := range configuration.TodoFiles { 75 configuration.TodoFiles[idx] = os.ExpandEnv(noteDir) 76 os.MkdirAll(path.Dir(configuration.TodoFiles[idx]), 0755) 77 } 78 79 return *configuration 80 } 81 82 var ( 83 app *tview.Application 84 mainArea *tview.Flex 85 selectionOptions []string 86 conf Config 87 ) 88 89 func repaint() { 90 91 mainArea = tview.NewFlex().SetDirection(tview.FlexRow) 92 mainArea.SetBorder(true) 93 94 selections := conf.TodoFiles 95 96 selectionOptions = []string{} 97 98 todoHeader := tview.NewTextView() 99 todoHeader.SetText("Todo:") 100 mainArea.AddItem(todoHeader, 1, 1, true) 101 102 for idx, selection := range selections { 103 sel := tview.NewTextView() 104 sel.SetText(strconv.Itoa(idx) + " " + selection) 105 mainArea.AddItem(sel, 1, 1, true) 106 selectionOptions = append(selectionOptions, selection) 107 } 108 109 } 110 111 func main() { 112 113 // TODO: Ensure all configuration fields are filled in, always in the config 114 115 conf = readConfig() 116 // fmt.Println(conf) 117 118 app = tview.NewApplication() 119 120 repaint() 121 122 mainArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { 123 r := event.Rune() 124 125 num, err := strconv.Atoi(string(r)) 126 127 if err == nil && num < len(selectionOptions){ 128 app.Suspend(func() { 129 130 editor := os.Getenv("EDITOR") 131 132 if strings.Compare(editor, "") == 0 { 133 editor = "vim" 134 } 135 136 cmd := exec.Command(editor, selectionOptions[num]) 137 cmd.Stdin = os.Stdin 138 cmd.Stdout = os.Stdout 139 cmd.Stderr = os.Stderr 140 if err := cmd.Run(); err != nil { 141 log.Printf("nvim error: %v", err) 142 } 143 cmd.Wait() 144 }) 145 } 146 147 148 repaint() 149 150 return event 151 }) 152 153 154 app.SetRoot(mainArea, true).SetFocus(mainArea) 155 156 err := app.Run() 157 158 if err != nil { 159 panic(err) 160 } 161 162 }