mirror of
https://github.com/RWejlgaard/org.git
synced 2026-05-06 04:34:45 +00:00
readme and keybindings improvements
This commit is contained in:
parent
097703beda
commit
8f6ec4a79f
5 changed files with 180 additions and 17 deletions
BIN
.imgs/priority_prompt.png
Normal file
BIN
.imgs/priority_prompt.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -70,7 +70,7 @@ org # Opens ./todo.org by default
|
||||||
| `p` | Set priority |
|
| `p` | Set priority |
|
||||||
| `e` | Set effort |
|
| `e` | Set effort |
|
||||||
| `r` | Toggle reorder mode |
|
| `r` | Toggle reorder mode |
|
||||||
| `shift+↑/↓` | Move item up/down (in reorder mode) |
|
| `shift+↑/↓` | Move item up/down |
|
||||||
| `ctrl+s` | Save |
|
| `ctrl+s` | Save |
|
||||||
| `?` | Toggle help |
|
| `?` | Toggle help |
|
||||||
| `q` or `ctrl+c` | Quit |
|
| `q` or `ctrl+c` | Quit |
|
||||||
|
|
@ -89,6 +89,7 @@ Changes are automatically saved when you quit the application.
|
||||||
### Prompts
|
### Prompts
|
||||||

|

|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
## File Format
|
## File Format
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,24 +22,26 @@ const (
|
||||||
modeSetDeadline
|
modeSetDeadline
|
||||||
modeSetPriority
|
modeSetPriority
|
||||||
modeSetEffort
|
modeSetEffort
|
||||||
|
modeHelp
|
||||||
)
|
)
|
||||||
|
|
||||||
type uiModel struct {
|
type uiModel struct {
|
||||||
orgFile *model.OrgFile
|
orgFile *model.OrgFile
|
||||||
cursor int
|
cursor int
|
||||||
scrollOffset int // Track the scroll position
|
scrollOffset int // Track the scroll position
|
||||||
mode viewMode
|
helpScroll int // Track scroll position in help mode
|
||||||
help help.Model
|
mode viewMode
|
||||||
keys keyMap
|
help help.Model
|
||||||
width int
|
keys keyMap
|
||||||
height int
|
width int
|
||||||
statusMsg string
|
height int
|
||||||
statusExpiry time.Time
|
statusMsg string
|
||||||
editingItem *model.Item
|
statusExpiry time.Time
|
||||||
textarea textarea.Model
|
editingItem *model.Item
|
||||||
textinput textinput.Model
|
textarea textarea.Model
|
||||||
itemToDelete *model.Item
|
textinput textinput.Model
|
||||||
reorderMode bool
|
itemToDelete *model.Item
|
||||||
|
reorderMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialModel(orgFile *model.OrgFile) uiModel {
|
func initialModel(orgFile *model.OrgFile) uiModel {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m.updateSetPriority(msg)
|
return m.updateSetPriority(msg)
|
||||||
case modeSetEffort:
|
case modeSetEffort:
|
||||||
return m.updateSetEffort(msg)
|
return m.updateSetEffort(msg)
|
||||||
|
case modeHelp:
|
||||||
|
return m.updateHelp(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
|
|
@ -48,7 +50,8 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
|
|
||||||
case key.Matches(msg, m.keys.Help):
|
case key.Matches(msg, m.keys.Help):
|
||||||
m.help.ShowAll = !m.help.ShowAll
|
m.mode = modeHelp
|
||||||
|
m.helpScroll = 0 // Reset scroll when entering help
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case key.Matches(msg, m.keys.Up):
|
case key.Matches(msg, m.keys.Up):
|
||||||
|
|
@ -733,3 +736,41 @@ func (m *uiModel) swapItems(item1, item2 *model.Item) {
|
||||||
}
|
}
|
||||||
swapInList(m.orgFile.Items)
|
swapInList(m.orgFile.Items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m uiModel) updateHelp(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m.width = msg.Width
|
||||||
|
m.height = msg.Height
|
||||||
|
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "?", "esc", "q":
|
||||||
|
m.mode = modeList
|
||||||
|
m.helpScroll = 0 // Reset scroll when exiting
|
||||||
|
return m, nil
|
||||||
|
case "up", "k":
|
||||||
|
if m.helpScroll > 0 {
|
||||||
|
m.helpScroll--
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
case "down", "j":
|
||||||
|
m.helpScroll++
|
||||||
|
// The view will handle clamping to max scroll
|
||||||
|
return m, nil
|
||||||
|
case "pageup":
|
||||||
|
m.helpScroll -= 10
|
||||||
|
if m.helpScroll < 0 {
|
||||||
|
m.helpScroll = 0
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
case "pagedown":
|
||||||
|
m.helpScroll += 10
|
||||||
|
return m, nil
|
||||||
|
case "home", "g":
|
||||||
|
m.helpScroll = 0
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,8 @@ func (m uiModel) View() string {
|
||||||
return m.viewSetPriority()
|
return m.viewSetPriority()
|
||||||
case modeSetEffort:
|
case modeSetEffort:
|
||||||
return m.viewSetEffort()
|
return m.viewSetEffort()
|
||||||
|
case modeHelp:
|
||||||
|
return m.viewHelp()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build footer (status + help)
|
// Build footer (status + help)
|
||||||
|
|
@ -421,6 +423,123 @@ func (m uiModel) viewSetEffort() string {
|
||||||
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, dialog)
|
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, dialog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m uiModel) viewHelp() string {
|
||||||
|
// Build the full help content first
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
// Title
|
||||||
|
lines = append(lines, titleStyle.Render("Keybindings Help"))
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
// Group bindings by category
|
||||||
|
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}
|
||||||
|
organizationBindings := []key.Binding{m.keys.SetPriority, m.keys.ShiftUp, m.keys.ShiftDown, m.keys.ToggleReorder}
|
||||||
|
viewBindings := []key.Binding{m.keys.ToggleView, m.keys.Save, m.keys.Help, m.keys.Quit}
|
||||||
|
|
||||||
|
// Helper function to render a binding
|
||||||
|
renderBinding := func(b key.Binding) string {
|
||||||
|
keyStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("99")).Bold(true)
|
||||||
|
descStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("245"))
|
||||||
|
help := b.Help()
|
||||||
|
return fmt.Sprintf(" %s %s", keyStyle.Render(help.Key), descStyle.Render(help.Desc))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render categories
|
||||||
|
categoryStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("214")).Bold(true)
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("Navigation"))
|
||||||
|
for _, binding := range navigationBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("Item Actions"))
|
||||||
|
for _, binding := range itemBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("Task Management"))
|
||||||
|
for _, binding := range taskBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("Time Tracking"))
|
||||||
|
for _, binding := range timeBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("Organization"))
|
||||||
|
for _, binding := range organizationBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
lines = append(lines, categoryStyle.Render("View & System"))
|
||||||
|
for _, binding := range viewBindings {
|
||||||
|
lines = append(lines, renderBinding(binding))
|
||||||
|
}
|
||||||
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
// Calculate visible area
|
||||||
|
footerLines := 2 // Footer text
|
||||||
|
availableHeight := m.height - footerLines
|
||||||
|
if availableHeight < 5 {
|
||||||
|
availableHeight = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
totalLines := len(lines)
|
||||||
|
|
||||||
|
// Determine which lines to show based on scroll offset
|
||||||
|
startLine := m.helpScroll
|
||||||
|
endLine := startLine + availableHeight
|
||||||
|
if endLine > totalLines {
|
||||||
|
endLine = totalLines
|
||||||
|
}
|
||||||
|
if startLine >= totalLines {
|
||||||
|
startLine = totalLines - 1
|
||||||
|
if startLine < 0 {
|
||||||
|
startLine = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build visible content
|
||||||
|
var content strings.Builder
|
||||||
|
for i := startLine; i < endLine && i < len(lines); i++ {
|
||||||
|
content.WriteString(lines[i])
|
||||||
|
content.WriteString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add scroll indicators and footer
|
||||||
|
var footer strings.Builder
|
||||||
|
if startLine > 0 || endLine < totalLines {
|
||||||
|
scrollInfo := fmt.Sprintf("(Scroll: %d-%d of %d lines)", startLine+1, endLine, totalLines)
|
||||||
|
footer.WriteString(statusStyle.Render(scrollInfo))
|
||||||
|
footer.WriteString(" ")
|
||||||
|
}
|
||||||
|
footer.WriteString(statusStyle.Render("↑/↓ scroll • ? or ESC to close"))
|
||||||
|
|
||||||
|
// Combine content and footer
|
||||||
|
var result strings.Builder
|
||||||
|
result.WriteString(content.String())
|
||||||
|
|
||||||
|
// Add padding if needed
|
||||||
|
currentHeight := lipgloss.Height(content.String())
|
||||||
|
paddingNeeded := availableHeight - currentHeight
|
||||||
|
if paddingNeeded > 0 {
|
||||||
|
result.WriteString(strings.Repeat("\n", paddingNeeded))
|
||||||
|
}
|
||||||
|
|
||||||
|
result.WriteString(footer.String())
|
||||||
|
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (m uiModel) viewEditMode() string {
|
func (m uiModel) viewEditMode() string {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue