Add archive and unarch commands

This commit is contained in:
Nikolay Puzanov 2015-10-15 13:14:02 +03:00
parent d0bd48b0a1
commit 2bf8890d96
5 changed files with 178 additions and 64 deletions

View File

@ -20,6 +20,9 @@
timesheet week [DATE] Show raw events for current week or week of DATE timesheet week [DATE] Show raw events for current week or week of DATE
timesheet month [DATE] Show raw events for current month or month of DATE timesheet month [DATE] Show raw events for current month or month of DATE
timesheet TASK Show raw events timesheet TASK Show raw events
archive Show archive tasks
archive TASK Add task to archive
unarch TASK Remove task from archive
refresh Refresh worksheet file after manual edit refresh Refresh worksheet file after manual edit
(no command) Show running task and timer (no command) Show running task and timer
@ -53,7 +56,6 @@
$ worktimer.scm report $ worktimer.scm report
--- REPORT --- REPORT
Overall: 00:03:45 Overall: 00:03:45
uberproject: 00:03:45 uberproject: 00:03:45
website: 00:03:45 website: 00:03:45
@ -118,6 +120,11 @@
`timesheet`. Эта команда показывает выполнявшиеся задачи в таком виде, в котором `timesheet`. Эта команда показывает выполнявшиеся задачи в таком виде, в котором
они сохраняются на диск. Параметры команды такие-же, как у команды `report`. они сохраняются на диск. Параметры команды такие-же, как у команды `report`.
Задачи (или подзадачи) можно отправлять в архив командой `archive [TASK]`. После этого
они перестают отображаться в отчете и в списке задач. Посмотреть список
архивированных задач можно командой `archive` без параметров. Деархивировать
задачу можно командой `unarch [TASK]`.
# Автодополнение для zsh # Автодополнение для zsh
Для включения автодополнения в zsh скопируйте файл `zsh-completion/_timer` в Для включения автодополнения в zsh скопируйте файл `zsh-completion/_timer` в
@ -134,5 +141,3 @@
Автодополнение в bash включается так: Автодополнение в bash включается так:
$ . bash-completion/timer $ . bash-completion/timer
[![Join the chat at https://gitter.im/punzik/worktimer](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/punzik/worktimer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

View File

@ -27,6 +27,9 @@
timesheet week [DATE] Show raw events for current week or week of DATE timesheet week [DATE] Show raw events for current week or week of DATE
timesheet month [DATE] Show raw events for current month or month of DATE timesheet month [DATE] Show raw events for current month or month of DATE
timesheet TASK Show raw events timesheet TASK Show raw events
archive Show archive tasks
archive TASK Add task to archive
unarch TASK Remove task from archive
refresh Refresh worksheet file after manual edit refresh Refresh worksheet file after manual edit
(no command) Show running task and timer (no command) Show running task and timer
#+end_src #+end_src
@ -139,6 +142,11 @@
=timesheet=. Эта команда показывает выполнявшиеся задачи в таком виде, в котором =timesheet=. Эта команда показывает выполнявшиеся задачи в таком виде, в котором
они сохраняются на диск. Параметры команды такие-же, как у команды =report=. они сохраняются на диск. Параметры команды такие-же, как у команды =report=.
Задачи (или подзадачи) можно отправлять в архив командой =archive [TASK]=. После этого
они перестают отображаться в отчете и в списке задач. Посмотреть список
архивированных задач можно командой =archive= без параметров. Деархивировать
задачу можно командой =unarch [TASK]=.
** Автодополнение для zsh ** Автодополнение для zsh
Для включения автодополнения в zsh скопируйте файл =zsh-completion/_timer= в Для включения автодополнения в zsh скопируйте файл =zsh-completion/_timer= в
=~/.zsh-completion/=, и добавте в файл =~/.zshrc= строки =~/.zsh-completion/=, и добавте в файл =~/.zshrc= строки

View File

@ -5,12 +5,12 @@ _timer()
case "$COMP_CWORD" in case "$COMP_CWORD" in
1) 1)
# Commands # Commands
COMPREPLY=( $(compgen -W "start stop report deadline refresh timesheet help" -- $uncomplete) ) COMPREPLY=( $(compgen -W "start stop report deadline archive unarch refresh timesheet help" -- $uncomplete) )
;; ;;
2) 2)
# Command argument 1 # Command argument 1
case "${COMP_WORDS[1]}" in case "${COMP_WORDS[1]}" in
start) start|archive)
local tasklist=$(timer tasklist) local tasklist=$(timer tasklist)
COMPREPLY=( $(compgen -W "$tasklist" -- $uncomplete)) COMPREPLY=( $(compgen -W "$tasklist" -- $uncomplete))
;; ;;
@ -22,6 +22,10 @@ _timer()
local deadlist=$(timer deadlist) local deadlist=$(timer deadlist)
COMPREPLY=( $(compgen -W "set clear all $deadlist" -- $uncomplete)) COMPREPLY=( $(compgen -W "set clear all $deadlist" -- $uncomplete))
;; ;;
unarch)
local archlist=$(timer archlist)
COMPREPLY=( $(compgen -W "$archlist" -- $uncomplete))
;;
esac esac
;; ;;
3) 3)

