diff options
| -rw-r--r-- | converter/main.go | 127 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | workstack.go | 76 | ||||
| -rw-r--r-- | ws/main.go (renamed from main.go) | 96 | 
4 files changed, 225 insertions, 76 deletions
| diff --git a/converter/main.go b/converter/main.go new file mode 100644 index 0000000..a863b2c --- /dev/null +++ b/converter/main.go @@ -0,0 +1,127 @@ +/* +Sample code to convert an old tasks.gob file to a newer format +This is scrpited and dangerous, keep backups!!! +*/ +package main + +import ( +	"encoding/gob" +	"fmt" +	"os" +	"time" + +	ws "git.spacehb.net/ws.git" +) + +func main() { + +	TasksDoneConv := []ws.TaskDone{} +	TasksConv := []ws.Task{} +	TagsConv := []ws.Tag{} + +	// Get old gobdata +	f, err := os.Open("tasks.gob") +	if err != nil { +		panic(err) +	} + +	dec := gob.NewDecoder(f) +	// old data format +	Tasks := []string{} +	TasksDone := []struct { +		Text string +		Date time.Time +	}{} +	err = dec.Decode(&TasksDone) +	if err != nil { +		panic(err) +	} +	err = dec.Decode(&Tasks) +	if err != nil { +		panic(err) +	} + +	// Get current gobdata +	f, err = os.Open(ws.GetGobdataPath()) +	if err != nil { +		panic(err) +	} +	dec = gob.NewDecoder(f) +	err = dec.Decode(&TasksConv) +	if err != nil { +		panic(err) +	} +	err = dec.Decode(&TasksDoneConv) +	if err != nil { +		panic(err) +	} +	err = dec.Decode(&TagsConv) +	if err != nil { +		panic(err) +	} + +	for _, v := range Tasks { +		start := false +		var tag []byte +		var text []byte +		for i := 0; i < len(v); i++ { +			if v[i] == '{' { +				start = true +				i++ +			} +			if v[i] == '}' { +				start = false +				i++ +			} +			if start == true { +				tag = append(tag, v[i]) +			} +			if start == false { +				text = append(text, v[i]) +			} +		} + +		tagstr := ws.Tag(tag) +		if len(TagsConv) == 0 { +			TagsConv = append(TagsConv, tagstr) +		} +		found := false +		for _, v := range TagsConv { +			if tagstr == v { +				found = true +				break +			} +		} +		if !found { +			TagsConv = append(TagsConv, ws.Tag(tag)) +		} + +		textstr := string(text[1:]) + +		TasksConv = append(TasksConv, ws.Task{Text: textstr, Tag: tagstr}) +		// fmt.Printf("tag: '%s' | text: '%s'\n", tag, text) +	} +	fmt.Printf("TagsConv: %#v\n", TagsConv) +	for i, v := range TasksConv { +		fmt.Printf("%2d. %s\n", i+1, v) +	} + +	// Save data to gobdata +	f, err = os.Create(ws.GetGobdataPath()) +	if err != nil { +		panic(err) +	} +	enc := gob.NewEncoder(f) +	err = enc.Encode(TasksConv) +	if err != nil { +		panic(err) +	} +	err = enc.Encode(TasksDoneConv) +	if err != nil { +		panic(err) +	} +	err = enc.Encode(TagsConv) +	if err != nil { +		panic(err) +	} +} @@ -1,3 +1,3 @@ -module ws +module git.spacehb.net/ws.git  go 1.23.1 diff --git a/workstack.go b/workstack.go new file mode 100644 index 0000000..1205039 --- /dev/null +++ b/workstack.go @@ -0,0 +1,76 @@ +package workstack + +// Workstack or ws for short is a program that manages To-Do's in a stack-based fashion.  It tries +// to guide your focus to your three most important tasks such that you do not get distracted by +// other tasks. +// Every task added starts as inactive "[ ]" and can be marked as done by changing the status to +// "[x]". +// When the programs exits Tasks are saved to a tasks.gob file, this will truncate (os.Create) the +// existing file. + +// TODO's +// - edit functionality +// - import: read multiple lines from stdin and import them as taks +// - parsing text as Tasks, maybe helper program? +// - clocking functionality with a 'task' command +// - testing: +//	- [ ] add +//  - [ ] done +//  - [ ] undone +//  - [ ] del +//  - [ ] pc +//  - [ ] <no arg> +//	- [ ] ls +//	- [ ] list +//	- [ ] tag +//	- [ ] tagd +//	- [ ] tagl + +import ( +	"fmt" +	"os" +	"time" +) + +type TaskDone struct { +	Task Task +	Date time.Time +} + +func (t TaskDone) String() string { +	return fmt.Sprintf("(%s) %s", t.Date.Format(DateLayout), t.Task) +} + +type Tag string + +type Task struct { +	Text string +	Tag  Tag +} + +func (t Task) String() string { +	if t.Tag != "" { +		return fmt.Sprintf("{%s} %s", t.Tag, t.Text) +	} else { +		return fmt.Sprintf("%s", t.Text) +	} +} + +var ( +	// Persistent storage for Tasks +	Gobdata    string = "tasks.gob" +	DateLayout string = "15:04:05 02/01/2006" +) + +const ( +	TASK_LIST_COUNT  = 5 +	GOBDATA_FILENAME = "tasks.gob" +) + +func GetGobdataPath() string { +	p := os.Getenv("HOME") +	if p == "" { +		panic("HOME var not set.") +	} +	return p + "/sync/share/" + GOBDATA_FILENAME +} @@ -1,31 +1,5 @@  package main -// Workstack or ws for short is a program that manages To-Do's in a stack-based fashion.  It tries -// to guide your focus to your three most important tasks such that you do not get distracted by -// other tasks. -// Every task added starts as inactive "[ ]" and can be marked as done by changing the status to -// "[x]". -// When the programs exits Tasks are saved to a tasks.gob file, this will truncate (os.Create) the -// existing file. - -// TODO's -// - edit functionality -// - import: read multiple lines from stdin and import them as taks -// - parsing text as Tasks, maybe helper program? -// - clocking functionality with a 'task' command -// - testing: -//	- [ ] add -//  - [ ] done -//  - [ ] undone -//  - [ ] del -//  - [ ] pc -//  - [ ] <no arg> -//	- [ ] ls -//	- [ ] list -//	- [ ] tag -//	- [ ] tagd -//	- [ ] tagl -  import (  	"encoding/gob"  	"errors" @@ -34,44 +8,18 @@ import (  	"strconv"  	"strings"  	"time" -) - -type TaskDone struct { -	Task Task -	Date time.Time -} - -func (t TaskDone) String() string { -	return fmt.Sprintf("(%s) %s", t.Date.Format(DateLayout), t.Task) -} - -type Task struct { -	Text string -	Tag  string -} -func (t Task) String() string { -	if t.Tag != "" { -		return fmt.Sprintf("%s {%s}", t.Text, t.Tag) -	} else { -		return fmt.Sprintf("%s", t.Text) -	} -} +	ws "git.spacehb.net/ws.git" +)  var (  	// Stack of active tasks -	Tags []string +	Tags []ws.Tag  	// Active tasks -	Tasks []Task +	Tasks []ws.Task  	// Completed tasks -	TasksDone []TaskDone +	TasksDone []ws.TaskDone  	// Persistent storage for Tasks -	Gobdata    string = "tasks.gob" -	DateLayout string = "15:04:05 02/01/2006" -) - -const ( -	TASK_LIST_COUNT = 5  )  // Search for arg in Args and return the index at which it was found @@ -119,20 +67,16 @@ func ParseNArg(pos, def, max int) int {  }  func main() { -	// create tasks.gob file -	var dec *gob.Decoder -	var f *os.File -	var err error +	var ( +		dec         *gob.Decoder +		f           *os.File +		err         error +		gobdataPath string = ws.GetGobdataPath() +	)  	// Open/Create gob data file if not exist  	{ -		p := os.Getenv("HOME") -		if p == "" { -			panic("HOME var not set.") -		} -		Gobdata = p + "/sync/share/" + Gobdata - -		f, err = os.Open(Gobdata) +		f, err = os.Open(gobdataPath)  		if errors.Is(err, os.ErrNotExist) {  			// Do nothing  		} else if err != nil { @@ -212,14 +156,16 @@ func main() {  		}  		if tagName == "" { -			Tasks = append(Tasks, Task{Text: taskText}) +			Tasks = append(Tasks, ws.Task{Text: taskText})  			break  		} +		tag := ws.Tag(tagName) +  		// Validate tag  		found := false  		for _, v := range Tags { -			if tagName == v { +			if tag == v {  				found = true  				break  			} @@ -228,7 +174,7 @@ func main() {  			fmt.Printf("No tag '%s' found.\n", tagName)  			os.Exit(1)  		} -		Tasks = append(Tasks, Task{Text: taskText, Tag: tagName}) +		Tasks = append(Tasks, ws.Task{Text: taskText, Tag: tag})  	// Delete an active task  	case "del": @@ -238,7 +184,7 @@ func main() {  	// Mark an active task as done  	case "done":  		n := ParseNArg(2, 1, len(Tasks)) -		TasksDone = append(TasksDone, TaskDone{ +		TasksDone = append(TasksDone, ws.TaskDone{  			Task: Tasks[n-1],  			Date: time.Now(),  		}) @@ -268,7 +214,7 @@ func main() {  			fmt.Println("No tasks.")  			break  		} -		for i := 0; i < len(Tasks) && i < TASK_LIST_COUNT; i++ { +		for i := 0; i < len(Tasks) && i < ws.TASK_LIST_COUNT; i++ {  			fmt.Printf("%d. %s\n", i+1, Tasks[i])  		} @@ -289,7 +235,7 @@ func main() {  	// create a new tag  	case "tag": -		tagName := strings.Join(os.Args[2:], " ") +		tagName := ws.Tag(strings.Join(os.Args[2:], " "))  		for i := 0; i < len(Tags); i++ {  			if tagName == Tags[i] {  				fmt.Printf("Tag '%s' already exists.\n", tagName) @@ -324,7 +270,7 @@ COMMANDS  	}  	// Save data to gobdata -	f, err = os.Create(Gobdata) +	f, err = os.Create(gobdataPath)  	if err != nil {  		panic(err)  	} | 
