Skip to content

Commit

Permalink
Merge pull request #28 from elkinaguas/configure-database-usage
Browse files Browse the repository at this point in the history
Configure database usage
  • Loading branch information
elkinaguas authored Aug 10, 2024
2 parents 50f8af3 + 0dbdf95 commit 24f1244
Show file tree
Hide file tree
Showing 22 changed files with 1,139 additions and 244 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ __pycache__/
*.py[cod]
*$py.class

# MacOS
.DS_Store

# C extensions
*.so

Expand Down
44 changes: 8 additions & 36 deletions clir/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,86 +4,58 @@
from rich.prompt import Prompt
from clir.command import Command
from clir.command import CommandTable
from clir.utils.config import init_config

@click.group()
def cli():
pass

def check_config():
dir_path = os.path.join(os.path.expanduser('~'), '.clir')
file_path = os.path.join(dir_path, 'commands.json')

return os.path.exists(file_path)

#--------------------------------------- CLI commands -------------------------------------------------------

@cli.command(help="Clir initial configuration 🛠️")
def init():
dir_path = os.path.join(os.path.expanduser('~'), '.clir')
os.makedirs(dir_path, exist_ok=True)

# Define the file path and name
files = ['commands.json', 'credentials.json']

# Check if the file already exists
for file in files:
file_path = os.path.join(dir_path, file)
if not os.path.exists(file_path):
# Create the file
with open(file_path, 'w') as file_object:
file_object.write('{}')

print(f'File "{file_path}" created successfully.')
else:
print(f'A clir environment already exists in "{dir_path}".')

@cli.command(help="Save new commands 💾")
@cli.command(help="Save new command 💾")
@click.option('-c', '--command', help="Command to be saved", prompt=True)
@click.option('-d', '--description', help="Description of the command", prompt=True)
@click.option('-t', '--tag', help="Tag to be associated with the command", prompt=True)
def new(command, description, tag):
if not check_config():
print("The initial configuration is not set. Executing 'clir init'...")
subprocess.run(["clir", "init"])

# Check again after executing 'clir init'
if not check_config():
print("Could not set the initial configuration. Unable to add the new command.")
return

init_config()
new_command = Command(command = command, description = description, tag = tag)
new_command.save_command()

@cli.command(help="Remove command 👋")
@click.option('-t', '--tag', help="Search by tag")
@click.option('-g', '--grep', help="Search by grep")
def rm(tag: str = "", grep: str = ""):
init_config()
table = CommandTable(tag=tag, grep=grep)
table.remove_command()

@cli.command(help="List commands 📃")
@click.option('-t', '--tag', help="Search by tag")
@click.option('-g', '--grep', help="Search by grep")
def ls(tag: str = "", grep: str = ""):
init_config()
table = CommandTable(tag=tag, grep=grep)
table.show_table()

@cli.command(help="Run command 🚀")
@click.option('-t', '--tag', help="Search by tag")
@click.option('-g', '--grep', help="Search by grep")
def run(tag: str = "", grep: str = ""):
init_config()
table = CommandTable(tag=tag, grep=grep)
table.run_command()

@cli.command(help="Copy command to clipboard 📋")
@click.option('-t', '--tag', help="Search by tag")
@click.option('-g', '--grep', help="Search by grep")
def cp(tag: str = "", grep: str = ""):
init_config()
table = CommandTable(tag=tag, grep=grep)
table.copy_command()

@cli.command(help="Show tags 🏷️")
@click.option('-g', '--grep', help="Search by grep")
def tags(grep: str = ""):
init_config()
table = CommandTable(grep=grep)
table.show_tags()
142 changes: 22 additions & 120 deletions clir/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
from rich.console import Console
from rich.table import Table
from rich.prompt import Prompt
from clir.utils.config import verify_xclip_installation
from clir.utils.core import get_commands, replace_arguments, transform_commands_to_json
from clir.utils.db import insert_command_db, get_commands_db, remove_command_db, verify_command_id_exists, verify_command_id_tag_relation_exists

class Command:
def __init__(self, command: str = "", description: str = "", tag: str = ""):
Expand All @@ -24,29 +27,24 @@ def __repr__(self):
return f"{self.command} {self.description} {self.tag}"

def save_command(self):
current_commands = _get_commands()
current_commands = get_commands_db()

command = self.command
desc = self.description
tag = self.tag

json_file_path = os.path.join(os.path.expanduser('~'), '.clir/commands.json')
if not tag:
tag = "clir"

uid = uuid.uuid4()

current_commands[str(command)] = {"description": desc, "tag": tag, "uid": str(uid)}

# Write updated data to JSON file
with open(json_file_path, 'w') as json_file:
json.dump(current_commands, json_file)
insert_command_db(command, desc, tag)

print(f'Command saved successfuly')


#Create class Table
class CommandTable:
def __init__(self, tag: str = "", grep: str = ""):
self.commands = _get_commands(tag = tag, grep = grep)
self.commands = transform_commands_to_json(get_commands_db(tag = tag, grep = grep))
self.tag = tag
self.grep = grep

Expand All @@ -59,7 +57,7 @@ def __repr__(self):
def show_table(self):

commands = self.commands

table = Table(show_lines=True, box=box.ROUNDED, style="grey46")
table.add_column("ID 📇", style="white bold", no_wrap=True)
table.add_column("Command 💻", style="green bold", no_wrap=True)
Expand Down Expand Up @@ -99,7 +97,7 @@ def run_command(self):
if current_commands[c]["uid"] == uid:
command = c

