github.com/wtfutil/wtf@v0.43.0/modules/todo/display.go (about)

     1  package todo
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/rivo/tview"
     9  	"github.com/wtfutil/wtf/checklist"
    10  	"github.com/wtfutil/wtf/utils"
    11  )
    12  
    13  func (widget *Widget) display() {
    14  	widget.Redraw(widget.content)
    15  }
    16  
    17  func (widget *Widget) content() (string, string, bool) {
    18  	str := ""
    19  	hidden := 0
    20  	if widget.settings.checkedPos == "last" {
    21  		str, hidden = widget.sortListByChecked(widget.list.UncheckedItems(), widget.list.CheckedItems())
    22  	} else if widget.settings.checkedPos == "first" {
    23  		str, hidden = widget.sortListByChecked(widget.list.CheckedItems(), widget.list.UncheckedItems())
    24  	} else {
    25  		str, hidden = widget.sortListByChecked(widget.list.Items, []*checklist.ChecklistItem{})
    26  	}
    27  
    28  	if widget.Error != "" {
    29  		str = widget.Error
    30  	}
    31  
    32  	title := widget.CommonSettings().Title
    33  	if widget.showTagPrefix != "" {
    34  		title += " #" + widget.showTagPrefix
    35  	}
    36  	if widget.showFilter != "" {
    37  		title += fmt.Sprintf(" /%s", widget.showFilter)
    38  	}
    39  	if widget.settings.hiddenNumInTitle {
    40  		title += fmt.Sprintf(" (%d hidden)", hidden)
    41  	}
    42  
    43  	return title, str, false
    44  }
    45  
    46  func (widget *Widget) sortListByChecked(firstGroup []*checklist.ChecklistItem, secondGroup []*checklist.ChecklistItem) (string, int) {
    47  	str := ""
    48  	hidden := 0
    49  	newList := checklist.NewChecklist(
    50  		widget.settings.Sigils.Checkbox.Checked,
    51  		widget.settings.Sigils.Checkbox.Unchecked,
    52  	)
    53  
    54  	offset := 0
    55  	selectedItem := widget.SelectedItem()
    56  	for idx, item := range firstGroup {
    57  		if widget.shouldShowItem(item) {
    58  			str += widget.formattedItemLine(idx, hidden, item)
    59  		} else {
    60  			hidden = hidden + 1
    61  		}
    62  		newList.Items = append(newList.Items, item)
    63  		offset++
    64  	}
    65  
    66  	for idx, item := range secondGroup {
    67  		if widget.shouldShowItem(item) {
    68  			str += widget.formattedItemLine(idx+offset, hidden, item)
    69  		} else {
    70  			hidden = hidden + 1
    71  		}
    72  		newList.Items = append(newList.Items, item)
    73  	}
    74  	if idx, ok := newList.IndexByItem(selectedItem); ok {
    75  		widget.Selected = idx
    76  	}
    77  
    78  	widget.SetList(newList)
    79  	return str, hidden
    80  }
    81  
    82  func (widget *Widget) shouldShowItem(item *checklist.ChecklistItem) bool {
    83  	if widget.showFilter != "" && !strings.Contains(strings.ToLower(item.Text), widget.showFilter) {
    84  		return false
    85  	}
    86  
    87  	if !widget.settings.parseTags {
    88  		return true
    89  	}
    90  
    91  	if len(item.Tags) == 0 {
    92  		return widget.showTagPrefix == ""
    93  	}
    94  
    95  	for _, tag := range item.Tags {
    96  		for _, hideTag := range widget.settings.hideTags {
    97  			if widget.showTagPrefix == "" && tag == hideTag {
    98  				return false
    99  			}
   100  		}
   101  		if widget.showTagPrefix == "" || strings.HasPrefix(tag, widget.showTagPrefix) {
   102  			return true
   103  		}
   104  	}
   105  
   106  	return false
   107  }
   108  
   109  func (widget *Widget) RowColor(idx int, hidden int, checked bool) string {
   110  	if widget.View.HasFocus() && (idx == widget.Selected) {
   111  		foreground := widget.CommonSettings().Colors.RowTheme.HighlightedForeground
   112  		if checked {
   113  			foreground = widget.settings.Colors.CheckboxTheme.Checked
   114  		}
   115  		return fmt.Sprintf(
   116  			"%s:%s",
   117  			foreground,
   118  			widget.CommonSettings().Colors.RowTheme.HighlightedBackground,
   119  		)
   120  	}
   121  
   122  	if checked {
   123  		return widget.settings.Colors.CheckboxTheme.Checked
   124  	} else {
   125  		return widget.CommonSettings().RowColor(idx - hidden)
   126  	}
   127  }
   128  
   129  func (widget *Widget) formattedItemLine(idx int, hidden int, currItem *checklist.ChecklistItem) string {
   130  	rowColor := widget.RowColor(idx, hidden, currItem.Checked)
   131  
   132  	todoDate := currItem.Date
   133  	row := fmt.Sprintf(
   134  		` [%s]|%s| `,
   135  		rowColor,
   136  		currItem.CheckMark(),
   137  	)
   138  
   139  	if widget.settings.parseDates && todoDate != nil {
   140  		row += fmt.Sprintf(
   141  			`[%s]%s `,
   142  			widget.settings.dateColor,
   143  			widget.getDateString(todoDate),
   144  		)
   145  	}
   146  
   147  	tagsPart := ""
   148  	if len(currItem.Tags) > 0 {
   149  		tagsPart = fmt.Sprintf(
   150  			`[%s]%s[white]`,
   151  			widget.settings.tagColor,
   152  			currItem.TagString(),
   153  		)
   154  	}
   155  
   156  	textPart := fmt.Sprintf(
   157  		`[%s]%s[white]`,
   158  		rowColor,
   159  		tview.Escape(currItem.Text),
   160  	)
   161  
   162  	if widget.settings.parseTags && widget.settings.tagsAtEnd {
   163  		row += textPart + " " + tagsPart
   164  	} else if widget.settings.parseTags {
   165  		row += tagsPart + textPart
   166  	} else {
   167  		row += textPart
   168  	}
   169  
   170  	return utils.HighlightableHelper(widget.View, row, idx-hidden, len(currItem.Text))
   171  }
   172  
   173  func (widget *Widget) getDateString(date *time.Time) string {
   174  	now := getNowDate()
   175  	diff := int(date.Sub(now).Hours() / 24)
   176  	if diff == 0 {
   177  		return "today"
   178  	} else if diff == 1 {
   179  		return "tomorrow"
   180  	} else if diff <= widget.settings.switchToInDaysIn {
   181  		return fmt.Sprintf("in %d days", diff)
   182  	} else {
   183  		dateStr := ""
   184  		y, m, d := date.Year(), date.Month(), date.Day()
   185  		switch widget.settings.dateFormat {
   186  		case "yyyy-mm-dd":
   187  			dateStr = fmt.Sprintf("%d-%02d-%02d", y, m, d)
   188  		case "yy-mm-dd":
   189  			dateStr = fmt.Sprintf("%d-%02d-%02d", y-2000, m, d)
   190  		case "dd-mm-yyyy":
   191  			dateStr = fmt.Sprintf("%02d-%02d-%d", d, m, y)
   192  		case "dd-mm-yy":
   193  			dateStr = fmt.Sprintf("%02d-%02d-%d", d, m, y-2000)
   194  		case "dd M yyyy":
   195  			dateStr = fmt.Sprintf("%02d %s %d", d, date.Month().String()[:3], y)
   196  			// date
   197  		case "dd M yy":
   198  			dateStr = fmt.Sprintf("%02d %s %d", d, date.Month().String()[:3], y-2000)
   199  			// dateStr = "aaasdada"
   200  		default:
   201  			dateStr = fmt.Sprintf("%d-%02d-%02d", y, m, d)
   202  			// dateStr = fmt.Sprintf("%d-%02d-%02d", y, m, d)
   203  		}
   204  		if widget.settings.hideYearIfCurrent && date.Year() == now.Year() {
   205  			if widget.settings.dateFormat[:1] == "y" {
   206  				dateStr = dateStr[strings.Index(dateStr, "-")+1:]
   207  			} else if widget.settings.dateFormat[3:4] == "-" {
   208  				dateStr = dateStr[:5]
   209  			} else {
   210  				parts := strings.Split(dateStr, " ")
   211  				dateStr = parts[0] + " " + parts[1]
   212  			}
   213  		}
   214  		return dateStr
   215  	}
   216  }
   217  
   218  func getNowDate() time.Time {
   219  	now := time.Now()
   220  	now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Now().Location())
   221  	return now
   222  }