mirror of
https://github.com/RWejlgaard/org.git
synced 2026-09-02 01:15:35 +00:00
feat: add configurable done flag to TODO states
This commit is contained in:
parent
25dd231073
commit
5b10f4e229
2 changed files with 81 additions and 1 deletions
|
|
@ -83,6 +83,7 @@ type TagsConfig struct {
|
|||
type StateConfig struct {
|
||||
Name string `toml:"name"`
|
||||
Color string `toml:"color"`
|
||||
Done bool `toml:"done,omitempty"`
|
||||
}
|
||||
|
||||
// StatesConfig holds TODO state configurations
|
||||
|
|
@ -163,7 +164,7 @@ func DefaultConfig() *Config {
|
|||
{Name: "TODO", Color: "202"},
|
||||
{Name: "PROG", Color: "220"},
|
||||
{Name: "BLOCK", Color: "196"},
|
||||
{Name: "DONE", Color: "34"},
|
||||
{Name: "DONE", Color: "34", Done: true},
|
||||
},
|
||||
DefaultNewTaskState: "TODO",
|
||||
},
|
||||
|
|
@ -393,6 +394,21 @@ func (c *Config) fillDefaults() {
|
|||
// Note: We don't fill DefaultNewTaskState if States.States is non-empty because
|
||||
// an empty string is a valid intentional value meaning "no default state".
|
||||
|
||||
// Back-compat: if states exist but none is flagged done (config predates the
|
||||
// `done` field), treat the last state as done to preserve prior behavior.
|
||||
if len(c.States.States) > 0 {
|
||||
anyDone := false
|
||||
for _, s := range c.States.States {
|
||||
if s.Done {
|
||||
anyDone = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !anyDone {
|
||||
c.States.States[len(c.States.States)-1].Done = true
|
||||
}
|
||||
}
|
||||
|
||||
// Fill UI if zero values
|
||||
if c.UI.HelpTextWidth == 0 {
|
||||
c.UI.HelpTextWidth = defaults.UI.HelpTextWidth
|
||||
|
|
@ -511,6 +527,19 @@ func (c *Config) GetStateNames() []string {
|
|||
return names
|
||||
}
|
||||
|
||||
// IsDoneState reports whether the named state is configured as a done state.
|
||||
func (c *Config) IsDoneState(name string) bool {
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
for _, state := range c.States.States {
|
||||
if state.Name == name {
|
||||
return state.Done
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UpdateKeybinding updates a keybinding in the configuration
|
||||
func (c *Config) UpdateKeybinding(action string, keys []string) error {
|
||||
// Use reflection would be complex, so we handle specific cases
|
||||
|
|
|
|||
51
internal/config/config_test.go
Normal file
51
internal/config/config_test.go
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package config
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIsDoneState(t *testing.T) {
|
||||
c := &Config{States: StatesConfig{States: []StateConfig{
|
||||
{Name: "TODO", Color: "202"},
|
||||
{Name: "DONE", Color: "34", Done: true},
|
||||
{Name: "CANCELLED", Color: "240", Done: true},
|
||||
}}}
|
||||
|
||||
cases := map[string]bool{"TODO": false, "DONE": true, "CANCELLED": true, "": false, "NOPE": false}
|
||||
for name, want := range cases {
|
||||
if got := c.IsDoneState(name); got != want {
|
||||
t.Errorf("IsDoneState(%q) = %v, want %v", name, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillDefaultsMarksLastStateDoneWhenNoneFlagged(t *testing.T) {
|
||||
c := &Config{States: StatesConfig{States: []StateConfig{
|
||||
{Name: "TODO", Color: "202"},
|
||||
{Name: "DONE", Color: "34"},
|
||||
}}}
|
||||
c.fillDefaults()
|
||||
|
||||
if c.States.States[len(c.States.States)-1].Name != "DONE" {
|
||||
t.Fatalf("states reordered unexpectedly")
|
||||
}
|
||||
if !c.States.States[len(c.States.States)-1].Done {
|
||||
t.Error("expected last state (DONE) to be flagged Done after migration")
|
||||
}
|
||||
if c.States.States[0].Done {
|
||||
t.Error("expected first state (TODO) to remain not-done")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFillDefaultsLeavesExplicitDoneFlagsAlone(t *testing.T) {
|
||||
c := &Config{States: StatesConfig{States: []StateConfig{
|
||||
{Name: "DONE", Color: "34", Done: true},
|
||||
{Name: "TODO", Color: "202"},
|
||||
}}}
|
||||
c.fillDefaults()
|
||||
|
||||
if c.States.States[0].Name != "DONE" || !c.States.States[0].Done {
|
||||
t.Error("explicit done flag on DONE should be preserved")
|
||||
}
|
||||
if c.States.States[1].Done {
|
||||
t.Error("last state (TODO) must NOT be auto-flagged when a done state already exists")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue