Add color completer, bottom-toolbar
This commit is contained in:
parent
f299a13ba6
commit
1e2ff25411
|
@ -0,0 +1,34 @@
|
||||||
|
from jira import JIRA
|
||||||
|
from jql_pygments import load_config
|
||||||
|
|
||||||
|
config = load_config()
|
||||||
|
|
||||||
|
jira_server = config["server"]
|
||||||
|
jira_username = config["username"]
|
||||||
|
jira_password = config["token"]
|
||||||
|
|
||||||
|
jira = JIRA(server=jira_server, basic_auth=(jira_username, jira_password))
|
||||||
|
|
||||||
|
projects = [
|
||||||
|
'QUANTUM', 'NEBULA', 'GALACTIC', 'STELLAR', 'AETHER', 'NOVA', 'COSMIC', 'LUNAR', 'ASTRAL', 'PHOTON'
|
||||||
|
]
|
||||||
|
|
||||||
|
issue_type = 'Task'
|
||||||
|
summary_template = 'Issue {0} for project {1}'
|
||||||
|
description_template = 'Description for issue {0} in project {1}'
|
||||||
|
|
||||||
|
def create_issues(project_key, num_issues=20):
|
||||||
|
for i in range(1, num_issues + 1):
|
||||||
|
issue_dict = {
|
||||||
|
'project': {'key': project_key},
|
||||||
|
'summary': summary_template.format(i, project_key),
|
||||||
|
'description': description_template.format(i, project_key),
|
||||||
|
'issuetype': {'name': issue_type},
|
||||||
|
}
|
||||||
|
jira.create_issue(fields=issue_dict)
|
||||||
|
print(f'Created issue {i} in project {project_key}')
|
||||||
|
|
||||||
|
for project in projects:
|
||||||
|
create_issues(project)
|
||||||
|
|
||||||
|
print("Issue creation completed.")
|
|
@ -14,7 +14,7 @@ from pygments.token import (
|
||||||
from prompt_toolkit import PromptSession
|
from prompt_toolkit import PromptSession
|
||||||
from prompt_toolkit.lexers import PygmentsLexer
|
from prompt_toolkit.lexers import PygmentsLexer
|
||||||
from prompt_toolkit.styles import Style
|
from prompt_toolkit.styles import Style
|
||||||
from prompt_toolkit.completion import WordCompleter
|
from prompt_toolkit.completion import Completer, Completion
|
||||||
from prompt_toolkit.validation import Validator, ValidationError
|
from prompt_toolkit.validation import Validator, ValidationError
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.text import Text as RichText
|
from rich.text import Text as RichText
|
||||||
|
@ -52,6 +52,10 @@ class JQLLexer(RegexLexer):
|
||||||
),
|
),
|
||||||
(r"(?i)(=|!=|<|>|<=|>=|~|!~|IN|NOT IN|IS|IS NOT|WAS|WAS IN|WAS NOT IN|WAS NOT)", Operator),
|
(r"(?i)(=|!=|<|>|<=|>=|~|!~|IN|NOT IN|IS|IS NOT|WAS|WAS IN|WAS NOT IN|WAS NOT)", Operator),
|
||||||
(r"[\*\(/\^\.@;:+%#\[\|\?\),\$]", Punctuation),
|
(r"[\*\(/\^\.@;:+%#\[\|\?\),\$]", Punctuation),
|
||||||
|
(
|
||||||
|
r"(?i)\b(?:QUANTUM|NEBULA|GALACTIC|STELLAR|AETHER|NOVA|COSMIC|LUNAR|ASTRAL|PHOTON)\b",
|
||||||
|
Name.Other,
|
||||||
|
),
|
||||||
(r"[\w\.\-]+", Text),
|
(r"[\w\.\-]+", Text),
|
||||||
],
|
],
|
||||||
"string": [
|
"string": [
|
||||||
|
@ -72,6 +76,8 @@ nord_style = Style.from_dict(
|
||||||
"pygments.name.function": "#A3BE8C",
|
"pygments.name.function": "#A3BE8C",
|
||||||
"pygments.literal.string": "#D08770",
|
"pygments.literal.string": "#D08770",
|
||||||
"pygments.text": "#D8DEE9",
|
"pygments.text": "#D8DEE9",
|
||||||
|
"pygments.name.other": "#D08770",
|
||||||
|
"pygments.error": "#BF616A bold",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,37 +92,21 @@ token_styles = {
|
||||||
String: "#D08770",
|
String: "#D08770",
|
||||||
Text: "#D8DEE9",
|
Text: "#D8DEE9",
|
||||||
Error: "#BF616A bold",
|
Error: "#BF616A bold",
|
||||||
|
Name.Other: "#D08770",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
completions = [
|
completion_styles = {
|
||||||
"assignee",
|
"Keywords": "#81A1C1 bold",
|
||||||
"affectedVersion",
|
"Functions": "#A3BE8C",
|
||||||
"attachments",
|
"Attributes": "#B48EAD",
|
||||||
"comment",
|
"Operators": "#EBCB8B bold",
|
||||||
"component",
|
"Projects": "#D08770",
|
||||||
"created",
|
}
|
||||||
"creator",
|
|
||||||
"description",
|
|
||||||
"due",
|
completions = {
|
||||||
"duedate",
|
"Keywords": [
|
||||||
"filter",
|
|
||||||
"fixVersion",
|
|
||||||
"issuekey",
|
|
||||||
"labels",
|
|
||||||
"lastViewed",
|
|
||||||
"priority",
|
|
||||||
"project",
|
|
||||||
"reporter",
|
|
||||||
"resolved",
|
|
||||||
"sprint",
|
|
||||||
"status",
|
|
||||||
"statusCategory",
|
|
||||||
"summary",
|
|
||||||
"text",
|
|
||||||
"timespent",
|
|
||||||
"voter",
|
|
||||||
"watcher",
|
|
||||||
"A",
|
"A",
|
||||||
"AND",
|
"AND",
|
||||||
"ARE",
|
"ARE",
|
||||||
|
@ -148,7 +138,10 @@ completions = [
|
||||||
"TO",
|
"TO",
|
||||||
"WILL",
|
"WILL",
|
||||||
"WITH",
|
"WITH",
|
||||||
|
],
|
||||||
|
"Functions": [
|
||||||
"issueHistory",
|
"issueHistory",
|
||||||
|
"openSprints",
|
||||||
"watchedIssues",
|
"watchedIssues",
|
||||||
"myApproval",
|
"myApproval",
|
||||||
"myPending",
|
"myPending",
|
||||||
|
@ -165,7 +158,67 @@ completions = [
|
||||||
"endOfMonth",
|
"endOfMonth",
|
||||||
"startOfYear",
|
"startOfYear",
|
||||||
"endOfYear",
|
"endOfYear",
|
||||||
]
|
],
|
||||||
|
"Attributes": [
|
||||||
|
"assignee",
|
||||||
|
"affectedVersion",
|
||||||
|
"attachments",
|
||||||
|
"comment",
|
||||||
|
"component",
|
||||||
|
"created",
|
||||||
|
"creator",
|
||||||
|
"description",
|
||||||
|
"due",
|
||||||
|
"duedate",
|
||||||
|
"filter",
|
||||||
|
"fixVersion",
|
||||||
|
"issuekey",
|
||||||
|
"labels",
|
||||||
|
"lastViewed",
|
||||||
|
"priority",
|
||||||
|
"project",
|
||||||
|
"reporter",
|
||||||
|
"resolved",
|
||||||
|
"sprint",
|
||||||
|
"status",
|
||||||
|
"statusCategory",
|
||||||
|
"summary",
|
||||||
|
"text",
|
||||||
|
"timespent",
|
||||||
|
"voter",
|
||||||
|
"watcher",
|
||||||
|
],
|
||||||
|
"Operators": [
|
||||||
|
"=",
|
||||||
|
"!=",
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"<=",
|
||||||
|
">=",
|
||||||
|
"~",
|
||||||
|
"!~",
|
||||||
|
"IN",
|
||||||
|
"NOT IN",
|
||||||
|
"IS",
|
||||||
|
"IS NOT",
|
||||||
|
"WAS",
|
||||||
|
"WAS IN",
|
||||||
|
"WAS NOT IN",
|
||||||
|
"WAS NOT",
|
||||||
|
],
|
||||||
|
"Projects": [
|
||||||
|
"QUANTUM",
|
||||||
|
"NEBULA",
|
||||||
|
"GALACTIC",
|
||||||
|
"STELLAR",
|
||||||
|
"AETHER",
|
||||||
|
"NOVA",
|
||||||
|
"COSMIC",
|
||||||
|
"LUNAR",
|
||||||
|
"ASTRAL",
|
||||||
|
"PHOTON",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class JQLPrinter:
|
class JQLPrinter:
|
||||||
|
@ -173,7 +226,7 @@ class JQLPrinter:
|
||||||
self.console = console
|
self.console = console
|
||||||
|
|
||||||
def print(self, text: str):
|
def print(self, text: str):
|
||||||
self.console.print(self.pygments_to_rich(text))
|
self.console.print(self.pygments_to_rich(text), end="")
|
||||||
|
|
||||||
def pygments_to_rich(self, text):
|
def pygments_to_rich(self, text):
|
||||||
tokens = list(JQLLexer().get_tokens(text))
|
tokens = list(JQLLexer().get_tokens(text))
|
||||||
|
@ -199,24 +252,67 @@ class JQLValidator(Validator):
|
||||||
raise ValidationError(message=f"[!] {error_text}", cursor_position=len(text))
|
raise ValidationError(message=f"[!] {error_text}", cursor_position=len(text))
|
||||||
|
|
||||||
|
|
||||||
def create_jira_prompt_session(jira):
|
class JQLCompleter(Completer):
|
||||||
completer = WordCompleter(completions, ignore_case=True)
|
"""Custom JQL completer to categorize and color completions."""
|
||||||
|
|
||||||
|
def __init__(self, categorized_completions):
|
||||||
|
self.categorized_completions = categorized_completions
|
||||||
|
|
||||||
|
def get_completions(self, document, complete_event):
|
||||||
|
text = document.get_word_before_cursor().lower()
|
||||||
|
for category, words in self.categorized_completions.items():
|
||||||
|
for word in words:
|
||||||
|
if text in word.lower():
|
||||||
|
display_text = f"{word}"
|
||||||
|
yield Completion(
|
||||||
|
word,
|
||||||
|
start_position=-len(text),
|
||||||
|
display=display_text,
|
||||||
|
display_meta=category,
|
||||||
|
style=f"fg: #D8DEE9 bg: {completion_styles.get(category, 'white')}",
|
||||||
|
selected_style=f"fg: {completion_styles.get(category, 'white')} bg: #D8DEE9",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
query_count = 0
|
||||||
|
|
||||||
|
|
||||||
|
def get_query_count():
|
||||||
|
return [("class:bottom-toolbar", f"Query count: {query_count}")]
|
||||||
|
|
||||||
|
|
||||||
|
def create_jql_prompt_session(jira):
|
||||||
|
completer = JQLCompleter(completions)
|
||||||
return PromptSession(
|
return PromptSession(
|
||||||
lexer=PygmentsLexer(JQLLexer),
|
lexer=PygmentsLexer(JQLLexer),
|
||||||
style=nord_style,
|
style=nord_style,
|
||||||
completer=completer,
|
completer=completer,
|
||||||
validator=JQLValidator(jira),
|
validator=JQLValidator(jira),
|
||||||
rprompt="[b] Back [exit] Exit",
|
rprompt="[b] Back [exit] Exit",
|
||||||
|
bottom_toolbar=get_query_count,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def load_config():
|
||||||
with open("config.json") as json_file:
|
with open("config.json") as json_file:
|
||||||
config = json.load(json_file)
|
try:
|
||||||
|
with open("config.json") as json_file:
|
||||||
|
return json.load(json_file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("Configuration file not found.")
|
||||||
|
exit(1)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print("Error decoding configuration file.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
global query_count
|
||||||
|
config = load_config()
|
||||||
console = Console(color_system="truecolor")
|
console = Console(color_system="truecolor")
|
||||||
jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"]))
|
jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"]))
|
||||||
jql = JQLPrinter(console)
|
jql = JQLPrinter(console)
|
||||||
session = create_jira_prompt_session(jira)
|
session = create_jql_prompt_session(jira)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
user_input = session.prompt("Enter JQL: ", validate_while_typing=False)
|
user_input = session.prompt("Enter JQL: ", validate_while_typing=False)
|
||||||
|
@ -224,7 +320,19 @@ def main():
|
||||||
continue
|
continue
|
||||||
if user_input.lower() == "exit":
|
if user_input.lower() == "exit":
|
||||||
break
|
break
|
||||||
jql.print(user_input)
|
issues = jira.search_issues(user_input)
|
||||||
|
if issues:
|
||||||
|
query_count += 1
|
||||||
|
console.print(
|
||||||
|
RichText.assemble(
|
||||||
|
(f"[+] Found {len(issues)} issues from JQL query: ", "green bold"),
|
||||||
|
jql.pygments_to_rich(user_input),
|
||||||
|
),
|
||||||
|
end="",
|
||||||
|
)
|
||||||
|
for issue in issues:
|
||||||
|
console.print(f"{issue.key}: {issue.fields.summary}")
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
continue
|
continue
|
||||||
except EOFError:
|
except EOFError:
|
||||||
|
|
Loading…
Reference in New Issue