Skip to content

Commit f57980a

Browse files
committed
initial project setup
1 parent 3a35126 commit f57980a

File tree

9 files changed

+218
-3
lines changed

9 files changed

+218
-3
lines changed

.github/workflows/python-publish.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This workflow will upload a Python Package using Twine when a release is created
2+
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3+
4+
name: Upload Python Package
5+
6+
on:
7+
release:
8+
types: [created]
9+
10+
jobs:
11+
deploy:
12+
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- uses: actions/checkout@v2
17+
- name: Set up Python
18+
uses: actions/setup-python@v2
19+
with:
20+
python-version: '3.x'
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip
24+
pip install setuptools wheel twine
25+
- name: Build and publish
26+
env:
27+
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
28+
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
29+
run: |
30+
python setup.py sdist bdist_wheel
31+
twine upload dist/*

.gitignore

+28-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
venv
2+
.idea
3+
__pycache__
4+
*.py[cod]
5+
data.pickle
6+
.env
7+
db.sqlite3
28
*.pyc
3-
.svn
4-
.cvs
5-
tmp/*
9+
.DS_Store
10+
__pycache__/
11+
# Distribution / packaging
12+
.Python
13+
build/
14+
develop-eggs/
15+
dist/
16+
downloads/
17+
eggs/
18+
.eggs/
19+
lib/
20+
lib64/
21+
parts/
22+
sdist/
23+
var/
24+
wheels/
25+
pip-wheel-metadata/
26+
share/python-wheels/
27+
*.egg-info/
28+
.installed.cfg
29+
*.egg
30+
MANIFEST

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Jakub Beleščák
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
recursive-include shelllangchain *

README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# GPT for your terminal
2+
3+
Do you want to use ChatGPT in your terminal? Well, now you can!
4+
Do you always forget the syntax for a for loop? Well, now you can ask GPT to write it for you!
5+
It is a super fast way to get your commands quickly written for you.
6+
7+
## Usage
8+
```
9+
$ slc get all images in folder and crop them to square while preserving aspec ratio
10+
11+
mogrify -path <output_directory> -resize '500x500^' -gravity center -extent 500x500 <input_directory/*.jpg>
12+
13+
To get all images in a folder and crop them to a square while preserving the aspect ratio, you can use the mogrify command from the ImageMagick package.
14+
15+
Here's how the command works:
16+
17+
- mogrify is a command-line tool used to resize and modify images.
18+
- -path <output_directory> specifies the output directory where the modified images will be saved.
19+
- -resize '500x500^' resizes the images to fit within a 500x500 square, preserving the aspect ratio. The '^' symbol is used to only resize images that are larger than the specified dimensions.
20+
- -gravity center -extent 500x500 crops the resized images to a 500x500 square by adding whitespace or extending the image if necessary.
21+
- <input_directory/*.jpg> specifies the input directory where the original images are located. Replace '.jpg' with the appropriate file extension if needed.
22+
23+
Make sure to replace <input_directory> and <output_directory> with the actual directory paths on your system.
24+
$
25+
```
26+
After that the command is ready in your clipboard and you can paste it in your terminal.
27+
28+
## Requirements
29+
- OpenAI API key (https://help.openai.com/en/articles/4936850-where-do-i-find-my-api-key)
30+
31+
## Installation
32+
33+
### Using pip
34+
```
35+
pip install --user shelllangchain
36+
```
37+
Depending on your shell you might need to add the following line to your .bashrc or .zshrc file:
38+
```
39+
export OPENAI_API_KEY=<your_openai_api_key>
40+
```
41+
You can now use the `slc` command in your terminal.
42+
43+
44+
### From source
45+
If you want to modify this script, or replace chat-gpt-3.5 with another model, you can do so by cloning this repo and
46+
modifying the scripts.
47+
48+
Clone this repo and add the scripts to your PATH variable (bin folder should be on your $PATH).
49+
create a .env file in the root of this repo and add the following line:
50+
51+
```
52+
OPENAI_API_KEY=your_openai_api_key
53+
```
54+

requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
requests
2+
langchain
3+
pyperclip
4+
dotenv

setup.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import setuptools
2+
3+
with open("README.md", "r", encoding="utf-8") as fh:
4+
long_description = fh.read()
5+
6+
setuptools.setup(
7+
name="shelllangchain",
8+
version="0.1.6",
9+
author="Belda",
10+
author_email="[email protected]",
11+
description="Natural language to shell command converter",
12+
long_description=long_description,
13+
long_description_content_type="text/markdown",
14+
url="https://github.com/belda/shelllangchain",
15+
packages=setuptools.find_packages(),
16+
include_package_data=True,
17+
zip_safe=False,
18+
entry_points={
19+
"console_scripts": [
20+
"slc=shelllangchain.langchain_bash_helper:main"
21+
]
22+
},
23+
classifiers=[
24+
"Programming Language :: Python :: 3",
25+
"License :: OSI Approved :: MIT License",
26+
"Operating System :: OS Independent",
27+
],
28+
python_requires='>=3.4',
29+
install_requires = [
30+
['langchain', 'pyperclip', 'requests','dotenv']
31+
]
32+
)

shelllangchain/__init__.py

Whitespace-only changes.
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'''
2+
Simple local script, that converts natural language to bash commands directly on commandline and copies it to clipboard.
3+
'''
4+
import json
5+
import os
6+
import sys
7+
8+
import pyperclip
9+
from langchain.chat_models import ChatOpenAI
10+
from langchain.schema import SystemMessage
11+
from dotenv import load_dotenv
12+
from langchain_core.messages import HumanMessage, AIMessage
13+
14+
load_dotenv()
15+
16+
OPENAI_API_KEY = os.environ.get('OPENAI_API_KEY','')
17+
18+
19+
def get_bash_command(prompt : str) -> [str, str]:
20+
''' returns the bash command and explanation for the commands parameters '''
21+
chat = ChatOpenAI()
22+
messages = [
23+
SystemMessage(content=""" You are a assistant and an expert on linux commands and bash. When asked in natural language, you
24+
will provide the most fitting command and an explanation of the command workings in a structured way."""),
25+
HumanMessage(content="list all files in a current directory including their information"),
26+
AIMessage(content=json.dumps({"command": "ls -la",
27+
"explanation": "All files are listed using the inbuilt command \033[0;32mls\033[0m (is short for list).\n\t\033[0;32m-a\033[0m means all files\n\t\033[0;32m-l\033[0m means long format, \033[0;32m-l\033[0m means long format\n\t\033[0;32m-a\033[0m means all files"})),
28+
HumanMessage(content=prompt)
29+
]
30+
rsp = json.loads(chat(messages).content)
31+
return rsp['command'], rsp['explanation']
32+
33+
34+
def main():
35+
''' parses the arguments and processes fiels '''
36+
if OPENAI_API_KEY == '':
37+
print("You need to have your OPENAI_API_KEY defined in your environment variables", file=sys.stderr)
38+
sys.exit(1)
39+
40+
prompt = (" ").join(sys.argv[1:])
41+
command, explanation = get_bash_command(prompt)
42+
pyperclip.copy(command)
43+
print(f"\033[0;32m{command}\033[0m\n\n{explanation}\n\n")
44+
45+
46+
if __name__ == "__main__":
47+
main()

0 commit comments

Comments
 (0)