View File

@ -137,6 +137,16 @@
(loop (cdr a) (cdr b)) (loop (cdr a) (cdr b))
(string< (car a) (car b)))))))) (string< (car a) (car b))))))))
;;; Path prefixes with prefix?
(define (path-prefix? path prefix)
(let loop ((path path)
(prefix prefix))
(if (null? prefix) #t
(if (null? path) #f
(if (string=? (car path) (car prefix))
(loop (cdr path) (cdr prefix))
#f)))))
;;; Compare dates ;;; Compare dates
(define (date<? a b) (define (date<? a b)
(let ((ta (date->time-utc a)) (let ((ta (date->time-utc a))
@ -273,6 +283,13 @@
(apply append (cons records more))) (apply append (cons records more)))
string<?))) string<?)))
;;; Check the path it belongs to archive
(define (path-in-archive? path archive)
(let loop ((a archive))
(if (null? a) #f
(if (path-prefix? path (car a)) #t
(loop (cdr a))))))
;;; ========================= PROJECT MAIN FUNCTIONS ========================== ;;; ========================= PROJECT MAIN FUNCTIONS ==========================
;;; Parse task string and return list: ;;; Parse task string and return list:
@ -325,22 +342,27 @@
(lambda (port) (lambda (port)
(let loop ((record-type 'unknown) (let loop ((record-type 'unknown)
(timerecords '()) (timerecords '())
(deadlines '())) (deadlines '())
(archives '()))
(let ((line (get-line port))) (let ((line (get-line port)))
(if (eof-object? line) (if (eof-object? line)
(values (remove-dup (values (remove-dup
(sort timerecords timerecord<?)) (sort timerecords timerecord<?))
(remove-dup (remove-dup
(sort deadlines deadline<?))) (sort deadlines deadline<?))
(remove-dup
(sort archives path<?)))
(let ((line (string-trim-both line))) (let ((line (string-trim-both line)))
(cond (cond
((or (string-null? line) ((or (string-null? line)
(eq? (string-ref line 0) #\#)) (eq? (string-ref line 0) #\#))
(loop record-type timerecords deadlines)) (loop record-type timerecords deadlines archives))
((string-ci=? line "--- DEADLINES") ((string-ci=? line "--- DEADLINES")
(loop 'deadline timerecords deadlines)) (loop 'deadline timerecords deadlines archives))
((string-ci=? line "--- TIMESHEET") ((string-ci=? line "--- TIMESHEET")
(loop 'timerecord timerecords deadlines)) (loop 'timerecord timerecords deadlines archives))
((string-ci=? line "--- ARCHIVE")
(loop 'archive timerecords deadlines archives))
(else (else
(cond (cond
((eq? record-type 'timerecord) ((eq? record-type 'timerecord)
@ -351,7 +373,8 @@
(begin (begin
(format #t "Warning: Line '~a' is not a timerecord. Skip.\n" line) (format #t "Warning: Line '~a' is not a timerecord. Skip.\n" line)
timerecords))) timerecords)))
deadlines)) deadlines
archives))
((eq? record-type 'deadline) ((eq? record-type 'deadline)
(loop record-type (loop record-type
timerecords timerecords
@ -360,8 +383,19 @@
(cons item deadlines) (cons item deadlines)
(begin (begin
(format #t "Warning: Line '~a' is not a deadline. Skip.\n" line) (format #t "Warning: Line '~a' is not a deadline. Skip.\n" line)
deadlines))))) deadlines)))
(else (loop record-type timerecords deadlines))))))))))) archives))
((eq? record-type 'archive)
(loop record-type
timerecords
deadlines
(let ((item (path-split line)))
(if item
(cons item archives)
(begin
(format #t "Warning: Line '~a' is not a archive path. Skip.\n" line)
archives)))))
(else (loop record-type timerecords deadlines archives)))))))))))
(values '() '()))) (values '() '())))
;;; Print deadline record ;;; Print deadline record
@ -400,11 +434,20 @@
(define (print-deadlines deadlines) (define (print-deadlines deadlines)
(for-each print-deadline (sort deadlines deadline<?))) (for-each print-deadline (sort deadlines deadline<?)))
;;; Print archives
(define (print-archives archives)
(for-each
(lambda (a) (format #t "~a\n" (path->string a)))
archives))
;;; Print timesheet ;;; Print timesheet
(define (print-timesheet timesheet deadlines) (define (print-timesheet timesheet deadlines archives)
(unless (null? deadlines) (unless (null? deadlines)
(format #t "--- DEADLINES\n") (format #t "--- DEADLINES\n")
(print-deadlines deadlines)) (print-deadlines deadlines))
(unless (null? deadlines)
(format #t "--- ARCHIVE\n")
(print-archives archives))
(unless (null? timesheet) (unless (null? timesheet)
(format #t "--- TIMESHEET\n") (format #t "--- TIMESHEET\n")
(print-timerecords timesheet))) (print-timerecords timesheet)))
@ -427,7 +470,7 @@
(set-car! (cdr tree) (add-duration (cadr tree) duration)) (set-car! (cdr tree) (add-duration (cadr tree) duration))
;; Search next leaf corresponding to path item ;; Search next leaf corresponding to path item
(if (null? path) (if (or (null? path))
project-tree project-tree
(let ((item (find (let ((item (find
(lambda (i) (string= (car i) (car path))) (lambda (i) (string= (car i) (car path)))
@ -569,10 +612,17 @@
(filter filter-lambda sheet) (filter filter-lambda sheet)
description))))) description)))))
;;; Remove archived tasks from sheet
(define (not-archived sheet archives)
(filter (lambda (x)
(not (path-in-archive?
(car x)
archives))) sheet))
;;; ================================ COMMANDS ================================== ;;; ================================ COMMANDS ==================================
;;; Start new task. Returns new sheet with started task or #f if nothing started. ;;; Start new task. Returns new sheet with started task or #f if nothing started.
(define (cmd-start-task sheet deadlines . params) (define (cmd-start-task sheet deadlines archives . params)
(let* ((last (last-task sheet)) (let* ((last (last-task sheet))
(path (if (null? params) (path (if (null? params)
(if last (car last) #f) (if last (car last) #f)
@ -582,33 +632,35 @@
(begin (format (begin (format
(current-error-port) (current-error-port)
"Not specified task path. No tasks in the sheet.\n") "Not specified task path. No tasks in the sheet.\n")
(values #f #f)) (values #f #f #f))
(begin (begin
(stop-task last) (stop-task last)
(let-values (((sheet task) (new-task sheet path))) (let-values (((sheet task) (new-task sheet path)))
(format #t "--- NEW TASK RUN\n") (format #t "--- NEW TASK RUN\n")
(print-timerecord task) (print-timerecord task)
(values sheet deadlines)))))) (values sheet deadlines archives))))))
;;; Stop a running task. Returns new sheet or #f if nothing to stop. ;;; Stop a running task. Returns new sheet or #f if nothing to stop.
(define (cmd-stop-task sheet deadlines . params) (define (cmd-stop-task sheet deadlines archives . params)
(let ((last (last-task sheet))) (let ((last (last-task sheet)))
(if (stop-task last) (if (stop-task last)
(begin (begin
(format #t "--- STOP TASK\n") (format #t "--- STOP TASK\n")
(print-timerecord last) (print-timerecord last)
(values sheet deadlines)) (values sheet deadlines archives))
(begin (begin
(format (current-error-port) "Nothing to stop\n") (format (current-error-port) "Nothing to stop\n")
(values #f #f))))) (values #f #f #f)))))
;;; Print report ;;; Print report
(define (cmd-report sheet deadlines . params) (define (cmd-report sheet deadlines archives . params)
(format #t "--- REPORT") (format #t "--- REPORT")
(let ((qualis (nth-maybe 0 params)) (let ((qualis (nth-maybe 0 params))
(range (nth-maybe 1 params))) (range (nth-maybe 1 params)))
(let-values (((sheet description) (let-values (((sheet description)
(filter-sheet sheet qualis range))) (filter-sheet
(not-archived sheet archives)
qualis range)))
(when (not (null? description)) (when (not (null? description))
(display ". ") (display ". ")
(display description)) (display description))
@ -622,27 +674,38 @@
(format #t "\n--- ~a TASK\n" (format #t "\n--- ~a TASK\n"
(if (caddr last) "LAST STOPPED" "RUNNING")) (if (caddr last) "LAST STOPPED" "RUNNING"))
(print-timerecord last (current-date)))) (print-timerecord last (current-date))))
(values #f #f)) (values #f #f #f))
;;; Print all tasks ;;; Print all tasks
(define (cmd-tasklist sheet deadlines . unused) (define (cmd-tasklist sheet deadlines archives . unused)
(format #t "~{~a ~}\n" (record-path-list sheet deadlines)) (format #t "~{~a ~}\n" (record-path-list
(values #f #f)) (not-archived sheet archives)
deadlines))
(values #f #f #f))
;;; Print deadlines ;;; Print deadlines
(define (cmd-deadlist sheet deadlines . unused) (define (cmd-deadlist sheet deadlines archives . unused)
(format #t "~{~a ~}\n" (record-name-list deadlines)) (format #t "~{~a ~}\n" (record-name-list deadlines))
(values #f #f)) (values #f #f #f))
;;; Print archive
(define (cmd-archlist sheet deadlines archives . unused)
(format #t "~{~a ~}\n"
(remove-dup
(sort
(map (lambda (x) (path->string x)) archives)
string<?)))
(values #f #f #f))
;;; Print last task ;;; Print last task
(define (cmd-lasttask sheet deadlines . unused) (define (cmd-lasttask sheet deadlines archives . unused)
(let ((last (last-task sheet))) (let ((last (last-task sheet)))
(when (not (null? last)) (when (not (null? last))
(format #t "~a\n" (path->string (car last))))) (format #t "~a\n" (path->string (car last)))))
(values #f #f)) (values #f #f #f))
;;; Deadlines ;;; Deadlines
(define (cmd-deadline sheet deadlines . args) (define (cmd-deadline sheet deadlines archives . args)
(let ((deadlines (let ((deadlines
(let* ((arg0 (if (null? args) #f (car args))) (let* ((arg0 (if (null? args) #f (car args)))
(arg1 (if (and arg0 (not (null? (cdr args)))) (cadr args) #f)) (arg1 (if (and arg0 (not (null? (cdr args)))) (cadr args) #f))
@ -712,28 +775,54 @@
deadlines)) deadlines))
#f))))) #f)))))
(if deadlines (if deadlines
(values sheet deadlines) (values sheet deadlines archives)
(values #f #f)))) (values #f #f #f))))
;;; Events ;;; Events
(define (cmd-timesheet sheet deadlines . params) (define (cmd-timesheet sheet deadlines archives . params)
(format #t "--- TIMESHEET") (format #t "--- TIMESHEET")
(let ((qualis (nth-maybe 0 params)) (let ((qualis (nth-maybe 0 params))
(range (nth-maybe 1 params))) (range (nth-maybe 1 params)))
(let-values (((sheet description) (let-values (((sheet description)
(filter-sheet sheet qualis range))) (filter-sheet
(not-archived sheet archives)
qualis range)))
(when (not (null? description)) (when (not (null? description))
(display ". ") (display ". ")
(display description)) (display description))
(newline) (newline)
(print-timerecords sheet))) (print-timerecords sheet)))
(values #f #f)) (values #f #f #f))
;;; Archive
(define (cmd-archive sheet deadlines archives . params)
(let ((task-str (nth-maybe 0 params)))
(if (null? task-str)
(begin
(format #t "--- ARCHIVE\n")
(print-archives archives)
(values #f #f #f))
(values sheet
deadlines
(cons (path-split task-str) archives)))))
;;; Unarchive
(define (cmd-unarch sheet deadlines archives . params)
(let ((task-str (nth-maybe 0 params)))
(if (null? task-str)
(values #f #f #f)
(let ((task (path-split task-str)))
(values sheet
deadlines
(fold (lambda (p a)
(if (equal? p task) a
(cons p a))) '() archives))))))
;;; ================================ MAIN FUNCTION ================================== ;;; ================================ MAIN FUNCTION ==================================
(define (main cmdl) (define (main cmdl)
(let ((command (cdr cmdl))) (let ((command (cdr cmdl)))
(let-values (((sheet deadlines) (read-timesheet ts-file))) (let-values (((sheet deadlines archives) (read-timesheet ts-file)))
(if (null? command) (if (null? command)
;; Show running task ;; Show running task
@ -765,18 +854,21 @@
(let ((param (cdr command)) (let ((param (cdr command))
(command (car command))) (command (car command)))
(let-values (let-values
(((sheet' deadlines') (((sheet' deadlines' archives')
(apply (apply
(cond (cond
((string= command "start") cmd-start-task) ((string= command "start") cmd-start-task)
((string= command "stop") cmd-stop-task) ((string= command "stop") cmd-stop-task)
((string= command "report") cmd-report) ((string= command "report") cmd-report)
((string= command "refresh") (lambda (s d . p) (values s d))) ((string= command "refresh") (lambda (s d a . p) (values s d a)))
((string= command "deadline") cmd-deadline) ((string= command "deadline") cmd-deadline)
((string= command "timesheet") cmd-timesheet) ((string= command "timesheet") cmd-timesheet)
((string= command "archive") cmd-archive)
((string= command "unarch") cmd-unarch)
;; Service commands ;; Service commands
((string= command "tasklist") cmd-tasklist) ((string= command "tasklist") cmd-tasklist)
((string= command "deadlist") cmd-deadlist) ((string= command "deadlist") cmd-deadlist)
((string= command "archlist") cmd-archlist)
((string= command "lasttask") cmd-lasttask) ((string= command "lasttask") cmd-lasttask)
;; ----------------------- Show usage ------------------------- ;; ;; ----------------------- Show usage ------------------------- ;;
@ -801,13 +893,16 @@
(format #t " timesheet week [DATE] Show raw events for current week or week of DATE\n") (format #t " timesheet week [DATE] Show raw events for current week or week of DATE\n")
(format #t " timesheet month [DATE] Show raw events for current month or month of DATE\n") (format #t " timesheet month [DATE] Show raw events for current month or month of DATE\n")
(format #t " timesheet TASK Show raw events\n") (format #t " timesheet TASK Show raw events\n")
(format #t " archive Show archive tasks\n")
(format #t " archive TASK Add task to archive\n")
(format #t " unarch TASK Remove task from archive\n")
(format #t " refresh Refresh worksheet file after manual edit\n") (format #t " refresh Refresh worksheet file after manual edit\n")
(format #t " (no command) Show running task and timer\n\n") (format #t " (no command) Show running task and timer\n\n")
(format #t "DATE format: YYYY-mm-dd\n") (format #t "DATE format: YYYY-mm-dd\n")
(format #t "TIME format: HH:MM:SS\n") (format #t "TIME format: HH:MM:SS\n")
(newline))) (newline)))
(lambda (s d . p) (values #f #f)))) (lambda (s d a . p) (values #f #f #f))))
(cons* sheet deadlines param)))) (cons* sheet deadlines archives param))))
;; ----------------------- Save new sheet ------------------------- ;; ;; ----------------------- Save new sheet ------------------------- ;;
(when (and (when (and
@ -815,7 +910,7 @@
(not (null? sheet'))) (not (null? sheet')))
(with-output-to-file ts-file (with-output-to-file ts-file
(lambda () (lambda ()
(print-timesheet sheet' deadlines')))))))))) (print-timesheet sheet' deadlines' archives'))))))))))
;;; JUST DO IT! ;;; JUST DO IT!
(main (command-line)) (main (command-line))

View File

@ -13,13 +13,13 @@ _timer() {
case "$state" in case "$state" in
(command) (command)
# Commands # Commands
_arguments '1:commands:(start stop report deadline refresh timesheet help)' _arguments '1:commands:(start stop report deadline archive unarch refresh timesheet help)'
;; ;;
(arg1) (arg1)
# Command argument 1 # Command argument 1
case $words[2] in case $words[2] in
(start) (start|archive)
compadd $(timer tasklist) compadd $(timer tasklist)
;; ;;
(report|timesheet) (report|timesheet)
@ -28,6 +28,8 @@ _timer() {
(deadline) (deadline)
compadd set clear all $(timer deadlist) compadd set clear all $(timer deadlist)
;; ;;
(unarch)
compadd $(timer archlist)
esac esac
;; ;;