Enable motion with HJKL keys
This commit will enable the user of the program to navigate the dates within a given year, using vi-like keybindings. The movement between months should act intuitively across different sizes of the terminal.
This commit is contained in:
		
							parent
							
								
									394c8f9b9d
								
							
						
					
					
						commit
						ce66ae9f21
					
				
					 1 changed files with 120 additions and 2 deletions
				
			
		
							
								
								
									
										122
									
								
								Main.go
									
										
									
									
									
								
							
							
						
						
									
										122
									
								
								Main.go
									
										
									
									
									
								
							|  | @ -63,6 +63,14 @@ func date(year int, month time.Month, day int) time.Time { | |||
| 	return time.Date(year, month, day, 0, 0, 0, 0, time.Local) | ||||
| } | ||||
| 
 | ||||
| func lastDay(m time.Month) time.Time { | ||||
| 	return date(selTime.Year(), m+1, 0) | ||||
| } | ||||
| 
 | ||||
| func monthHeight(m time.Month) int { | ||||
| 	return (offset(m) + lastDay(m).Day() - 1) / 7 | ||||
| } | ||||
| 
 | ||||
| func centeredText(s string, x, y, width int, scr tcell.Screen, style tcell.Style) { | ||||
| 	start := x + max((width-utf8.RuneCountInString(s))/2, 0) | ||||
| 	i := 0 | ||||
|  | @ -93,6 +101,105 @@ func wrappedText(s string, scr tcell.Screen, style tcell.Style) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func bottomOfMonth(m time.Month, w time.Weekday) (time time.Time) { | ||||
| 	last := lastDay(m) | ||||
| 	day := last.Day() | ||||
| 
 | ||||
| 	if w > last.Weekday() { | ||||
| 		day -= 7 | ||||
| 	} | ||||
| 
 | ||||
| 	day += int(w - last.Weekday()) | ||||
| 
 | ||||
| 	time = date(selTime.Year(), m, day) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func topOfMonth(m time.Month, w time.Weekday) (time time.Time) { | ||||
| 	first := date(selTime.Year(), m, 1) | ||||
| 	day := 1 | ||||
| 
 | ||||
| 	if w < first.Weekday() { | ||||
| 		day += 7 | ||||
| 	} | ||||
| 
 | ||||
| 	day += int(w - first.Weekday()) | ||||
| 
 | ||||
| 	time = date(selTime.Year(), m, day) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func moveUp() { | ||||
| 	weekday := selTime.Weekday() | ||||
| 	newTime := selTime.AddDate(0, 0, -7) | ||||
| 	if newTime.Month() == selTime.Month() { | ||||
| 		selTime = newTime | ||||
| 	} else if int(selTime.Month()) > monthsWide { | ||||
| 		newMonth := selTime.Month() - time.Month(monthsWide) | ||||
| 		selTime = bottomOfMonth(newMonth, weekday) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func moveDown() { | ||||
| 	weekday := selTime.Weekday() | ||||
| 	newTime := selTime.AddDate(0, 0, +7) | ||||
| 	if newTime.Month() == selTime.Month() { | ||||
| 		selTime = newTime | ||||
| 	} else if int(selTime.Month()) <= (12-1)/monthsWide*monthsWide { | ||||
| 		newMonth := selTime.Month() + time.Month(monthsWide) | ||||
| 		selTime = topOfMonth(newMonth, weekday) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func offset(m time.Month) int { | ||||
| 	return (int(date(selTime.Year(), m, 1).Weekday()) + 6) % 7 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func rowInMonth(m time.Month, day int) int { | ||||
| 	return (day + offset(m) - 1) / 7 | ||||
| } | ||||
| 
 | ||||
| func leftmostInRow(m time.Month, row int) time.Time { | ||||
| 	if row == 0 { | ||||
| 		return date(selTime.Year(), m, 1) | ||||
| 	} | ||||
| 	if row > monthHeight(m) { | ||||
| 		row = monthHeight(m) | ||||
| 	} | ||||
| 
 | ||||
| 	day := row*7 + 1 - offset(m) | ||||
| 
 | ||||
| 	return date(selTime.Year(), m, day) | ||||
| } | ||||
| 
 | ||||
| func rightmostInRow(m time.Month, row int) time.Time { | ||||
| 	if row >= monthHeight(m) { | ||||
| 		return lastDay(m) | ||||
| 	} | ||||
| 
 | ||||
| 	day := row*7 + 7 - offset(m) | ||||
| 
 | ||||
| 	return date(selTime.Year(), m, day) | ||||
| } | ||||
| 
 | ||||
| func moveRight() { | ||||
| 	if selTime.Weekday() != time.Sunday && selTime.Day() != lastDay(selTime.Month()).Day() { | ||||
| 		selTime = selTime.AddDate(0, 0, 1) | ||||
| 	} else if int(selTime.Month())%monthsWide != 0 { | ||||
| 		selTime = leftmostInRow(selTime.Month()+1, rowInMonth(selTime.Month(), selTime.Day())) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func moveLeft() { | ||||
| 	if selTime.Weekday() != time.Monday && selTime.Day() != 1 { | ||||
| 		selTime = selTime.AddDate(0, 0, -1) | ||||
| 	} else if int(selTime.Month())%monthsWide != 1 && monthsWide != 1 { // special case, if monthsWide | ||||
| 		// is 1, (x%monthsWide) is 0 | ||||
| 		selTime = rightmostInRow(selTime.Month()-1, rowInMonth(selTime.Month(), selTime.Day())) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func drawMonth(m time.Month, x, y int) { | ||||
| 	centeredText(months[m], x, y, maxMonthWidth, wall, defStyle) | ||||
| 
 | ||||
|  | @ -181,13 +288,24 @@ func main() { | |||
| 		// Process event | ||||
| 		switch ev := ev.(type) { | ||||
| 		case *tcell.EventResize: | ||||
| 			drawWall() | ||||
| 			wall.Sync() | ||||
| 		case *tcell.EventKey: | ||||
| 			if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC || | ||||
| 				ev.Rune() == 'Q' || ev.Rune() == 'q' { | ||||
| 				quit() | ||||
| 			} | ||||
| 			switch ev.Rune() { | ||||
| 			case 'h': | ||||
| 				moveLeft() | ||||
| 			case 'j': | ||||
| 				moveDown() | ||||
| 			case 'k': | ||||
| 				moveUp() | ||||
| 			case 'l': | ||||
| 				moveRight() | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		drawWall() | ||||
| 		wall.Sync() | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Petar Kapriš
						Petar Kapriš