oil-cli-tool 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: oil-cli-tool
3
+ Version: 1.0.0
4
+ Summary: A tool for slick shell scripts.
5
+ Author: Your Name
6
+ Requires-Dist: typer
7
+ Requires-Dist: inquirer
8
+ Requires-Dist: yaspin
9
+ Requires-Dist: tabulate
10
+ Requires-Dist: pyfiglet
11
+ Dynamic: author
12
+ Dynamic: requires-dist
13
+ Dynamic: summary
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: oil-cli-tool
3
+ Version: 1.0.0
4
+ Summary: A tool for slick shell scripts.
5
+ Author: Your Name
6
+ Requires-Dist: typer
7
+ Requires-Dist: inquirer
8
+ Requires-Dist: yaspin
9
+ Requires-Dist: tabulate
10
+ Requires-Dist: pyfiglet
11
+ Dynamic: author
12
+ Dynamic: requires-dist
13
+ Dynamic: summary
@@ -0,0 +1,11 @@
1
+ setup.py
2
+ oil_cli_tool.egg-info/PKG-INFO
3
+ oil_cli_tool.egg-info/SOURCES.txt
4
+ oil_cli_tool.egg-info/dependency_links.txt
5
+ oil_cli_tool.egg-info/entry_points.txt
6
+ oil_cli_tool.egg-info/requires.txt
7
+ oil_cli_tool.egg-info/top_level.txt
8
+ oil_pkg/__init__.py
9
+ oil_pkg/cli.py
10
+ oil_pkg/core.py
11
+ oil_pkg/ui.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ oil = oil_pkg.cli:app
@@ -0,0 +1,5 @@
1
+ typer
2
+ inquirer
3
+ yaspin
4
+ tabulate
5
+ pyfiglet
@@ -0,0 +1 @@
1
+ oil_pkg
File without changes
@@ -0,0 +1,151 @@
1
+ from typing import List, Optional
2
+ import typer
3
+ from oil_pkg.core import oil_soak, oil_spill, oil_rag, oil_read_csv, oil_join, get_piped_data
4
+ from oil_pkg.ui import oil_choose, oil_input, oil_spin, oil_splat, oil_confirm, oil_table, oil_write, oil_filter
5
+
6
+ app = typer.Typer(
7
+ help="Oil: A tool for slick shell scripts.",
8
+ add_completion=False
9
+ )
10
+
11
+ @app.callback(invoke_without_command=True)
12
+ def main(ctx: typer.Context):
13
+ """
14
+ Oil: A tool for slick shell scripts.
15
+ """
16
+ if ctx.invoked_subcommand is None:
17
+ typer.echo(ctx.get_help())
18
+ raise typer.Exit()
19
+
20
+ @app.command()
21
+ def choose(message: str, options: List[str] = typer.Argument(...)):
22
+ """Allows the user to select an option from a list."""
23
+ # List[str] automatically collects all positional arguments into a list [cite: 54, 75]
24
+ result = oil_choose(message, options)
25
+ typer.echo(result)
26
+
27
+ @app.command()
28
+ def input(message: str):
29
+ """Allows the user to input a string."""
30
+ result = oil_input(message)
31
+ typer.echo(result)
32
+
33
+ @app.command()
34
+ def soak(file_path: str, data: Optional[str] = typer.Argument(None)):
35
+ """Soaks up data and saves it to a persistent file."""
36
+ # If no data is provided as an argument, attempt to read from stdin (pipe)
37
+ if data is None:
38
+ piped_lines = get_piped_data()
39
+ data = "\n".join(piped_lines) if piped_lines else ""
40
+
41
+ # Save the data to the user-specified file_path
42
+ oil_soak(file_path, {"cli_input": data})
43
+ typer.echo(f"✨ Successfully soaked data into {file_path}")
44
+
45
+ @app.command()
46
+ def spill(file_path: str):
47
+ """Spills (reads) data from a persistent file and prints it."""
48
+ result = oil_spill(file_path)
49
+ typer.echo(result)
50
+
51
+
52
+ @app.command()
53
+ def rag(file_path: str):
54
+ """Wipes a persistent state file clean."""
55
+ success = oil_rag(file_path)
56
+ if success:
57
+ typer.echo(f"✨ Wiped clean: {file_path}")
58
+ else:
59
+ typer.echo(f"Nothing to wipe: {file_path} does not exist.")
60
+
61
+ @app.command()
62
+ def spin(message: str, seconds: int = typer.Argument(2)):
63
+ """Displays a loading spinner."""
64
+ oil_spin(message, seconds)
65
+
66
+ @app.command()
67
+ def splat(text: str, font: str = "standard"):
68
+ """Generates ASCII art (splat) from text."""
69
+ # Use the function name defined in ui.py (oil_splat)
70
+ typer.echo(oil_splat(text, font=font))
71
+
72
+
73
+ @app.command()
74
+ def confirm(message: str):
75
+ """Ask a user to confirm an action."""
76
+ if oil_confirm(message):
77
+ typer.echo("Confirmed.")
78
+ else:
79
+ typer.echo("Action cancelled.")
80
+ raise typer.Exit(code=1)
81
+
82
+ @app.command()
83
+ def rag(file_path: str):
84
+ """Wipes a persistent state file clean."""
85
+ # Add the confirmation step
86
+ if not oil_confirm(f"Are you sure you want to wipe {file_path}?"):
87
+ typer.echo("Wipe aborted.")
88
+ raise typer.Exit()
89
+
90
+ success = oil_rag(file_path)
91
+ if success:
92
+ typer.echo(f"✨ Wiped clean: {file_path}")
93
+ else:
94
+ typer.echo(f"Nothing to wipe: {file_path} does not exist.")
95
+
96
+ @app.command()
97
+ def table(file_path: str):
98
+ """Render a table of data from a file."""
99
+ # Assuming your spill function returns a list of lists or similar data structure
100
+ from oil.core import oil_spill
101
+ data = oil_spill(file_path)
102
+ typer.echo(oil_table(data))
103
+
104
+ @app.command()
105
+ def table(file_path: str):
106
+ """Render a table of data from a file."""
107
+ data = oil_read_csv(file_path)
108
+ # The first row is headers, the rest is data
109
+ typer.echo(oil_table(data, headers="firstrow"))
110
+
111
+ @app.command()
112
+ def join(file1: str, file2: str, mode: str = "vertical"):
113
+ """Join contents of two files."""
114
+ with open(file1, 'r') as f1, open(file2, 'r') as f2:
115
+ typer.echo(oil_join(f1.read(), f2.read(), mode))
116
+
117
+ @app.command()
118
+ def write(output_file: str = None):
119
+ """Prompt for long-form text using the system editor."""
120
+ content = oil_write()
121
+ if output_file:
122
+ with open(output_file, 'w') as f:
123
+ f.write(content)
124
+ typer.echo(f"✨ Content saved to {output_file}")
125
+ else:
126
+ typer.echo(content)
127
+
128
+
129
+
130
+ @app.command()
131
+ def filter(options: str = None):
132
+ """Filter input from a pipe or a comma-separated list."""
133
+ data = []
134
+
135
+ if options:
136
+ data = options.split(',')
137
+ else:
138
+ data = get_piped_data()
139
+
140
+ if not data:
141
+ typer.echo("No data provided to filter.")
142
+ raise typer.Exit()
143
+
144
+ choice = oil_filter(data)
145
+ typer.echo(choice)
146
+
147
+
148
+
149
+ if __name__ == "__main__":
150
+ app()
151
+
@@ -0,0 +1,72 @@
1
+ import json
2
+ import os
3
+ import csv
4
+ import sys
5
+
6
+
7
+
8
+ def oil_soak(file_path, data):
9
+ """Saves data to a user-defined file path."""
10
+ # Get the directory part of the path
11
+ directory = os.path.dirname(file_path)
12
+
13
+ # Only try to create the directory if it's not the current directory
14
+ if directory:
15
+ os.makedirs(directory, exist_ok=True)
16
+
17
+ with open(file_path, 'w') as f:
18
+ json.dump(data, f, indent=4)
19
+
20
+ def oil_spill(file_path):
21
+ """Reads data from a user-defined file path."""
22
+ try:
23
+ with open(file_path, 'r') as f:
24
+ return json.load(f)
25
+ except (FileNotFoundError, json.JSONDecodeError):
26
+ # Return an empty dict if the file is missing or corrupted
27
+ return {}
28
+
29
+ def oil_rag(file_path):
30
+ """Wipes the persistent file clean (deletes it)."""
31
+ if os.path.exists(file_path):
32
+ os.remove(file_path)
33
+ return True
34
+ return False
35
+
36
+ def oil_read_csv(file_path: str):
37
+ with open(file_path, mode='r', newline='') as f:
38
+ reader = csv.reader(f)
39
+ return list(reader)
40
+
41
+ def oil_join(content1: str, content2: str, mode: str = "vertical"):
42
+ if mode == "vertical":
43
+ return f"{content1}\n{content2}"
44
+ elif mode == "horizontal":
45
+ lines1 = content1.splitlines()
46
+ lines2 = content2.splitlines()
47
+ # Ensure equal height for side-by-side
48
+ max_height = max(len(lines1), len(lines2))
49
+ lines1 += [""] * (max_height - len(lines1))
50
+ lines2 += [""] * (max_height - len(lines2))
51
+
52
+ joined = [f"{l1:<30} {l2}" for l1, l2 in zip(lines1, lines2)]
53
+ return "\n".join(joined)
54
+ return content1
55
+
56
+
57
+ def get_piped_data() -> list:
58
+ """Reads lines from stdin, then reconnects stdin to the terminal."""
59
+ if not sys.stdin.isatty():
60
+ # 1. Read the data coming from the pipe
61
+ data = sys.stdin.read().splitlines()
62
+
63
+ # 2. Reconnect standard input to the controlling terminal
64
+ # This allows interactive prompts (like inquirer) to read keyboard input again
65
+ try:
66
+ sys.stdin = open('/dev/tty')
67
+ except OSError:
68
+ pass # Fallback if /dev/tty isn't available
69
+
70
+ return data
71
+ return []
72
+
@@ -0,0 +1,78 @@
1
+ import inquirer
2
+ import typer
3
+ import time
4
+ import pyfiglet
5
+ from yaspin import yaspin
6
+ from tabulate import tabulate
7
+ import click
8
+ import os
9
+
10
+ def oil_choose(message, options):
11
+ """Renders a pure UI menu from a list."""
12
+ questions = [
13
+ inquirer.List('choice', message=message, choices=options)
14
+ ]
15
+ answers = inquirer.prompt(questions)
16
+
17
+ # Handle cancellation (Ctrl+C)
18
+ if answers is None:
19
+ return "Cancelled by user"
20
+
21
+ return answers['choice']
22
+
23
+ def oil_input(message):
24
+ """Captures pure UI input."""
25
+ return typer.prompt(message)
26
+
27
+ def oil_spin(message, seconds=2):
28
+ """Pure UI: Displays a loading spinner for a set amount of time."""
29
+ with yaspin(text=message, color="cyan") as spinner:
30
+ time.sleep(seconds)
31
+ spinner.ok("✔")
32
+
33
+ def oil_splat(text, font="standard"):
34
+ """Pure UI: Converts string into ASCII art."""
35
+ return pyfiglet.figlet_format(text, font=font)
36
+
37
+
38
+
39
+ def oil_confirm(message: str) -> bool:
40
+ questions = [
41
+ inquirer.Confirm('confirmed', message=message, default=False),
42
+ ]
43
+ answers = inquirer.prompt(questions)
44
+ return answers['confirmed'] #
45
+
46
+ #
47
+
48
+ def oil_table(data, headers="firstrow"):
49
+ return tabulate(data, headers=headers, tablefmt="grid")
50
+
51
+ def oil_write(text: str = "") -> str:
52
+ """Opens the user's default editor to write/edit text."""
53
+ # click.edit() is the standard way to handle terminal editors
54
+ edited_text = click.edit(text)
55
+ return edited_text if edited_text is not None else ""
56
+
57
+ def oil_filter(options: list) -> str:
58
+ """Provides an interactive fuzzy-selection interface."""
59
+ questions = [
60
+ inquirer.List('choice',
61
+ message="Select an option",
62
+ choices=options,
63
+ carousel=True),
64
+ ]
65
+
66
+ # --- THE OS-LEVEL FILE DESCRIPTOR SWAP ---
67
+ original_stdout_fd = os.dup(1)
68
+
69
+ try:
70
+ tty_fd = os.open('/dev/tty', os.O_WRONLY)
71
+ os.dup2(tty_fd, 1)
72
+ answers = inquirer.prompt(questions)
73
+ os.close(tty_fd)
74
+ finally:
75
+ os.dup2(original_stdout_fd, 1)
76
+ os.close(original_stdout_fd)
77
+
78
+ return answers['choice'] if answers else ""
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="oil-cli-tool",
5
+ version="1.0.0",
6
+ author="Your Name",
7
+ description="A tool for slick shell scripts.",
8
+ packages=["oil_pkg"],
9
+ install_requires=[
10
+ "typer",
11
+ "inquirer",
12
+ "yaspin",
13
+ "tabulate",
14
+ "pyfiglet",
15
+ ],
16
+ entry_points={
17
+ "console_scripts": [
18
+ "oil=oil_pkg.cli:app",
19
+ ],
20
+ },
21
+ )