Compare commits

...

1 Commits

Author SHA1 Message Date
89c924bb72 Only emit ANSI escape codes when stdout is a TTY. 2025-12-01 18:07:03 -06:00
4 changed files with 50 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
# Package
version = "4.31.1"
version = "4.31.2"
author = "Jonathan Bernard"
description = "Personal issue tracker."
license = "MIT"

View File

@@ -1,4 +1,4 @@
const PIT_VERSION* = "4.31.1"
const PIT_VERSION* = "4.31.2"
const USAGE* = """Usage:
pit ( new | add) <summary> [<state>] [options]
@@ -247,4 +247,4 @@ Issue Properties:
If present, expected to be a comma-delimited list of text tags. The -g
option is a short-hand for '-p tags:<tags-value>'.
"""
"""

View File

@@ -1,4 +1,4 @@
import std/[json, jsonutils, logging, options, os, strformat, strutils, tables, times,
import std/[json, logging, options, os, strformat, strutils, tables, times,
unicode]
import cliutils, docopt, langutils, uuids, zero_functional

View File

@@ -1,12 +1,12 @@
import std/[algorithm, json, jsonutils, options, os, sets, strutils, tables,
terminal, times, unicode, wordwrap]
terminal, times, unicode]
from std/sequtils import repeat, toSeq
import cliutils, uuids, zero_functional
import ./[formatting, libpit]
const NO_PROJECT* = "<no-project>"
const NO_MILESTONE* = "<no-project>"
const NO_CONTEXT* = "<no-project>"
const NO_PROJECT* = "∅ No Project"
const NO_MILESTONE* = "∅ No Milestone"
const NO_CONTEXT* = "<no-context>"
type
ProjectCfg* = ref object of RootObj
@@ -129,6 +129,8 @@ proc listProjects*(ctx: CliContext, filter = none[IssueFilter]()) =
let projectsCfg = ctx.loadProjectsConfiguration()
var projectsCfgChanged = false
var linesToPrint = newSeq[string]()
if filter.isSome: ctx.filterIssues(filter.get)
let projectsByContext = newTable[string, CountTableRef[string]]()
@@ -150,10 +152,10 @@ proc listProjects*(ctx: CliContext, filter = none[IssueFilter]()) =
for (context, projects) in pairs(projectsByContext):
stdout.writeLine(withColor(
linesToPrint.add(withColor(
ctx.getIssueContextDisplayName(context) & ":",
fgYellow) & termReset)
stdout.writeLine("")
linesToPrint.add("")
var toList = toHashSet(toSeq(keys(projects)))
@@ -164,22 +166,29 @@ proc listProjects*(ctx: CliContext, filter = none[IssueFilter]()) =
for project in projectsCfg[context]:
if project.name in toList:
toList.excl(project.name)
stdout.writeLine(" " & project.name &
linesToPrint.add(" " & project.name &
" (" & $projects[project.name] & " issues)")
# Then list any remaining projects not in the configuration, and add them
# to the configuration
for (projectName, count) in pairs(projects):
if projectName in toList:
stdout.writeLine(" " & projectName & " (" & $count & " issues)")
linesToPrint.add(" " & projectName & " (" & $count & " issues)")
projectsCfg[context].add(ProjectCfg(name: projectName, milestoneOrder: @[]))
projectsCfgChanged = true
stdout.writeLine("")
linesToPrint.add("")
if projectsCfgChanged: ctx.saveProjectsConfiguration(projectsCfg)
if isatty(stdout):
stdout.writeLine(linesToPrint.join("\p"))
else:
stdout.writeLine(stripAnsi(linesToPrint.join("\p")))
proc listMilestones*(ctx: CliContext, filter = none[IssueFilter]()) =
var linesToPrint = newSeq[string]()
ctx.loadAllIssues()
if filter.isSome: ctx.filterIssues(filter.get)
@@ -194,8 +203,8 @@ proc listMilestones*(ctx: CliContext, filter = none[IssueFilter]()) =
if values(project.milestones) --> all(it.len == 0):
continue
stdout.writeLine(withColor(project.name, fgBlue, bold = true, bright=true))
stdout.writeLine(withColor(
linesToPrint.add(withColor(project.name, fgBlue, bold = true, bright=true))
linesToPrint.add(withColor(
"".repeat(runeLen(stripAnsi(project.name))),
fgBlue, bold = true))
@@ -203,9 +212,15 @@ proc listMilestones*(ctx: CliContext, filter = none[IssueFilter]()) =
if project.milestones.hasKey(milestone) and
project.milestones[milestone].len > 0:
let issueCount = project.milestones[milestone].len
stdout.writeLine(" " & milestone & " (" & $issueCount & " issues)")
linesToPrint.add(" " & milestone & " (" & $issueCount & " issues)")
linesToPrint.add("")
if isatty(stdout):
stdout.writeLine(linesToPrint.join("\p"))
else:
stdout.writeLine(stripAnsi(linesToPrint.join("\p")))
stdout.writeLine("")
proc formatProjectIssue(
ctx: CliContext,
@@ -306,22 +321,23 @@ proc joinColumns(columns: seq[seq[string]], columnWidth: int): seq[string] =
proc showProject*(ctx: CliContext, project: Project) =
var linesToPrint = newSeq[string]()
let fullWidth = terminalWidth() - 1
let columnWidth = 80
let numColumns = (fullWidth - 4) div (columnWidth + 2)
stdout.writeLine("")
stdout.writeLine(withColor(
"" & "".repeat(project.name.len + 2) &
"" & "".repeat(fullWidth - project.name.len - 4) & "",
linesToPrint.add("")
linesToPrint.add(withColor(
"" & "".repeat(project.name.runeLen + 2) &
"" & "".repeat(fullWidth - project.name.runeLen - 4) & "",
fgBlue, bold=true))
stdout.writeLine(
linesToPrint.add(
withColor("", fgBlue, bold=true) &
withColor(project.name, fgBlue, bold=true, bright=true) &
withColor("" & " ".repeat(fullWidth - project.name.len - 4) & "", fgBlue, bold=true))
stdout.writeLine(withColor(
"" & "".repeat(project.name.len + 2) &
"" & " ".repeat(fullWidth - project.name.len - 4) & "",
withColor("" & " ".repeat(fullWidth - project.name.runeLen - 4) & "", fgBlue, bold=true))
linesToPrint.add(withColor(
"" & "".repeat(project.name.runeLen + 2) &
"" & " ".repeat(fullWidth - project.name.runeLen - 4) & "",
fgBlue, bold=true))
let milestoneTexts: seq[seq[string]] = project.milestoneOrder -->
@@ -338,16 +354,22 @@ proc showProject*(ctx: CliContext, project: Project) =
for line in joinedLines:
let padLen = fullWidth - runeLen(stripAnsi(line)) - 3
stdout.writeLine(
linesToPrint.add(
withColor("", fgBlue) &
line &
" ".repeat(padLen) &
withColor("", fgBlue))
stdout.writeLine(withColor(
linesToPrint.add(withColor(
"" & "".repeat(terminalWidth() - 2) & "",
fgBlue, bold=true))
if isatty(stdout):
stdout.writeLine(linesToPrint.join("\p"))
else:
stdout.writeLine(stripAnsi(linesToPrint.join("\p")))
proc showProjectBoard*(ctx: CliContext, filter = none[IssueFilter]()) =
ctx.loadAllIssues()