Browse Source

++todo-bingo

master
Maxim Likhachev 4 years ago
parent
commit
1ca023c94b
  1. 3
      README.md
  2. 238
      scripts/todo-bingo

3
README.md

@ -60,11 +60,12 @@ will create the symbolic link for each script in the \<path> directory. @@ -60,11 +60,12 @@ will create the symbolic link for each script in the \<path> directory.
- [photosort](scripts/photosort) renames the image files by exif data.
- [th](scripts/th) makes an image thumbnail.
## Notes
## Notes, Todo Tools
- [dates](scripts/dates) + conky or similar software remind of upcoming events (birthdays, etc.).
- [mem](scripts/mem) stores the shorts notes in the file.
- [pomodoro](scripts/pomodoro) tracks the working time.
- [todo-bingo](scripts/todo-bingo) provides a simple GUI to visualize TODO lists.
## Network

238
scripts/todo-bingo

@ -0,0 +1,238 @@ @@ -0,0 +1,238 @@
#!/usr/bin/env tclsh
# Copyright (C) 2021, Maxim Lihachev, <envrm@yandex.ru>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
#
# Simple Bingo-style TODO visualizer.
#
# Input:
#
# todo.md:
#
# - [ ] A
# - [x] B
# - [x] C
# - [ ] …
# - [ ] V
#
# GUI:
#
# ┌───────────────────────┐
# ├───┬───┬───┬───┬───┬───┤
# │ A │ B │ C │ D │ E │ F │
# ├───┼───┼───┼───┼───┼───┤
# │ A │ B │ C │ D │ E │ F │
# ├───┼───┼───┼───┼───┼───┤
# │ G │ H │ I │ J │ K │ L │
# ├───┼───┼───┼───┼───┼───┤
# │ M │ N │ O │ P │ Q │ R │
# ├───┴─┬─┴───┼───┴─┬─┴───┤
# │ S │ T │ U │ V │
# ├─────┴─────┴─────┴─────┤
# │ 10/22 [45%] │
# └───────────────────────┘
#
#
# TODO: работа с повторяющимися строками
#
package require fileutil
proc help {} {
puts "USAGE: [file tail $::argv0] <todo.md>"
}
namespace eval todo {
set file {}
set data {}
set list {}
set status {}
array set format {
marker {^\s*-\s+\[[ xX]\]\s*}
done {^\s*-\s+\[[xX]\]\s*}
todo {^\s*-\s+\[[ ]\]\s*}
}
proc sanitize_string {str} {
string map {
{*} {\*} {+} {\+} {[} {\[} {]} {\]} {.} {\.}
{(} {\(} {)} {\)} {\{} {\\{} {\}} {\\}}
} $str
}
proc load {filename} {
todo::update [split [fileutil::cat [set ::todo::file $filename]] "\n"]
todo::update_status
}
proc update {data} {
set ::todo::data $data
}
proc update_list {} {
set ::todo::list [lsearch -all -inline -regexp $::todo::data {^[\s]*-[\s]\[[ xX]\]\s.*$}]
}
proc update_status {} {
::todo::update_list
set total_items [llength $::todo::list]
set done_items [llength [regexp -inline -all -nocase {\[[xX]\]} $::todo::list]]
set percents [expr {$done_items * 100 / $total_items}]
set ::todo::status "$done_items/$total_items \[${percents}%\]"
}
proc update_file {} {
fileutil::writeFile $::todo::file [join $::todo::data "\n"]
}
proc update_item {item} {
set item_pattern $::todo::format(marker)[::todo::sanitize_string [lindex $item end]]
set todo_string [lsearch -inline -regexp $::todo::data $item_pattern]
set todo_index [lsearch -exact $::todo::data $todo_string]
set updated_todo [::todo::toggle_marker $todo_string]
::todo::update_list
::todo::update [lreplace $::todo::data $todo_index $todo_index $updated_todo]
::todo::update_status
::todo::update_file
}
# Toggle todo markers:
# "- [ ]" -> "- [x]"
# "- [x]" -> "- [ ]"
proc toggle_marker {str} {
string map {{- [ ]} {- [x]} {- [x]} {- [ ]} {- [X]} {- [ ]}} $str
}
}
namespace eval gui {
proc set_theme {} {
ttk::style theme use clam
set layout [ttk::style layout TButton]
set tail [lindex $layout end]
ttk::style layout Button.TODO [lreplace $layout end end $tail]
ttk::style configure Button.TODO {*}[ttk::style configure TButton] -background LightBlue -wraplength 150
ttk::style map Button.TODO {*}[ttk::style map TButton] -background {active LightSteelBlue}
ttk::style layout Button.DONE [lreplace $layout end end $tail]
ttk::style configure Button.DONE {*}[ttk::style configure TButton] -background GreenYellow -wraplength 150
ttk::style map Button.DONE {*}[ttk::style map TButton] -background {active LawnGreen}
}
proc set_button_status {button status} {
set status [string toupper $status]
$button configure -style Button.$status
if {$status == "TODO"} {
set ::gui::state($button) 0
} else {
set ::gui::state($button) 1
}
}
proc toggle_button_status {button} {
if {$::gui::state($button)} {
::gui::set_button_status $button todo
} else {
::gui::set_button_status $button done
}
::todo::update_item [lsearch -inline [$button configure] {-text*}]
}
proc show {} {
::gui::set_theme
set columns [expr {ceil(sqrt([llength $::todo::list]))}]
lassign {0 0 0} current_column current_frame current_todo_item
foreach todo_item $::todo::list {
if {$current_column == 0} {
pack [set f [frame .[incr current_frame]]] -expand on -fill both -side top
}
::gui::draw_todo_button "${f}.todo-[incr current_todo_item]" $todo_item
if {$current_column == $columns} {
set current_column 0
} else {
incr current_column
}
}
::gui::draw_statusbar
::gui::bind_hotkeys
}
proc draw_todo_button {widget item} {
# Remove todo markers and useless spaces
regsub -expanded $::todo::format(marker) $item {} title
pack [ttk::button $widget -text $title -width 1 \
-command "::gui::toggle_button_status $widget"] \
-expand on -side left -fill both
tooltip::tooltip $widget $title
if {[regexp -expanded $::todo::format(todo) $item]} {
::gui::set_button_status $widget todo
} else {
::gui::set_button_status $widget done
}
}
proc draw_statusbar {} {
pack [frame .statusbar] -fill x
pack [label .statusbar.status -font {Serif 10} -textvariable ::todo::status -padx 3 -anchor e] -fill x
}
proc bind_hotkeys {} {
bind . <Control-q> exit
bind . <q> exit
}
}
# ------------------------------------------------------------------------------
if {$argc == 0} {
help
exit 1
} else {
set filename [lindex $argv 0]
if {![file exists $filename] || ![file writable $filename]} {
puts stderr "ERROR: File $filename does not exist or it is not writable."
exit 1
}
}
package require Tk
package require tooltip
todo::load $filename
gui::show
Loading…
Cancel
Save