Add filters for text-matching on issue summary or details.
This commit is contained in:
parent
2404f6a3d1
commit
a924d7b649
24
src/pit.nim
24
src/pit.nim
@ -4,6 +4,7 @@
|
||||
import cliutils, docopt, json, logging, options, os, ospaths, sequtils,
|
||||
tables, terminal, times, timeutils, unicode, uuids
|
||||
|
||||
from nre import re
|
||||
import strutils except capitalize, toUpper, toLower
|
||||
import pitpkg/private/libpit
|
||||
export libpit
|
||||
@ -182,7 +183,7 @@ proc edit(issue: Issue) =
|
||||
getCurrentExceptionMsg()
|
||||
issue.store()
|
||||
|
||||
proc list(ctx: CliContext, filter: Option[IssueFilter], state: Option[IssueState], today, future, verbose: bool) =
|
||||
proc list(ctx: CliContext, filter: Option[IssueFilter], state: Option[IssueState], showToday, showFuture, verbose: bool) =
|
||||
|
||||
if state.isSome:
|
||||
ctx.loadIssues(state.get)
|
||||
@ -193,6 +194,12 @@ proc list(ctx: CliContext, filter: Option[IssueFilter], state: Option[IssueState
|
||||
ctx.loadAllIssues()
|
||||
if filter.isSome: ctx.filterIssues(filter.get)
|
||||
|
||||
let today = showToday and [Current, TodoToday].anyIt(
|
||||
ctx.issues.hasKey(it) and ctx.issues[it].len > 0)
|
||||
|
||||
let future = showFuture and [Pending, Todo].anyIt(
|
||||
ctx.issues.hasKey(it) and ctx.issues[it].len > 0)
|
||||
|
||||
let indent = if today and future: " " else: ""
|
||||
|
||||
# Today's items
|
||||
@ -246,6 +253,12 @@ Options:
|
||||
|
||||
-F, --future Limit to future issues.
|
||||
|
||||
-m, --match <pattern> Limit to issues whose summaries match the given
|
||||
pattern (PCRE regex supported).
|
||||
|
||||
-M, --match-all <pat> Limit to the issues whose summaries or details
|
||||
match the given pattern (PCRE regex supported).
|
||||
|
||||
-v, --verbose Show issue details when listing issues.
|
||||
|
||||
-q, --quiet Suppress verbose output.
|
||||
@ -380,6 +393,15 @@ Options:
|
||||
filter.properties = propertiesOption.get
|
||||
filterOption = some(filter)
|
||||
|
||||
# If they supplied text matches, add that to the filter.
|
||||
if args["--match"]:
|
||||
filter.summaryMatch = some(re("(?i)" & $args["--match"]))
|
||||
filterOption = some(filter)
|
||||
|
||||
if args["--match-all"]:
|
||||
filter.fullMatch = some(re("(?i)" & $args["--match-all"]))
|
||||
filterOption = some(filter)
|
||||
|
||||
# If no "context" property is given, use the default (if we have one)
|
||||
if ctx.defaultContext.isSome and not filter.properties.hasKey("context"):
|
||||
stderr.writeLine("Limiting to default context: " & ctx.defaultContext.get)
|
||||
|
@ -1,7 +1,8 @@
|
||||
import cliutils, docopt, json, logging, options, os, ospaths, sequtils,
|
||||
strutils, tables, times, timeutils, uuids
|
||||
|
||||
from nre import re, match
|
||||
from nre import find, match, re, Regex
|
||||
|
||||
type
|
||||
Issue* = ref object
|
||||
id*: UUID
|
||||
@ -19,8 +20,9 @@ type
|
||||
Dormant = "dormant"
|
||||
|
||||
IssueFilter* = ref object
|
||||
completedRange*: Option[tuple[b, e: DateTime]]
|
||||
fullMatch*, summaryMatch*: Option[Regex]
|
||||
properties*: TableRef[string, string]
|
||||
completedRange*: tuple[b, e: DateTime]
|
||||
|
||||
PitConfig* = ref object
|
||||
tasksDir*: string
|
||||
@ -62,22 +64,30 @@ proc setDateTime*(issue: Issue, key: string, dt: DateTime) =
|
||||
|
||||
proc initFilter*(): IssueFilter =
|
||||
result = IssueFilter(
|
||||
properties: newTable[string,string](),
|
||||
completedRange: (fromUnix(0).local, fromUnix(253400659199).local))
|
||||
completedRange: none(tuple[b, e: DateTime]),
|
||||
fullMatch: none(Regex),
|
||||
summaryMatch: none(Regex),
|
||||
properties: newTable[string, string]())
|
||||
|
||||
proc initFilter*(props: TableRef[string, string]): IssueFilter =
|
||||
proc propsFilter*(props: TableRef[string, string]): IssueFilter =
|
||||
if isNil(props):
|
||||
raise newException(ValueError,
|
||||
"cannot initialize property filter without properties")
|
||||
|
||||
result = IssueFilter(
|
||||
properties: props,
|
||||
completedRange: (fromUnix(0).local, fromUnix(253400659199).local))
|
||||
result = initFilter()
|
||||
result.properties = props
|
||||
|
||||
proc initFilter*(range: tuple[b, e: DateTime]): IssueFilter =
|
||||
result = IssueFilter(
|
||||
properties: newTable[string, string](),
|
||||
completedRange: range)
|
||||
proc dateFilter*(range: tuple[b, e: DateTime]): IssueFilter =
|
||||
result = initFilter()
|
||||
result.completedRange = some(range)
|
||||
|
||||
proc summaryMatchFilter*(pattern: string): IssueFilter =
|
||||
result = initFilter()
|
||||
result.summaryMatch = some(re("(?i)" & pattern))
|
||||
|
||||
proc fullMatchFilter*(pattern: string): IssueFilter =
|
||||
result = initFilter()
|
||||
result.fullMatch = some(re("(?i)" & pattern))
|
||||
|
||||
## Parse and format issues
|
||||
proc fromStorageFormat*(id: string, issueTxt: string): Issue =
|
||||
@ -190,10 +200,19 @@ proc filter*(issues: seq[Issue], filter: IssueFilter): seq[Issue] =
|
||||
for k,v in filter.properties:
|
||||
result = result.filterIt(it.hasProp(k) and it[k] == v)
|
||||
|
||||
result = result.filterIt(not it.hasProp("completed") or
|
||||
it.getDateTime("completed").between(
|
||||
filter.completedRange.b,
|
||||
filter.completedRange.e))
|
||||
if filter.completedRange.isSome:
|
||||
let range = filter.completedRange.get
|
||||
result = result.filterIt(
|
||||
not it.hasProp("completed") or
|
||||
it.getDateTime("completed").between(range.b, range.e))
|
||||
|
||||
if filter.summaryMatch.isSome:
|
||||
let p = filter.summaryMatch.get
|
||||
result = result.filterIt(it.summary.find(p).isSome)
|
||||
|
||||
if filter.fullMatch.isSome:
|
||||
let p = filter.fullMatch.get
|
||||
result = result.filterIt( it.summary.find(p).isSome or it.details.find(p).isSome)
|
||||
|
||||
### Configuration utilities
|
||||
proc loadConfig*(args: Table[string, Value] = initTable[string, Value]()): PitConfig =
|
||||
|
Loading…
x
Reference in New Issue
Block a user