command = _replace_arguments(command)
command = replace_arguments(command)
if uid and command:
print(f'[bold green]Running command:[/bold green] {command}')
os.system(command)
Expand All @@ -119,14 +117,14 @@ def copy_command(self):
print(f'Copying command: {command}')
if platform.system() == "Darwin":
# Verify that pbcopy is installed
if _verify_installation(package = "pbcopy"):
os.system(f'echo -n "{command}" | pbcopy')
if verify_xclip_installation(package = "pbcopy"):
os.system(f'printf "{command}" | pbcopy')
else:
print("pbcopy is not installed, this command needs pbcopy to work properly")
return
elif platform.system() == "Linux":
# Verify that xclip is installed
if _verify_installation(package = "xclip"):
if verify_xclip_installation(package = "xclip"):
os.system(f'echo -n "{command}" | xclip -selection clipboard')
else:
print("xclip is not installed, this command needs xclip to work properly")
Expand Down Expand Up @@ -156,23 +154,18 @@ def show_tags(self):

# Create a function that deletes a command when passing its uid
def remove_command(self):
json_file_path = os.path.join(os.path.expanduser('~'), '.clir/commands.json')

uid = self.get_command_uid()
all_commands = _get_commands()

del_command = ""
for command in self.commands:
if self.commands[command]["uid"] == uid:
del_command = command

if uid:
all_commands.pop(str(del_command))

# Write updated data to JSON file
with open(json_file_path, 'w') as json_file:
json.dump(all_commands, json_file)
remove_command_db(uid)
verify_command_id_exists(uid)
verify_command_id_tag_relation_exists(uid)

if verify_command_id_exists(uid):
print(f'Command not removed')
elif not verify_command_id_exists(uid) and verify_command_id_tag_relation_exists(uid):
print(f'Command removed successfuly but relation to tag not removed')
elif not verify_command_id_exists(uid) and not verify_command_id_tag_relation_exists(uid):
print(f'Command removed successfuly')


Expand All @@ -191,95 +184,4 @@ def get_command_uid(self):
except ValueError:
print("ID must be an integer")

return ""

def _verify_installation(package: str = ""):
if package == "xclip":
try:
subprocess.run(["xclip", "-version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return True
except:
return False
if package == "pbcopy":
try:
subprocess.run(["pbcopy", "-version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return True
except:
return False

return "No package specified"

def _filter_by_tag(commands: dict = {}, tag: str = ""):
if commands:
current_commands = commands
else:
current_commands = _get_commands()

tag_commands = {}
for command in current_commands:
if current_commands[command]["tag"] == tag:
tag_commands[command] = current_commands[command]

return tag_commands

def _filter_by_grep(commands: dict = {}, grep: str = ""):
if commands:
current_commands = commands
else:
current_commands = _get_commands()

grep_commands = {}
pattern = grep
for command in current_commands:
text = command + " " + current_commands[command]["description"]# + " " + current_commands[command]["tag"]
match = re.findall(pattern, text, re.IGNORECASE)
if match:
grep_commands[command] = current_commands[command]

return grep_commands

# Create a function that returns all commands
def _get_commands(tag: str = "", grep: str = ""):
current_commands = ""
json_file_path = os.path.join(os.path.expanduser('~'), '.clir/commands.json')

try:
with open(json_file_path, 'r') as json_file:
current_commands = json.load(json_file)
except FileNotFoundError:
return []

if tag:
current_commands = _filter_by_tag(commands=current_commands, tag=tag)
if grep:
current_commands = _filter_by_grep(commands=current_commands, grep=grep)

sorted_commands = dict(sorted(current_commands.items(), key=lambda item: item[1]["tag"]))

return sorted_commands

def _get_user_input(arg):
return input(f"Enter value for '{arg}': ")

def _replace_arguments(command):
# Use regex to find all arguments with underscores
matches = re.findall(r'_\w+', command)

# Check that all arguments are unique
if len(matches) != len(set(matches)):
print("[bold red]Make sure that all arguments are unique[/bold red]")
return None

# Prompt the user for values for each argument
replacements = {arg: _get_user_input(arg) for arg in matches}

# Split the command into a list
command_list = command.split(" ")

# Replace arguments in the command
for arg, value in replacements.items():
for indx,term in enumerate(command_list):
if arg == term:
command_list[indx] = value

return " ".join(command_list)
return ""
1 change: 1 addition & 0 deletions clir/config/clir.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Example
23 changes: 23 additions & 0 deletions clir/config/db/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
PRAGMA user_version = 1;
CREATE TABLE IF NOT EXISTS commands (
id TEXT PRIMARY KEY,
creation_date TEXT NOT NULL,
last_modif_date TEST NOT NULL,
command TEXT NOT NULL,
description TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS tags (
id TEXT PRIMARY KEY,
creation_date TEXT NOT NULL,
last_modif_date TEXT NOT NULL,
tag TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS commands_tags (
command_id TEXT,
tag_id TEXT,
PRIMARY KEY (command_id, tag_id),
FOREIGN KEY (command_id) REFERENCES commands(id),
FOREIGN KEY (tag_id) REFERENCES tags(id)
);
File renamed without changes.
Loading

0 comments on commit 24f1244

Please sign in to comment.