mirror of
https://github.com/RWejlgaard/org.git
synced 2026-05-06 04:34:45 +00:00
Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bc00d6891 | ||
|
|
fce607e29d | ||
| c858e70d07 |
6 changed files with 270 additions and 130 deletions
20
README.md
20
README.md
|
|
@ -23,6 +23,9 @@ org tasks.org # Open specific org file
|
|||
org /path/to/work.org # Open specific org file with path
|
||||
org -m # Multi-file: Load all .org files in current directory
|
||||
org -m /path/to/dir # Multi-file: Load all .org files in specified directory
|
||||
org -c # Quick capture mode
|
||||
org -c "Task description" # Quick capture with pre-filled text
|
||||
echo "Task" | org # Pipe text to capture
|
||||
```
|
||||
|
||||
### Single-File Mode (Default)
|
||||
|
|
@ -35,6 +38,20 @@ org tasks.org # Opens tasks.org
|
|||
org ~/work/project.org # Opens specific file
|
||||
```
|
||||
|
||||
### Quick Capture Mode
|
||||
|
||||
Use the `-c` or `--capture` flag to quickly add tasks without navigating through the UI:
|
||||
|
||||
```bash
|
||||
org -c # Open directly in capture mode
|
||||
org -c "Buy groceries" # Capture with pre-filled text
|
||||
org -c "Write report" tasks.org # Capture to specific file
|
||||
echo "Meeting notes" | org # Pipe text to capture
|
||||
echo "Task" | org ~/work.org # Pipe to specific file
|
||||
```
|
||||
|
||||
This is perfect for quickly capturing tasks from scripts, terminal workflows, or shell aliases. The capture mode skips the need to press 'c' once inside the application, making it faster to add quick TODO items.
|
||||
|
||||
### Multi-File Mode
|
||||
|
||||
Use the `-m` or `--multi` flag to load all `.org` files in a directory as top-level items. Each file appears as a top-level item in the interface, with its contents nested underneath. Changes made to items are automatically saved back to their respective files.
|
||||
|
|
@ -92,6 +109,7 @@ Feel free to fork and create a pull request if there's any features missing for
|
|||
- **Syntax Highlighting**: Code blocks are automatically highlighted (supports both ```lang and #+BEGIN_SRC formats)
|
||||
- **Markdown Support**: Use markdown-style code blocks in your notes
|
||||
- **Drawer Management**: LOGBOOK and PROPERTIES drawers are automatically filtered in list view
|
||||
- **Fold/Unfold All**: Fold/Unfold all items with shift+tab
|
||||
|
||||
### Keybindings
|
||||
|
||||
|
|
@ -101,6 +119,7 @@ Feel free to fork and create a pull request if there's any features missing for
|
|||
| `←/h`, `→/l` | Cycle state backward/forward |
|
||||
| `t` or `space` | Cycle TODO state |
|
||||
| `tab` | Fold/unfold item |
|
||||
| `shift+tab` | Fold/Unfold all items |
|
||||
| `enter` | Edit notes |
|
||||
| `c` | Capture new TODO |
|
||||
| `s` | Add sub-task |
|
||||
|
|
@ -111,6 +130,7 @@ Feel free to fork and create a pull request if there's any features missing for
|
|||
| `i` | Clock in |
|
||||
| `o` | Clock out |
|
||||
| `d` | Set deadline |
|
||||
| `S` | Set scheduled date |
|
||||
| `p` | Set priority |
|
||||
| `e` | Set effort |
|
||||
| `r` | Toggle reorder mode |
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ type KeybindingsConfig struct {
|
|||
Rename []string `toml:"rename"`
|
||||
CycleState []string `toml:"cycle_state"`
|
||||
ToggleFold []string `toml:"toggle_fold"`
|
||||
ToggleFoldAll []string `toml:"toggle_fold_all"`
|
||||
EditNotes []string `toml:"edit_notes"`
|
||||
ToggleView []string `toml:"toggle_view"`
|
||||
Capture []string `toml:"capture"`
|
||||
|
|
@ -41,6 +42,7 @@ type KeybindingsConfig struct {
|
|||
ClockIn []string `toml:"clock_in"`
|
||||
ClockOut []string `toml:"clock_out"`
|
||||
SetDeadline []string `toml:"set_deadline"`
|
||||
SetScheduled []string `toml:"set_scheduled"`
|
||||
SetPriority []string `toml:"set_priority"`
|
||||
SetEffort []string `toml:"set_effort"`
|
||||
Help []string `toml:"help"`
|
||||
|
|
@ -114,6 +116,7 @@ func DefaultConfig() *Config {
|
|||
Rename: []string{"R"},
|
||||
CycleState: []string{"t", " "},
|
||||
ToggleFold: []string{"tab"},
|
||||
ToggleFoldAll: []string{"shift+tab", "backtab"},
|
||||
EditNotes: []string{"enter"},
|
||||
ToggleView: []string{"a"},
|
||||
Capture: []string{"c"},
|
||||
|
|
@ -124,6 +127,7 @@ func DefaultConfig() *Config {
|
|||
ClockIn: []string{"i"},
|
||||
ClockOut: []string{"o"},
|
||||
SetDeadline: []string{"d"},
|
||||
SetScheduled: []string{"S"},
|
||||
SetPriority: []string{"p"},
|
||||
SetEffort: []string{"e"},
|
||||
Help: []string{"?"},
|
||||
|
|
@ -282,6 +286,9 @@ func (c *Config) fillDefaults() {
|
|||
if len(c.Keybindings.ToggleFold) == 0 {
|
||||
c.Keybindings.ToggleFold = defaults.Keybindings.ToggleFold
|
||||
}
|
||||
if len(c.Keybindings.ToggleFoldAll) == 0 {
|
||||
c.Keybindings.ToggleFoldAll = defaults.Keybindings.ToggleFoldAll
|
||||
}
|
||||
if len(c.Keybindings.EditNotes) == 0 {
|
||||
c.Keybindings.EditNotes = defaults.Keybindings.EditNotes
|
||||
}
|
||||
|
|
@ -312,6 +319,9 @@ func (c *Config) fillDefaults() {
|
|||
if len(c.Keybindings.SetDeadline) == 0 {
|
||||
c.Keybindings.SetDeadline = defaults.Keybindings.SetDeadline
|
||||
}
|
||||
if len(c.Keybindings.SetScheduled) == 0 {
|
||||
c.Keybindings.SetScheduled = defaults.Keybindings.SetScheduled
|
||||
}
|
||||
if len(c.Keybindings.SetPriority) == 0 {
|
||||
c.Keybindings.SetPriority = defaults.Keybindings.SetPriority
|
||||
}
|
||||
|
|
@ -517,6 +527,8 @@ func (c *Config) UpdateKeybinding(action string, keys []string) error {
|
|||
c.Keybindings.CycleState = keys
|
||||
case "toggle_fold":
|
||||
c.Keybindings.ToggleFold = keys
|
||||
case "toggle_fold_all":
|
||||
c.Keybindings.ToggleFoldAll = keys
|
||||
case "edit_notes":
|
||||
c.Keybindings.EditNotes = keys
|
||||
case "capture":
|
||||
|
|
@ -557,6 +569,7 @@ func (c *Config) GetAllKeybindings() map[string][]string {
|
|||
"rename": c.Keybindings.Rename,
|
||||
"cycle_state": c.Keybindings.CycleState,
|
||||
"toggle_fold": c.Keybindings.ToggleFold,
|
||||
"toggle_fold_all": c.Keybindings.ToggleFoldAll,
|
||||
"edit_notes": c.Keybindings.EditNotes,
|
||||
"toggle_view": c.Keybindings.ToggleView,
|
||||
"capture": c.Keybindings.Capture,
|
||||
|
|
@ -567,6 +580,7 @@ func (c *Config) GetAllKeybindings() map[string][]string {
|
|||
"clock_in": c.Keybindings.ClockIn,
|
||||
"clock_out": c.Keybindings.ClockOut,
|
||||
"set_deadline": c.Keybindings.SetDeadline,
|
||||
"set_scheduled": c.Keybindings.SetScheduled,
|
||||
"set_priority": c.Keybindings.SetPriority,
|
||||
"set_effort": c.Keybindings.SetEffort,
|
||||
"help": c.Keybindings.Help,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const (
|
|||
modeCapture
|
||||
modeAddSubTask
|
||||
modeSetDeadline
|
||||
modeSetScheduled
|
||||
modeSetPriority
|
||||
modeSetEffort
|
||||
modeHelp
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@ type keyMap struct {
|
|||
Delete key.Binding
|
||||
Save key.Binding
|
||||
ToggleFold key.Binding
|
||||
ToggleFoldAll key.Binding
|
||||
EditNotes key.Binding
|
||||
ToggleReorder key.Binding
|
||||
ClockIn key.Binding
|
||||
ClockOut key.Binding
|
||||
SetDeadline key.Binding
|
||||
SetScheduled key.Binding
|
||||
SetPriority key.Binding
|
||||
SetEffort key.Binding
|
||||
Settings key.Binding
|
||||
|
|
@ -86,6 +88,10 @@ func newKeyMapFromConfig(cfg *config.Config) keyMap {
|
|||
key.WithKeys(kb.ToggleFold...),
|
||||
key.WithHelp(formatKeyHelp(kb.ToggleFold), "fold/unfold"),
|
||||
),
|
||||
ToggleFoldAll: key.NewBinding(
|
||||
key.WithKeys(kb.ToggleFoldAll...),
|
||||
key.WithHelp(formatKeyHelp(kb.ToggleFoldAll), "fold/unfold all"),
|
||||
),
|
||||
EditNotes: key.NewBinding(
|
||||
key.WithKeys(kb.EditNotes...),
|
||||
key.WithHelp(formatKeyHelp(kb.EditNotes), "edit notes"),
|
||||
|
|
@ -126,6 +132,10 @@ func newKeyMapFromConfig(cfg *config.Config) keyMap {
|
|||
key.WithKeys(kb.SetDeadline...),
|
||||
key.WithHelp(formatKeyHelp(kb.SetDeadline), "set deadline"),
|
||||
),
|
||||
SetScheduled: key.NewBinding(
|
||||
key.WithKeys(kb.SetScheduled...),
|
||||
key.WithHelp(formatKeyHelp(kb.SetScheduled), "set scheduled"),
|
||||
),
|
||||
SetPriority: key.NewBinding(
|
||||
key.WithKeys(kb.SetPriority...),
|
||||
key.WithHelp(formatKeyHelp(kb.SetPriority), "set priority"),
|
||||
|
|
@ -183,7 +193,7 @@ func (k keyMap) FullHelp() [][]key.Binding {
|
|||
// This will be overridden by custom rendering in viewFullHelp
|
||||
return [][]key.Binding{
|
||||
{k.Up, k.Down, k.Left, k.Right},
|
||||
{k.ToggleFold, k.EditNotes, k.ToggleReorder},
|
||||
{k.ToggleFold, k.ToggleFoldAll, k.EditNotes, k.ToggleReorder},
|
||||
{k.Capture, k.AddSubTask, k.Delete, k.Save},
|
||||
{k.ToggleView, k.Help, k.Quit},
|
||||
}
|
||||
|
|
@ -193,9 +203,9 @@ func (k keyMap) FullHelp() [][]key.Binding {
|
|||
func (k keyMap) getAllBindings() []key.Binding {
|
||||
return []key.Binding{
|
||||
k.Up, k.Down, k.Left, k.Right,
|
||||
k.ToggleFold, k.EditNotes, k.ToggleReorder,
|
||||
k.ToggleFold, k.ToggleFoldAll, k.EditNotes, k.ToggleReorder,
|
||||
k.Capture, k.AddSubTask, k.Delete, k.Save,
|
||||
k.ClockIn, k.ClockOut, k.SetDeadline, k.SetPriority, k.SetEffort,
|
||||
k.ClockIn, k.ClockOut, k.SetDeadline, k.SetScheduled, k.SetPriority, k.SetEffort,
|
||||
k.TagItem, k.Settings, k.ToggleView, k.Help, k.Quit,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m.updateAddSubTask(msg)
|
||||
case modeSetDeadline:
|
||||
return m.updateSetDeadline(msg)
|
||||
case modeSetScheduled:
|
||||
return m.updateSetScheduled(msg)
|
||||
case modeSetPriority:
|
||||
return m.updateSetPriority(msg)
|
||||
case modeSetEffort:
|
||||
|
|
@ -153,6 +155,46 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
case key.Matches(msg, m.keys.ToggleFoldAll):
|
||||
if len(m.orgFile.Items) > 0 {
|
||||
// Check if any top-level item is not folded
|
||||
anyUnfolded := false
|
||||
for _, item := range m.orgFile.Items {
|
||||
if !item.Folded {
|
||||
anyUnfolded = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if anyUnfolded {
|
||||
// Fold all items recursively (collapse all)
|
||||
var foldAll func([]*model.Item)
|
||||
foldAll = func(items []*model.Item) {
|
||||
for _, item := range items {
|
||||
item.Folded = true
|
||||
if len(item.Children) > 0 {
|
||||
foldAll(item.Children)
|
||||
}
|
||||
}
|
||||
}
|
||||
foldAll(m.orgFile.Items)
|
||||
m.setStatus("All items folded")
|
||||
} else {
|
||||
// Unfold everything recursively
|
||||
var unfoldAll func([]*model.Item)
|
||||
unfoldAll = func(items []*model.Item) {
|
||||
for _, item := range items {
|
||||
item.Folded = false
|
||||
if len(item.Children) > 0 {
|
||||
unfoldAll(item.Children)
|
||||
}
|
||||
}
|
||||
}
|
||||
unfoldAll(m.orgFile.Items)
|
||||
m.setStatus("All items unfolded")
|
||||
}
|
||||
}
|
||||
|
||||
case key.Matches(msg, m.keys.EditNotes):
|
||||
items := m.getVisibleItems()
|
||||
if len(items) > 0 && m.cursor < len(items) {
|
||||
|
|
@ -281,6 +323,17 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m, textinput.Blink
|
||||
}
|
||||
|
||||
case key.Matches(msg, m.keys.SetScheduled):
|
||||
items := m.getVisibleItems()
|
||||
if len(items) > 0 && m.cursor < len(items) {
|
||||
m.editingItem = items[m.cursor]
|
||||
m.mode = modeSetScheduled
|
||||
m.textinput.SetValue("")
|
||||
m.textinput.Placeholder = "YYYY-MM-DD or +N (days from today)"
|
||||
m.textinput.Focus()
|
||||
return m, textinput.Blink
|
||||
}
|
||||
|
||||
case key.Matches(msg, m.keys.SetPriority):
|
||||
items := m.getVisibleItems()
|
||||
if len(items) > 0 && m.cursor < len(items) {
|
||||
|
|
@ -521,83 +574,11 @@ func (m uiModel) updateAddSubTask(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
}
|
||||
|
||||
func (m uiModel) updateSetDeadline(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
m.textinput.Width = 50
|
||||
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyEnter:
|
||||
input := strings.TrimSpace(m.textinput.Value())
|
||||
if m.editingItem != nil {
|
||||
if input == "" {
|
||||
// Empty input clears the deadline
|
||||
m.editingItem.Deadline = nil
|
||||
// Remove DEADLINE line from notes (only lines starting with DEADLINE:)
|
||||
var filteredNotes []string
|
||||
for _, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if !strings.HasPrefix(trimmedNote, "DEADLINE:") {
|
||||
filteredNotes = append(filteredNotes, note)
|
||||
}
|
||||
}
|
||||
m.editingItem.Notes = filteredNotes
|
||||
m.setStatus("Deadline cleared!")
|
||||
} else {
|
||||
deadline, err := parseDeadlineInput(input)
|
||||
if err != nil {
|
||||
m.setStatus(fmt.Sprintf("Invalid date: %v", err))
|
||||
} else {
|
||||
m.editingItem.Deadline = &deadline
|
||||
// Also update or add DEADLINE line in notes
|
||||
updatedNotes := false
|
||||
for i, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if strings.HasPrefix(trimmedNote, "DEADLINE:") {
|
||||
m.editingItem.Notes[i] = fmt.Sprintf("DEADLINE: <%s>", parser.FormatOrgDate(deadline))
|
||||
updatedNotes = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// If DEADLINE wasn't in notes, it will be added by writeItem
|
||||
if !updatedNotes {
|
||||
// Remove old deadline lines just to be safe
|
||||
var filteredNotes []string
|
||||
for _, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if !strings.HasPrefix(trimmedNote, "DEADLINE:") {
|
||||
filteredNotes = append(filteredNotes, note)
|
||||
}
|
||||
}
|
||||
m.editingItem.Notes = filteredNotes
|
||||
}
|
||||
m.setStatus("Deadline set!")
|
||||
}
|
||||
}
|
||||
}
|
||||
m.mode = modeList
|
||||
m.textinput.Blur()
|
||||
m.editingItem = nil
|
||||
return m, nil
|
||||
case tea.KeyEsc:
|
||||
m.mode = modeList
|
||||
m.textinput.Blur()
|
||||
m.editingItem = nil
|
||||
m.setStatus("Cancelled")
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
m.textinput, cmd = m.textinput.Update(msg)
|
||||
return m, cmd
|
||||
return m.updateSetDate(msg, "DEADLINE")
|
||||
}
|
||||
|
||||
// parseDeadlineInput parses deadline input like "2024-01-15" or "+3" (3 days from now)
|
||||
func parseDeadlineInput(input string) (time.Time, error) {
|
||||
// parseDateInput parses date input like "2024-01-15" or "+3" (3 days from now)
|
||||
func parseDateInput(input string) (time.Time, error) {
|
||||
// Check if it's a relative date (+N days)
|
||||
if strings.HasPrefix(input, "+") {
|
||||
daysStr := strings.TrimPrefix(input, "+")
|
||||
|
|
@ -625,6 +606,110 @@ func parseDeadlineInput(input string) (time.Time, error) {
|
|||
return time.Time{}, fmt.Errorf("unable to parse date: %s (use YYYY-MM-DD or +N)", input)
|
||||
}
|
||||
|
||||
func (m uiModel) updateSetScheduled(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m.updateSetDate(msg, "SCHEDULED")
|
||||
}
|
||||
|
||||
func (m uiModel) updateSetDate(msg tea.Msg, dateType string) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = msg.Width
|
||||
m.height = msg.Height
|
||||
m.textinput.Width = 50
|
||||
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyEnter:
|
||||
input := strings.TrimSpace(m.textinput.Value())
|
||||
if m.editingItem != nil {
|
||||
var prefixDate string
|
||||
var clearedDateMsg string
|
||||
var setDateMsg string
|
||||
|
||||
if dateType == "DEADLINE" {
|
||||
prefixDate = "DEADLINE:"
|
||||
clearedDateMsg = "Deadline cleared!"
|
||||
setDateMsg = "Deadline set!"
|
||||
} else {
|
||||
prefixDate = "SCHEDULED:"
|
||||
clearedDateMsg = "Scheduled date cleared!"
|
||||
setDateMsg = "Scheduled date set!"
|
||||
}
|
||||
|
||||
if input == "" {
|
||||
// Empty input clears the date
|
||||
if dateType == "DEADLINE" {
|
||||
m.editingItem.Deadline = nil
|
||||
} else {
|
||||
m.editingItem.Scheduled = nil
|
||||
}
|
||||
|
||||
// Remove property line from notes
|
||||
var filteredNotes []string
|
||||
for _, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if !strings.HasPrefix(trimmedNote, prefixDate) {
|
||||
filteredNotes = append(filteredNotes, note)
|
||||
}
|
||||
}
|
||||
m.editingItem.Notes = filteredNotes
|
||||
m.setStatus(clearedDateMsg)
|
||||
} else {
|
||||
dateVal, err := parseDateInput(input)
|
||||
if err != nil {
|
||||
m.setStatus(fmt.Sprintf("Invalid date: %v", err))
|
||||
} else {
|
||||
if dateType == "DEADLINE" {
|
||||
m.editingItem.Deadline = &dateVal
|
||||
} else {
|
||||
m.editingItem.Scheduled = &dateVal
|
||||
}
|
||||
|
||||
// Also update or add property line in notes
|
||||
updatedNotes := false
|
||||
for i, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if strings.HasPrefix(trimmedNote, prefixDate) {
|
||||
m.editingItem.Notes[i] = fmt.Sprintf("%s <%s>", prefixDate, parser.FormatOrgDate(dateVal))
|
||||
updatedNotes = true
|
||||
break
|
||||
}
|
||||
}
|
||||
// If property wasn't in notes, it will be added by writeItem
|
||||
if !updatedNotes {
|
||||
// Remove old property lines just to be safe
|
||||
var filteredNotes []string
|
||||
for _, note := range m.editingItem.Notes {
|
||||
trimmedNote := strings.TrimSpace(note)
|
||||
if !strings.HasPrefix(trimmedNote, prefixDate) {
|
||||
filteredNotes = append(filteredNotes, note)
|
||||
}
|
||||
}
|
||||
m.editingItem.Notes = filteredNotes
|
||||
}
|
||||
m.setStatus(setDateMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
m.mode = modeList
|
||||
m.textinput.Blur()
|
||||
m.editingItem = nil
|
||||
return m, nil
|
||||
case tea.KeyEsc:
|
||||
m.mode = modeList
|
||||
m.textinput.Blur()
|
||||
m.editingItem = nil
|
||||
m.setStatus("Cancelled")
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
m.textinput, cmd = m.textinput.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m uiModel) updateSetPriority(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ func (m uiModel) View() string {
|
|||
return m.viewAddSubTask()
|
||||
case modeSetDeadline:
|
||||
return m.viewSetDeadline()
|
||||
case modeSetScheduled:
|
||||
return m.viewSetScheduled()
|
||||
case modeSetPriority:
|
||||
return m.viewSetPriority()
|
||||
case modeSetEffort:
|
||||
|
|
@ -379,6 +381,14 @@ func (m uiModel) viewAddSubTask() string {
|
|||
}
|
||||
|
||||
func (m uiModel) viewSetDeadline() string {
|
||||
return m.viewSetDate("Set Deadline", "Leave empty to clear deadline")
|
||||
}
|
||||
|
||||
func (m uiModel) viewSetScheduled() string {
|
||||
return m.viewSetDate("Set Scheduled Date", "Leave empty to clear scheduled date")
|
||||
}
|
||||
|
||||
func (m uiModel) viewSetDate(title, helpMsg string) string {
|
||||
dialogStyle := lipgloss.NewStyle().
|
||||
Border(lipgloss.RoundedBorder()).
|
||||
BorderForeground(lipgloss.Color("141")).
|
||||
|
|
@ -386,7 +396,7 @@ func (m uiModel) viewSetDeadline() string {
|
|||
Width(60)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString(m.styles.titleStyle.Render("Set Deadline"))
|
||||
content.WriteString(m.styles.titleStyle.Render(title))
|
||||
content.WriteString("\n")
|
||||
if m.editingItem != nil {
|
||||
content.WriteString(m.styles.statusStyle.Render(fmt.Sprintf("For: %s", m.editingItem.Title)))
|
||||
|
|
@ -396,7 +406,7 @@ func (m uiModel) viewSetDeadline() string {
|
|||
content.WriteString("\n\n")
|
||||
content.WriteString(m.styles.statusStyle.Render("Examples: 2025-12-31, +7 (7 days from now)"))
|
||||
content.WriteString("\n")
|
||||
content.WriteString(m.styles.statusStyle.Render("Leave empty to clear deadline"))
|
||||
content.WriteString(m.styles.statusStyle.Render(helpMsg))
|
||||
content.WriteString("\n")
|
||||
content.WriteString(m.styles.statusStyle.Render("Press Enter to save • ESC to cancel"))
|
||||
|
||||
|
|
@ -488,7 +498,7 @@ func (m uiModel) viewHelp() string {
|
|||
navigationBindings := []key.Binding{m.keys.Up, m.keys.Down, m.keys.Left, m.keys.Right}
|
||||
itemBindings := []key.Binding{m.keys.ToggleFold, m.keys.EditNotes, m.keys.CycleState}
|
||||
taskBindings := []key.Binding{m.keys.Capture, m.keys.AddSubTask, m.keys.Delete}
|
||||
timeBindings := []key.Binding{m.keys.ClockIn, m.keys.ClockOut, m.keys.SetDeadline, m.keys.SetEffort}
|
||||
timeBindings := []key.Binding{m.keys.ClockIn, m.keys.ClockOut, m.keys.SetDeadline, m.keys.SetScheduled, m.keys.SetEffort}
|
||||
organizationBindings := []key.Binding{m.keys.SetPriority, m.keys.TagItem, m.keys.ShiftUp, m.keys.ShiftDown, m.keys.ToggleReorder}
|
||||
viewBindings := []key.Binding{m.keys.ToggleView, m.keys.Settings, m.keys.Save, m.keys.Help, m.keys.Quit}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue