WIP Support basic list options.
This commit is contained in:
		
							
								
								
									
										80
									
								
								src/pit.nim
									
									
									
									
									
								
							
							
						
						
									
										80
									
								
								src/pit.nim
									
									
									
									
									
								
							| @@ -13,6 +13,7 @@ type | |||||||
|     tasksDir*: string |     tasksDir*: string | ||||||
|     contexts*: TableRef[string, string] |     contexts*: TableRef[string, string] | ||||||
|     issues*: TableRef[IssueState, seq[Issue]] |     issues*: TableRef[IssueState, seq[Issue]] | ||||||
|  |     termWidth*: int | ||||||
|     cfg*: CombinedConfig |     cfg*: CombinedConfig | ||||||
|  |  | ||||||
| proc initContext(args: Table[string, Value]): CliContext = | proc initContext(args: Table[string, Value]): CliContext = | ||||||
| @@ -46,7 +47,8 @@ proc initContext(args: Table[string, Value]): CliContext = | |||||||
|     cfg: cfg, |     cfg: cfg, | ||||||
|     tasksDir: cfg.getVal("tasks-dir", ""), |     tasksDir: cfg.getVal("tasks-dir", ""), | ||||||
|     contexts: newTable[string,string](), |     contexts: newTable[string,string](), | ||||||
|     issues: newTable[IssueState, seq[Issue]]()) |     issues: newTable[IssueState, seq[Issue]](), | ||||||
|  |     termWidth: parseInt(cfg.getVal("term-width", "80"))) | ||||||
|  |  | ||||||
|   if cfgJson.hasKey("contexts"): |   if cfgJson.hasKey("contexts"): | ||||||
|     for k, v in cfgJson["contexts"]: |     for k, v in cfgJson["contexts"]: | ||||||
| @@ -75,7 +77,8 @@ proc formatIssue(ctx: CliContext, issue: Issue, state: IssueState, | |||||||
|  |  | ||||||
|   if state == Pending and issue.properties.hasKey("pending"): |   if state == Pending and issue.properties.hasKey("pending"): | ||||||
|     let startIdx = "Pending: ".len |     let startIdx = "Pending: ".len | ||||||
|     var pendingText = issue["pending"].wordWrap(width - startIdx - 2).indent(startIdx) |     var pendingText = issue["pending"].wordWrap(width - startIdx - 2) | ||||||
|  |                                       .indent(startIdx) | ||||||
|     pendingText = ("Pending: " & pendingText[startIdx..^1]).indent(indent.len + 2) |     pendingText = ("Pending: " & pendingText[startIdx..^1]).indent(indent.len + 2) | ||||||
|     lines.add(pendingText) |     lines.add(pendingText) | ||||||
|  |  | ||||||
| @@ -84,16 +87,15 @@ proc formatIssue(ctx: CliContext, issue: Issue, state: IssueState, | |||||||
|   return lines.join("\n") |   return lines.join("\n") | ||||||
|  |  | ||||||
| proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState, | proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState, | ||||||
|                    width = 80, indent = "  "): string = |                    indent = ""): string = | ||||||
|   let innerWidth = width - (indent.len * 2) |   let innerWidth = ctx.termWidth - (indent.len * 2) | ||||||
|   var lines: seq[string] = @[] |   var lines: seq[string] = @[] | ||||||
|  |  | ||||||
|   lines.add(indent & ".".repeat(innerWidth)) |   lines.add(indent & ".".repeat(innerWidth)) | ||||||
|   lines.add(state.displayName.center(width)) |   lines.add(state.displayName.center(ctx.termWidth)) | ||||||
|   lines.add("") |   lines.add("") | ||||||
|  |  | ||||||
|   var topPadded = true |   var topPadded = true | ||||||
|   var showDetails = false |  | ||||||
|  |  | ||||||
|   let issuesByContext = issues.groupBy("context") |   let issuesByContext = issues.groupBy("context") | ||||||
|  |  | ||||||
| @@ -116,16 +118,23 @@ proc formatSection(ctx: CliContext, issues: seq[Issue], state: IssueState, | |||||||
|   lines.add("") |   lines.add("") | ||||||
|   return lines.join("\n") |   return lines.join("\n") | ||||||
|  |  | ||||||
| proc loadIssues(ctx: CliContext, state: IssueState): seq[Issue] = | proc loadIssues(ctx: CliContext, state: IssueState) = | ||||||
|   result = loadIssues(joinPath(ctx.tasksDir, $state)) |   ctx.issues[state] = loadIssues(joinPath(ctx.tasksDir, $state)) | ||||||
|  |  | ||||||
| proc loadAllIssues(ctx: CliContext) = | proc loadAllIssues(ctx: CliContext) = | ||||||
|   for state in IssueState: |   for state in IssueState: ctx.loadIssues(state) | ||||||
|     ctx.issues[state] = loadIssues(ctx, state) |  | ||||||
|  |  | ||||||
| proc sameDay(a, b: DateTime): bool = | proc sameDay(a, b: DateTime): bool = | ||||||
|   result = a.year == b.year and a.yearday == b.yearday |   result = a.year == b.year and a.yearday == b.yearday | ||||||
|  |  | ||||||
|  | proc formatHeader(ctx: CliContext, header: string): string = | ||||||
|  |   var lines: seq[string] = @[] | ||||||
|  |   lines.add('_'.repeat(ctx.termWidth)) | ||||||
|  |   lines.add(header.center(ctx.termWidth)) | ||||||
|  |   lines.add('~'.repeat(ctx.termWidth)) | ||||||
|  |   lines.add("") | ||||||
|  |   return lines.join("\n") | ||||||
|  |  | ||||||
| when isMainModule: | when isMainModule: | ||||||
|  |  | ||||||
|  try: |  try: | ||||||
| @@ -146,9 +155,11 @@ Options: | |||||||
|   -C, --config <cfgFile>    Location of the config file (defaults to $HOME/.pitrc) |   -C, --config <cfgFile>    Location of the config file (defaults to $HOME/.pitrc) | ||||||
|   -h, --help                Print this usage information. |   -h, --help                Print this usage information. | ||||||
|   -T, --today               Limit to today's issues. |   -T, --today               Limit to today's issues. | ||||||
|  |   -F, --future              Limit to future issues. | ||||||
|   -E, --echo-args           Echo arguments (for debug purposes). |   -E, --echo-args           Echo arguments (for debug purposes). | ||||||
|   --tasks-dir               Path to the tasks directory (defaults to the value |   --tasks-dir               Path to the tasks directory (defaults to the value | ||||||
|                             configured in the .pitrc file) |                             configured in the .pitrc file) | ||||||
|  |   --term-width              Manually set the terminal width to use. | ||||||
| """ | """ | ||||||
|  |  | ||||||
|   logging.addHandler(newConsoleLogger()) |   logging.addHandler(newConsoleLogger()) | ||||||
| @@ -169,33 +180,40 @@ Options: | |||||||
|   ## Actual command runners |   ## Actual command runners | ||||||
|   if args["list"]: |   if args["list"]: | ||||||
|  |  | ||||||
|     ctx.loadAllIssues() |     # Specific state request | ||||||
|  |     if args["<state>"]: | ||||||
|  |       let state = parseEnum[IssueState]($args["<state>"]) | ||||||
|  |       ctx.loadIssues(state) | ||||||
|  |       echo ctx.formatSection(ctx.issues[state], state) | ||||||
|  |  | ||||||
|     let fullWidth = 80 |     else: | ||||||
|     let innerWidth = fullWidth - 4 |  | ||||||
|  |  | ||||||
|     # Today's items |       let showBoth = args["--today"] == args["--future"] | ||||||
|     echo '_'.repeat(fullWidth) |       let indent = if showBoth: "  " else: "" | ||||||
|     echo "Today".center(fullWidth) |       ctx.loadAllIssues() | ||||||
|     echo '~'.repeat(fullWidth) |  | ||||||
|     echo "" |  | ||||||
|  |  | ||||||
|     for s in [Current, TodoToday]: |       # Today's items | ||||||
|       echo ctx.formatSection(ctx.issues[s], s) |       if args["--today"] or showBoth: | ||||||
|  |         if showBoth: echo ctx.formatHeader("Today") | ||||||
|  |  | ||||||
|     echo ctx.formatSection( |         for s in [Current, TodoToday]: | ||||||
|       ctx.issues[Done].filterIt( |           if ctx.issues.hasKey(s) and ctx.issues[s].len > 0: | ||||||
|         it.properties.hasKey("completed") and |             echo ctx.formatSection(ctx.issues[s], s, indent) | ||||||
|         sameDay(now, it.getDateTime("completed"))), Done) |  | ||||||
|  |  | ||||||
|     # Future items |         if ctx.issues.hasKey(Done): | ||||||
|     echo '_'.repeat(fullWidth) |             let doneIssues = ctx.issues[Done].filterIt( | ||||||
|     echo "Future".center(fullWidth) |               it.properties.hasKey("completed") and | ||||||
|     echo '~'.repeat(fullWidth) |               sameDay(now, it.getDateTime("completed"))) | ||||||
|     echo "" |             if doneIssues.len > 0: | ||||||
|  |               echo ctx.formatSection(doneIssues, Done, indent) | ||||||
|  |  | ||||||
|     for s in [Pending, Todo]: |       # Future items | ||||||
|       echo ctx.formatSection(ctx.issues[s], s) |       if args["--future"] or showBoth: | ||||||
|  |         if showBoth: echo ctx.formatHeader("Future") | ||||||
|  |  | ||||||
|  |         for s in [Pending, Todo]: | ||||||
|  |           if ctx.issues.hasKey(s) and ctx.issues[s].len > 0: | ||||||
|  |             echo ctx.formatSection(ctx.issues[s], s, indent) | ||||||
|  |  | ||||||
|  except: |  except: | ||||||
|   fatal "pit: " & getCurrentExceptionMsg() |   fatal "pit: " & getCurrentExceptionMsg() | ||||||
|   | |||||||
| @@ -17,6 +17,8 @@ type | |||||||
|     Todo = "todo" |     Todo = "todo" | ||||||
|  |  | ||||||
| const ISO8601Format* = "yyyy:MM:dd'T'HH:mm:sszzz" | const ISO8601Format* = "yyyy:MM:dd'T'HH:mm:sszzz" | ||||||
|  | const DONE_FOLDER_FORMAT* = "yyyy-MM" | ||||||
|  |  | ||||||
| let ISSUE_FILE_PATTERN = re"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}\.txt" | let ISSUE_FILE_PATTERN = re"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}\.txt" | ||||||
|  |  | ||||||
| proc displayName*(s: IssueState): string = | proc displayName*(s: IssueState): string = | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user