summaryrefslogtreecommitdiff
path: root/src/xpit_/list_.py
blob: fe281c2c25376f7738d9bb7938274d2389fc0289 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import os
from sys import argv, stdout, stderr
from . import args_helpers, issue, issue_tracker

DEFAULT_ORDER: list[bytes] = [b"ID", b"POST_COUNT", b"TITLE", b"status", b"labels"]

help_text = f"""\
Usage: xpit list [options]
Examples:
    xpit list -d , -f TITLE,POST_COUNT
Options:
    -d, --delimiter <str>
        Delimiter used to separate the fields.
        Defaults to '|' (pipe).
    -f, --fields <FIELD,...>
        Defaults to '{b','.join(DEFAULT_ORDER).decode("utf-8")}'.
        Guaranteed fields:
            ID - ID of the issue
            TITLE - Title of the issue
            AUTHOR - Author of the issue
            POST_COUNT - Total number of posts in the issue, including the initial post
            PATH_ABS - absolute path to issue.md file
            PATH_REL - relative path to issue.md file
        Other fields are optional and parsed in issues' INI headers.
        The fields are printed in order and the same field can be printed more than once.
    -h, --help
        Print this help text.
"""

class Args:
    def __init__(self) -> None:
        self.order = DEFAULT_ORDER
        self.delimiter = '|'

    def parse(self) -> bool:
        flag_value_map = {
            "help|h": 0,
            "delimiter|d": 1,
            "fields|f": 1,
        }
        res = args_helpers.parse_generic(flag_value_map, argv, 2)
        if res is None:
            return False
        if "help" in res:
            stdout.write(help_text)
            return False
        if "delimiter" in res:
            self.delimiter = res["delimiter"][0]
        if "fields" in res:
            self.order = [field.encode("utf-8") for field in res["fields"][0].split(',')]

        return True
args = Args()

def main() -> int:
    if len(argv) < 2:
        stdout.write(help_text)
        return 1

    if not args.parse():
        return 1

    cwd = os.getcwd()
    issue_tracker_dir = issue_tracker.find_dir(cwd)
    if issue_tracker_dir is None:
        return 1
    for file_name in os.listdir(issue_tracker_dir):
        if not os.path.isdir(os.path.join(issue_tracker_dir, file_name)):
            continue

        file_path = os.path.join(issue_tracker_dir, file_name, "issue.md")
        with open(file_path, "rb") as f:
            src = f.read()
        info, err = issue.parse(src)
        if err is not None:
            stderr.write(err.msg)
            return 1
        i = 0
        while True:
            key = args.order[i]
            if key == b"ID":
                stdout.write(file_name)
            elif key == b"TITLE":
                stdout.write(info.title.decode("utf-8"))
            elif key == b"POST_COUNT":
                stdout.write(str(info.post_count()))
            elif key == b"AUTHOR":
                stdout.write(info.meta[b"author"].decode("utf-8"))
            elif key == b"PATH_ABS":
                stdout.write(file_path)
            elif key == b"PATH_REL":
                stdout.write(os.path.relpath(file_path, start=cwd))
            else:
                if key in info.meta:
                    stdout.write(info.meta[key].decode("utf-8"))

            i += 1
            if i >= len(args.order):
                break
            stdout.write(args.delimiter)
        stdout.write('\n')

    return 0