Compare commits
2 Commits
50e0eb839e
...
6c50bd267e
Author | SHA1 | Date |
---|---|---|
Roland Thomas Jr | 6c50bd267e | |
Roland Thomas Jr | 7b872484e9 |
|
@ -0,0 +1,21 @@
|
|||
from jira import JIRA
|
||||
from rich.console import Console
|
||||
|
||||
from jql_utils import JQLPrompt, load_config
|
||||
|
||||
config = load_config()
|
||||
console = Console(color_system="truecolor")
|
||||
jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"]))
|
||||
jql_prompt = JQLPrompt(jira)
|
||||
|
||||
issues = jql_prompt.prompt()
|
||||
|
||||
console.print("[ℹ] Getting more issues... 🚀", style="#A3BE8C bold")
|
||||
|
||||
more_issues = jql_prompt.multi_prompt()
|
||||
|
||||
if issues or more_issues:
|
||||
console.print("[ℹ] Saving logs... 🚀", style="#A3BE8C bold")
|
||||
jql_prompt.save_log()
|
||||
|
||||
console.print("Exiting... 🚀", style="bold green")
|
|
@ -1,70 +0,0 @@
|
|||
from prompt_toolkit.lexers import Lexer
|
||||
from prompt_toolkit.styles import Style
|
||||
from prompt_toolkit.document import Document
|
||||
from prompt_toolkit.formatted_text import StyleAndTextTuples
|
||||
from typing import Callable
|
||||
|
||||
class JQLLexer(Lexer):
|
||||
def lex_document(self, document: Document) -> Callable[[int], StyleAndTextTuples]:
|
||||
text = document.text
|
||||
tokens = []
|
||||
|
||||
keywords = {
|
||||
"AND", "OR", "NOT", "IN", "ORDER BY", "ASC", "DESC",
|
||||
"IS", "NULL", "TRUE", "FALSE", "EMPTY"
|
||||
}
|
||||
operators = {
|
||||
"=", "!", ">", "<", ">=", "<=", "~", "!~", "!="
|
||||
}
|
||||
punctuations = {"(", ")", ",", ":", " "}
|
||||
|
||||
pos = 0
|
||||
word = ''
|
||||
|
||||
while pos < len(text):
|
||||
char = text[pos]
|
||||
|
||||
if char.isalpha():
|
||||
word += char
|
||||
else:
|
||||
if word:
|
||||
if word.upper() in keywords:
|
||||
tokens.append(('class:keyword', word))
|
||||
else:
|
||||
tokens.append(('class:name', word))
|
||||
word = ''
|
||||
|
||||
if char in operators:
|
||||
tokens.append(('class:operator', char))
|
||||
elif char in punctuations:
|
||||
tokens.append(('class:punctuation', char))
|
||||
elif char.isspace():
|
||||
tokens.append(('class:text', char))
|
||||
else:
|
||||
tokens.append(('class:error', char))
|
||||
pos += 1
|
||||
|
||||
if word:
|
||||
if word.upper() in keywords:
|
||||
tokens.append(('class:keyword', word))
|
||||
else:
|
||||
tokens.append(('class:name', word))
|
||||
|
||||
return lambda i: tokens
|
||||
|
||||
# Example usage
|
||||
from prompt_toolkit import PromptSession
|
||||
|
||||
custom_style = Style.from_dict({
|
||||
'keyword': '#ff0066 bold',
|
||||
'operator': '#00ff00',
|
||||
'name': '#0000ff',
|
||||
'punctuation': '#00ffff',
|
||||
'text': '#ffffff',
|
||||
'error': '#ff0000 bold',
|
||||
})
|
||||
|
||||
session = PromptSession(lexer=JQLLexer(), style=custom_style)
|
||||
|
||||
text = session.prompt('Enter JQL: ')
|
||||
print(f'You entered: {text}')
|
|
@ -1,17 +1,19 @@
|
|||
import json
|
||||
from typing import Dict, List
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from jira import JIRA
|
||||
from jira.exceptions import JIRAError
|
||||
from jira.resources import Issue
|
||||
from prompt_toolkit import PromptSession
|
||||
from prompt_toolkit.completion import Completer, Completion
|
||||
from prompt_toolkit.lexers import PygmentsLexer
|
||||
from prompt_toolkit.shortcuts import confirm
|
||||
from prompt_toolkit.styles import Style
|
||||
from prompt_toolkit.validation import ValidationError, Validator
|
||||
from prompt_toolkit.shortcuts import confirm
|
||||
from pygments.lexer import RegexLexer
|
||||
from pygments.token import Error, Keyword, Name, Operator, Punctuation, String, Text, Whitespace, _TokenType
|
||||
|
||||
from pygments.token import (Error, Keyword, Name, Operator, Punctuation,
|
||||
String, Text, Whitespace, _TokenType)
|
||||
from rich.console import Console
|
||||
from rich.text import Text as RichText
|
||||
|
||||
|
@ -38,10 +40,10 @@ class JQLLexer(RegexLexer):
|
|||
Keyword,
|
||||
),
|
||||
(
|
||||
r"(?i)\b(?:Assignee|affectedVersion|Attachments|Category|Comment|Component|Created|createdDate|"
|
||||
r"Creator|Description|Due|duedate|Filter|fixVersion|issuekey|issuetype|issueLinkType|Labels|"
|
||||
r"lastViewed|Priority|Project|Reporter|Resolved|Sprint|Status|statusCategory|Summary|Text|"
|
||||
r"timespent|Voter|Watcher)\b",
|
||||
r"(?i)\b(?:assignee|affectedVersion|attachments|category|comment|component|created|createdDate|"
|
||||
r"creator|cescription|due|duedate|filter|fixVersion|issuekey|issuetype|issueLinkType|labels|"
|
||||
r"lastViewed|priority|project|reporter|resolved|Sprint|status|statusCategory|summary|text|"
|
||||
r"timespent|updated|updatedDate|voter|watcher|watchers)\b",
|
||||
Name.Attribute,
|
||||
),
|
||||
(r"(?i)(=|!=|<|>|<=|>=|~|!~|IN|NOT IN|IS|IS NOT|WAS|WAS IN|WAS NOT IN|WAS NOT)", Operator),
|
||||
|
@ -178,6 +180,7 @@ completions: Dict[str, List[str]] = {
|
|||
"summary",
|
||||
"text",
|
||||
"timespent",
|
||||
"updated",
|
||||
"voter",
|
||||
"watcher",
|
||||
],
|
||||
|
@ -281,21 +284,26 @@ def load_config():
|
|||
|
||||
|
||||
class JQLPrompt:
|
||||
def __init__(self, jira, console):
|
||||
self.jira = jira
|
||||
self.console = console
|
||||
self.session = self.create_jql_prompt_session()
|
||||
self.jql = JQLPrinter(console)
|
||||
self.query_count = 0
|
||||
def __init__(self, jira):
|
||||
self.jira: JIRA = jira
|
||||
self.console: Console = Console(color_system="truecolor", record=True)
|
||||
self.session: PromptSession = self.create_jql_prompt_session()
|
||||
self.jql: JQLPrinter = JQLPrinter(self.console)
|
||||
self.query_count: int = 0
|
||||
self.issue_count: int = 0
|
||||
self.total_issue_count: int = 0
|
||||
self.issues: List[Issue] = []
|
||||
|
||||
def get_query_count(self):
|
||||
space = self.console.width // 4
|
||||
query_count_str = f"Query count: {self.query_count}"
|
||||
plain_text = f"{query_count_str:^{space}}{query_count_str:^{space}}{query_count_str:^{space}}{query_count_str:^{space}}"
|
||||
space = self.console.width // 3
|
||||
query_count_str = f"Query Count: {self.query_count}" if self.query_count else ""
|
||||
issue_count_str = f"Issues Added: {self.issue_count}" if self.issue_count else ""
|
||||
total_issue_count_str = f"Total Issues: {self.total_issue_count}" if self.total_issue_count else ""
|
||||
plain_text = f"{query_count_str:^{space}}{issue_count_str:^{space}}{total_issue_count_str:^{space}}"
|
||||
return [("bg:#2E3440 #D8DEE9", plain_text)]
|
||||
|
||||
def create_jql_prompt_session(self):
|
||||
completer = JQLCompleter(completions)
|
||||
completer: JQLCompleter = JQLCompleter(completions)
|
||||
return PromptSession(
|
||||
message=[("#B48EAD", "JQL \u276f ")],
|
||||
lexer=PygmentsLexer(JQLLexer),
|
||||
|
@ -310,8 +318,9 @@ class JQLPrompt:
|
|||
validate_while_typing=False,
|
||||
)
|
||||
|
||||
def get_input(self):
|
||||
user_input = self.session.prompt()
|
||||
def prompt(self) -> Optional[List[Issue]]:
|
||||
user_input: str = self.session.prompt()
|
||||
self.issue_count = 0
|
||||
if not user_input:
|
||||
do_empty_query = confirm(
|
||||
[("#EBCB8B bold", "[?] "), ("#D8DEE9 bold", "Do you want to perform an empty query?")],
|
||||
|
@ -328,21 +337,39 @@ class JQLPrompt:
|
|||
self.query_count += 1
|
||||
self.console.print(
|
||||
RichText.assemble(
|
||||
(f"[+] Found {len(issues)} issues from JQL query: ", "green bold"),
|
||||
(f"[+] Found {len(issues)} issues from JQL query: ", "#A3BE8C bold"),
|
||||
self.jql.pygments_to_rich(user_input),
|
||||
),
|
||||
end="",
|
||||
)
|
||||
for issue in issues:
|
||||
self.console.print(f"{issue.key}: {issue.fields.summary}")
|
||||
return issues
|
||||
self.console.print("[!] No issues found.", style="#BF616A bold")
|
||||
|
||||
def run(self):
|
||||
def multi_prompt(self) -> Optional[List[Issue]]:
|
||||
self.issues = []
|
||||
while True:
|
||||
try:
|
||||
self.get_input()
|
||||
issues = self.prompt()
|
||||
if issues:
|
||||
issues = [issue for issue in issues if issue not in self.issues]
|
||||
self.issues.extend(issues)
|
||||
self.issue_count += len(issues)
|
||||
self.total_issue_count += len(issues)
|
||||
self.console.print(f"[ℹ] Total issues: {len(self.issues)}", style="#D8DEE9")
|
||||
get_more = confirm([("#A3BE8C", "[?] Get more issues?")], suffix=[("#81A1C1 bold", " (Y/n) ")])
|
||||
if not get_more:
|
||||
break
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
break
|
||||
self.console.print("Goodbye!", style="#BF616A bold")
|
||||
if self.issues:
|
||||
self.console.print(f"[+] Issues added: {self.total_issue_count}", style="#A3BE8C bold")
|
||||
return self.issues
|
||||
self.console.print("[!] No issues added.", style="#BF616A bold")
|
||||
|
||||
def save_log(self):
|
||||
log_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
with open(f"jql_{log_time}.txt", "w") as log_file:
|
||||
log_file.write(self.console.export_text())
|
||||
|
||||
|
||||
"""
|
||||
|
@ -362,10 +389,9 @@ class JQLPrompt:
|
|||
|
||||
def main():
|
||||
config = load_config()
|
||||
console = Console(color_system="truecolor")
|
||||
jira = JIRA(server=config["server"], basic_auth=(config["username"], config["token"]))
|
||||
prompt = JQLPrompt(jira, console)
|
||||
prompt.run()
|
||||
prompt = JQLPrompt(jira)
|
||||
prompt.multi_prompt()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
Loading…
Reference in New Issue