janito 0.9.0__tar.gz → 0.10.1__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.
Files changed (34) hide show
  1. janito-0.10.1/.gitignore +110 -0
  2. janito-0.10.1/PKG-INFO +86 -0
  3. {janito-0.9.0 → janito-0.10.1}/README.md +5 -7
  4. janito-0.10.1/janito/__init__.py +5 -0
  5. {janito-0.9.0 → janito-0.10.1}/janito/data/instructions.txt +1 -3
  6. {janito-0.9.0 → janito-0.10.1}/janito/tools/search_text.py +226 -196
  7. janito-0.10.1/pyproject.toml +31 -0
  8. janito-0.9.0/MANIFEST.in +0 -1
  9. janito-0.9.0/PKG-INFO +0 -9
  10. janito-0.9.0/janito/__init__.py +0 -5
  11. janito-0.9.0/janito.egg-info/PKG-INFO +0 -9
  12. janito-0.9.0/janito.egg-info/SOURCES.txt +0 -28
  13. janito-0.9.0/janito.egg-info/dependency_links.txt +0 -1
  14. janito-0.9.0/janito.egg-info/entry_points.txt +0 -2
  15. janito-0.9.0/janito.egg-info/requires.txt +0 -3
  16. janito-0.9.0/janito.egg-info/top_level.txt +0 -1
  17. janito-0.9.0/pyproject.toml +0 -20
  18. janito-0.9.0/setup.cfg +0 -4
  19. janito-0.9.0/setup.py +0 -7
  20. {janito-0.9.0 → janito-0.10.1}/LICENSE +0 -0
  21. {janito-0.9.0 → janito-0.10.1}/janito/__main__.py +0 -0
  22. {janito-0.9.0 → janito-0.10.1}/janito/callbacks.py +0 -0
  23. {janito-0.9.0 → janito-0.10.1}/janito/cli.py +0 -0
  24. {janito-0.9.0 → janito-0.10.1}/janito/config.py +0 -0
  25. {janito-0.9.0 → janito-0.10.1}/janito/test_file.py +0 -0
  26. {janito-0.9.0 → janito-0.10.1}/janito/token_report.py +0 -0
  27. {janito-0.9.0 → janito-0.10.1}/janito/tools/__init__.py +0 -0
  28. {janito-0.9.0 → janito-0.10.1}/janito/tools/decorators.py +0 -0
  29. {janito-0.9.0 → janito-0.10.1}/janito/tools/delete_file.py +0 -0
  30. {janito-0.9.0 → janito-0.10.1}/janito/tools/find_files.py +0 -0
  31. {janito-0.9.0 → janito-0.10.1}/janito/tools/str_replace_editor/__init__.py +0 -0
  32. {janito-0.9.0 → janito-0.10.1}/janito/tools/str_replace_editor/editor.py +0 -0
  33. {janito-0.9.0 → janito-0.10.1}/janito/tools/str_replace_editor/handlers.py +0 -0
  34. {janito-0.9.0 → janito-0.10.1}/janito/tools/str_replace_editor/utils.py +0 -0
@@ -0,0 +1,110 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ .installed.cfg
25
+ *.egg
26
+
27
+ # PyInstaller
28
+ *.manifest
29
+ *.spec
30
+
31
+ # Installer logs
32
+ pip-log.txt
33
+ pip-delete-this-directory.txt
34
+
35
+ # Unit test / coverage reports
36
+ htmlcov/
37
+ .tox/
38
+ .coverage
39
+ .coverage.*
40
+ .cache
41
+ nosetests.xml
42
+ coverage.xml
43
+ *.cover
44
+ .hypothesis/
45
+ .pytest_cache/
46
+
47
+ # Translations
48
+ *.mo
49
+ *.pot
50
+
51
+ # Django stuff:
52
+ *.log
53
+ local_settings.py
54
+ db.sqlite3
55
+
56
+ # Flask stuff:
57
+ instance/
58
+ .webassets-cache
59
+
60
+ # Scrapy stuff:
61
+ .scrapy
62
+
63
+ # Sphinx documentation
64
+ docs/_build/
65
+
66
+ # PyBuilder
67
+ target/
68
+
69
+ # Jupyter Notebook
70
+ .ipynb_checkpoints
71
+
72
+ # pyenv
73
+ .python-version
74
+
75
+ # celery beat schedule file
76
+ celerybeat-schedule
77
+
78
+ # SageMath parsed files
79
+ *.sage.py
80
+
81
+ # Environments
82
+ .env
83
+ .venv
84
+ env/
85
+ venv/
86
+ ENV/
87
+ env.bak/
88
+ venv.bak/
89
+
90
+ # Spyder project settings
91
+ .spyderproject
92
+ .spyproject
93
+
94
+ # Rope project settings
95
+ .ropeproject
96
+
97
+ # mkdocs documentation
98
+ /site
99
+
100
+ # mypy
101
+ .mypy_cache/
102
+
103
+ # IDE specific files
104
+ .idea/
105
+ .vscode/
106
+ *.swp
107
+ *.swo
108
+
109
+ # Janito
110
+ .janito/
janito-0.10.1/PKG-INFO ADDED
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: janito
3
+ Version: 0.10.1
4
+ Summary: Janito CLI tool
5
+ Project-URL: Homepage, https://github.com/joaompinto/janito
6
+ Author-email: João Pinto <lamego.pinto@gmail.com>
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.8
9
+ Requires-Dist: claudine>=0.1.0
10
+ Requires-Dist: rich>=13.0.0
11
+ Requires-Dist: typer>=0.9.0
12
+ Description-Content-Type: text/markdown
13
+
14
+ # 🤖 Janito
15
+
16
+ Janito is a powerful AI-assisted command-line interface (CLI) tool built with Python, leveraging Anthropic's Claude for intelligent code and file management.
17
+
18
+ ## ✨ Features
19
+
20
+ - 🧠 Intelligent AI assistant powered by Claude
21
+ - 📁 File management capabilities
22
+ - 🔍 Smart code search and editing
23
+ - 💻 Interactive terminal interface with rich formatting
24
+ - 📊 Token usage tracking and cost reporting
25
+
26
+ ## 🛠️ Installation
27
+
28
+ ```bash
29
+ # Install directly from PyPI
30
+ pip install janito
31
+ ```
32
+
33
+ For development or installation from source, please see [README_DEV.md](README_DEV.md).
34
+
35
+ ## 🚀 Usage
36
+
37
+ After installation, you can use the `janito` command in your terminal:
38
+
39
+ ```bash
40
+ # Get help
41
+ janito --help
42
+
43
+
44
+ # Ask the AI assistant a question
45
+ janito "Suggest improvements to this project"
46
+
47
+ janito "Add a --version to the cli to report he version"
48
+
49
+ ```
50
+
51
+ ## 🔧 Available Tools
52
+
53
+ Janito comes with several built-in tools:
54
+ - 📄 `str_replace_editor` - View, create, and edit files
55
+ - 🔎 `find_files` - Find files matching patterns
56
+ - 🗑️ `delete_file` - Delete files
57
+ - 🔍 `search_text` - Search for text patterns in files
58
+
59
+ ## ⚙️ Requirements
60
+
61
+ - Python 3.8 or higher
62
+ - Dependencies:
63
+ - typer (>=0.9.0)
64
+ - rich (>=13.0.0)
65
+ - claudine (for Claude AI integration)
66
+
67
+ ## 🔑 API Key
68
+
69
+ Janito requires an Anthropic API key to function. You can:
70
+ 1. Set it as an environment variable: `export ANTHROPIC_API_KEY=your_api_key`
71
+ 2. Or enter it when prompted
72
+
73
+ ## 💻 Development
74
+
75
+ ```bash
76
+ # Create a virtual environment
77
+ python -m venv .venv
78
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
79
+
80
+ # Install development dependencies
81
+ pip install -e ".[dev]"
82
+ ```
83
+
84
+ ## 📜 License
85
+
86
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -13,14 +13,12 @@ Janito is a powerful AI-assisted command-line interface (CLI) tool built with Py
13
13
  ## 🛠️ Installation
14
14
 
15
15
  ```bash
16
- # Clone the repository
17
- git clone https://github.com/joaompinto/janito.git
18
- cd janito
19
-
20
- # Install the package
21
- pip install -e .
16
+ # Install directly from PyPI
17
+ pip install janito
22
18
  ```
23
19
 
20
+ For development or installation from source, please see [README_DEV.md](README_DEV.md).
21
+
24
22
  ## 🚀 Usage
25
23
 
26
24
  After installation, you can use the `janito` command in your terminal:
@@ -72,4 +70,4 @@ pip install -e ".[dev]"
72
70
 
73
71
  ## 📜 License
74
72
 
75
- [Add your license information here]
73
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,5 @@
1
+ """
2
+ Janito package.
3
+ """
4
+
5
+ __version__ = "0.11.0"
@@ -1,6 +1,4 @@
1
- You are a helpful AI assistant, working in a repository.
2
- Answer the user's questions accurately and concisely.
3
-
1
+ You are an expert software engineer, working in a project.
4
2
  When using str_replace_editor be aware that our files starting path is "." .
5
3
 
6
4
  Before performing any action, always check the structure of the project for paths that might be related to the request.
@@ -1,197 +1,227 @@
1
- import os
2
- import fnmatch
3
- import re
4
- import pathlib
5
- from typing import List, Dict, Any, Tuple
6
- from janito.tools.decorators import tool_meta
7
-
8
-
9
- @tool_meta(label="Searching for '{text_pattern}' in files matching '{file_pattern}'")
10
- def search_text(text_pattern: str, file_pattern: str = "*", root_dir: str = ".", recursive: bool = True, respect_gitignore: bool = True) -> Tuple[str, bool]:
11
- """
12
- Search for text patterns within files matching a filename pattern.
13
-
14
- Args:
15
- text_pattern: Text pattern to search for within files
16
- file_pattern: Pattern to match file names against (default: "*" - all files)
17
- root_dir: Root directory to start search from (default: current directory)
18
- recursive: Whether to search recursively in subdirectories (default: True)
19
- respect_gitignore: Whether to respect .gitignore files (default: True)
20
-
21
- Returns:
22
- A tuple containing (message, is_error)
23
- """
24
- try:
25
- # Convert to absolute path if relative
26
- abs_root = os.path.abspath(root_dir)
27
-
28
- if not os.path.isdir(abs_root):
29
- return f"Error: Directory '{root_dir}' does not exist", True
30
-
31
- # Compile the regex pattern for better performance
32
- try:
33
- regex = re.compile(text_pattern)
34
- except re.error as e:
35
- return f"Error: Invalid regex pattern '{text_pattern}': {str(e)}", True
36
-
37
- matching_files = []
38
- match_count = 0
39
- results = []
40
-
41
- # Get gitignore patterns if needed
42
- ignored_patterns = []
43
- if respect_gitignore:
44
- ignored_patterns = _get_gitignore_patterns(abs_root)
45
-
46
- # Use os.walk for recursive behavior
47
- if recursive:
48
- for dirpath, dirnames, filenames in os.walk(abs_root):
49
- # Skip ignored directories
50
- if respect_gitignore:
51
- dirnames[:] = [d for d in dirnames if not _is_ignored(os.path.join(dirpath, d), ignored_patterns, abs_root)]
52
-
53
- for filename in fnmatch.filter(filenames, file_pattern):
54
- file_path = os.path.join(dirpath, filename)
55
-
56
- # Skip ignored files
57
- if respect_gitignore and _is_ignored(file_path, ignored_patterns, abs_root):
58
- continue
59
-
60
- file_matches = _search_file(file_path, regex, abs_root)
61
- if file_matches:
62
- matching_files.append(file_path)
63
- match_count += len(file_matches)
64
- results.append(f"\n{os.path.relpath(file_path, abs_root)} ({len(file_matches)} matches):")
65
- results.extend(file_matches)
66
- else:
67
- # Non-recursive mode - only search in the specified directory
68
- for filename in fnmatch.filter(os.listdir(abs_root), file_pattern):
69
- file_path = os.path.join(abs_root, filename)
70
-
71
- # Skip ignored files
72
- if respect_gitignore and _is_ignored(file_path, ignored_patterns, abs_root):
73
- continue
74
-
75
- if os.path.isfile(file_path):
76
- file_matches = _search_file(file_path, regex, abs_root)
77
- if file_matches:
78
- matching_files.append(file_path)
79
- match_count += len(file_matches)
80
- results.append(f"\n{os.path.relpath(file_path, abs_root)} ({len(file_matches)} matches):")
81
- results.extend(file_matches)
82
-
83
- if matching_files:
84
- result_text = "\n".join(results)
85
- summary = f"\n{match_count} matches in {len(matching_files)} files"
86
- return f"Searching for '{text_pattern}' in files matching '{file_pattern}':{result_text}\n{summary}", False
87
- else:
88
- return f"No matches found for '{text_pattern}' in files matching '{file_pattern}' in '{root_dir}'", False
89
-
90
- except Exception as e:
91
- return f"Error searching text: {str(e)}", True
92
-
93
-
94
- def _search_file(file_path: str, pattern: re.Pattern, root_dir: str) -> List[str]:
95
- """
96
- Search for regex pattern in a file and return matching lines with line numbers.
97
-
98
- Args:
99
- file_path: Path to the file to search
100
- pattern: Compiled regex pattern to search for
101
- root_dir: Root directory (for path display)
102
-
103
- Returns:
104
- List of formatted matches with line numbers and content
105
- """
106
- matches = []
107
- try:
108
- with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
109
- for i, line in enumerate(f, 1):
110
- if pattern.search(line):
111
- # Truncate long lines for display
112
- display_line = line.strip()
113
- if len(display_line) > 100:
114
- display_line = display_line[:97] + "..."
115
- matches.append(f" Line {i}: {display_line}")
116
- except (UnicodeDecodeError, IOError) as e:
117
- # Skip binary files or files with encoding issues
118
- pass
119
- return matches
120
-
121
-
122
- def _get_gitignore_patterns(root_dir: str) -> List[str]:
123
- """
124
- Get patterns from .gitignore files.
125
-
126
- Args:
127
- root_dir: Root directory to start from
128
-
129
- Returns:
130
- List of gitignore patterns
131
- """
132
- patterns = []
133
-
134
- # Check for .gitignore in the root directory
135
- gitignore_path = os.path.join(root_dir, '.gitignore')
136
- if os.path.isfile(gitignore_path):
137
- try:
138
- with open(gitignore_path, 'r', encoding='utf-8') as f:
139
- for line in f:
140
- line = line.strip()
141
- # Skip empty lines and comments
142
- if line and not line.startswith('#'):
143
- patterns.append(line)
144
- except Exception:
145
- pass
146
-
147
- # Add common patterns that are always ignored
148
- common_patterns = [
149
- '.git/', '.venv/', 'venv/', '__pycache__/', '*.pyc',
150
- '*.pyo', '*.pyd', '.DS_Store', '*.so', '*.egg-info/'
151
- ]
152
- patterns.extend(common_patterns)
153
-
154
- return patterns
155
-
156
-
157
- def _is_ignored(path: str, patterns: List[str], root_dir: str) -> bool:
158
- """
159
- Check if a path should be ignored based on gitignore patterns.
160
-
161
- Args:
162
- path: Path to check
163
- patterns: List of gitignore patterns
164
- root_dir: Root directory for relative paths
165
-
166
- Returns:
167
- True if the path should be ignored, False otherwise
168
- """
169
- # Get the relative path from the root directory
170
- rel_path = os.path.relpath(path, root_dir)
171
-
172
- # Convert to forward slashes for consistency with gitignore patterns
173
- rel_path = rel_path.replace(os.sep, '/')
174
-
175
- # Add trailing slash for directories
176
- if os.path.isdir(path) and not rel_path.endswith('/'):
177
- rel_path += '/'
178
-
179
- for pattern in patterns:
180
- # Handle negation patterns (those starting with !)
181
- if pattern.startswith('!'):
182
- continue # Skip negation patterns for simplicity
183
-
184
- # Handle directory-specific patterns (those ending with /)
185
- if pattern.endswith('/'):
186
- if os.path.isdir(path) and fnmatch.fnmatch(rel_path, pattern + '*'):
187
- return True
188
-
189
- # Handle file patterns
190
- if fnmatch.fnmatch(rel_path, pattern):
191
- return True
192
-
193
- # Handle patterns without wildcards as path prefixes
194
- if '*' not in pattern and '?' not in pattern and rel_path.startswith(pattern):
195
- return True
196
-
1
+ import os
2
+ import fnmatch
3
+ import re
4
+ import pathlib
5
+ from typing import List, Dict, Any, Tuple
6
+ from janito.tools.decorators import tool_meta
7
+
8
+
9
+ @tool_meta(label="Searching for '{text_pattern}' in files matching '{file_pattern}'")
10
+ def search_text(text_pattern: str, file_pattern: str = "*", root_dir: str = ".", recursive: bool = True, respect_gitignore: bool = True) -> Tuple[str, bool]:
11
+ """
12
+ Search for text patterns within files matching a filename pattern.
13
+
14
+ Args:
15
+ text_pattern: Text pattern to search for within files
16
+ file_pattern: Pattern to match file names against (default: "*")
17
+ Multiple patterns can be specified using semicolons or spaces as separators
18
+ Examples: "*.py *.toml *.sh *.md test*"
19
+ root_dir: Root directory to start search from (default: current directory)
20
+ recursive: Whether to search recursively in subdirectories (default: True)
21
+ respect_gitignore: Whether to respect .gitignore files (default: True)
22
+
23
+ Returns:
24
+ A tuple containing (message, is_error)
25
+ """
26
+ try:
27
+ # Convert to absolute path if relative
28
+ abs_root = os.path.abspath(root_dir)
29
+
30
+ if not os.path.isdir(abs_root):
31
+ return f"Error: Directory '{root_dir}' does not exist", True
32
+
33
+ # Compile the regex pattern for better performance
34
+ try:
35
+ regex = re.compile(text_pattern)
36
+ except re.error as e:
37
+ return f"Error: Invalid regex pattern '{text_pattern}': {str(e)}", True
38
+
39
+ matching_files = []
40
+ match_count = 0
41
+ results = []
42
+
43
+ # Get gitignore patterns if needed
44
+ ignored_patterns = []
45
+ if respect_gitignore:
46
+ ignored_patterns = _get_gitignore_patterns(abs_root)
47
+
48
+ # Use os.walk for recursive behavior
49
+ if recursive:
50
+ for dirpath, dirnames, filenames in os.walk(abs_root):
51
+ # Skip ignored directories
52
+ if respect_gitignore:
53
+ dirnames[:] = [d for d in dirnames if not _is_ignored(os.path.join(dirpath, d), ignored_patterns, abs_root)]
54
+
55
+ # Handle multiple patterns separated by semicolons or spaces
56
+ patterns = []
57
+ if ';' in file_pattern:
58
+ patterns = file_pattern.split(';')
59
+ elif ' ' in file_pattern:
60
+ patterns = file_pattern.split()
61
+ else:
62
+ patterns = [file_pattern]
63
+
64
+ for pattern in patterns:
65
+ for filename in fnmatch.filter(filenames, pattern):
66
+ file_path = os.path.join(dirpath, filename)
67
+
68
+ # Skip ignored files
69
+ if respect_gitignore and _is_ignored(file_path, ignored_patterns, abs_root):
70
+ continue
71
+
72
+ # Skip if already processed this file
73
+ if file_path in matching_files:
74
+ continue
75
+
76
+ file_matches = _search_file(file_path, regex, abs_root)
77
+ if file_matches:
78
+ matching_files.append(file_path)
79
+ match_count += len(file_matches)
80
+ results.append(f"\n{os.path.relpath(file_path, abs_root)} ({len(file_matches)} matches):")
81
+ results.extend(file_matches)
82
+ else:
83
+ # Non-recursive mode - only search in the specified directory
84
+ # Handle multiple patterns separated by semicolons or spaces
85
+ patterns = []
86
+ if ';' in file_pattern:
87
+ patterns = file_pattern.split(';')
88
+ elif ' ' in file_pattern:
89
+ patterns = file_pattern.split()
90
+ else:
91
+ patterns = [file_pattern]
92
+
93
+ for pattern in patterns:
94
+ for filename in fnmatch.filter(os.listdir(abs_root), pattern):
95
+ file_path = os.path.join(abs_root, filename)
96
+
97
+ # Skip ignored files
98
+ if respect_gitignore and _is_ignored(file_path, ignored_patterns, abs_root):
99
+ continue
100
+
101
+ # Skip if already processed this file
102
+ if file_path in matching_files:
103
+ continue
104
+
105
+ if os.path.isfile(file_path):
106
+ file_matches = _search_file(file_path, regex, abs_root)
107
+ if file_matches:
108
+ matching_files.append(file_path)
109
+ match_count += len(file_matches)
110
+ results.append(f"\n{os.path.relpath(file_path, abs_root)} ({len(file_matches)} matches):")
111
+ results.extend(file_matches)
112
+
113
+ if matching_files:
114
+ result_text = "\n".join(results)
115
+ summary = f"\n{match_count} matches in {len(matching_files)} files"
116
+ return f"Searching for '{text_pattern}' in files matching '{file_pattern}':{result_text}\n{summary}", False
117
+ else:
118
+ return f"No matches found for '{text_pattern}' in files matching '{file_pattern}' in '{root_dir}'", False
119
+
120
+ except Exception as e:
121
+ return f"Error searching text: {str(e)}", True
122
+
123
+
124
+ def _search_file(file_path: str, pattern: re.Pattern, root_dir: str) -> List[str]:
125
+ """
126
+ Search for regex pattern in a file and return matching lines with line numbers.
127
+
128
+ Args:
129
+ file_path: Path to the file to search
130
+ pattern: Compiled regex pattern to search for
131
+ root_dir: Root directory (for path display)
132
+
133
+ Returns:
134
+ List of formatted matches with line numbers and content
135
+ """
136
+ matches = []
137
+ try:
138
+ with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
139
+ for i, line in enumerate(f, 1):
140
+ if pattern.search(line):
141
+ # Truncate long lines for display
142
+ display_line = line.strip()
143
+ if len(display_line) > 100:
144
+ display_line = display_line[:97] + "..."
145
+ matches.append(f" Line {i}: {display_line}")
146
+ except (UnicodeDecodeError, IOError) as e:
147
+ # Skip binary files or files with encoding issues
148
+ pass
149
+ return matches
150
+
151
+
152
+ def _get_gitignore_patterns(root_dir: str) -> List[str]:
153
+ """
154
+ Get patterns from .gitignore files.
155
+
156
+ Args:
157
+ root_dir: Root directory to start from
158
+
159
+ Returns:
160
+ List of gitignore patterns
161
+ """
162
+ patterns = []
163
+
164
+ # Check for .gitignore in the root directory
165
+ gitignore_path = os.path.join(root_dir, '.gitignore')
166
+ if os.path.isfile(gitignore_path):
167
+ try:
168
+ with open(gitignore_path, 'r', encoding='utf-8') as f:
169
+ for line in f:
170
+ line = line.strip()
171
+ # Skip empty lines and comments
172
+ if line and not line.startswith('#'):
173
+ patterns.append(line)
174
+ except Exception:
175
+ pass
176
+
177
+ # Add common patterns that are always ignored
178
+ common_patterns = [
179
+ '.git/', '.venv/', 'venv/', '__pycache__/', '*.pyc',
180
+ '*.pyo', '*.pyd', '.DS_Store', '*.so', '*.egg-info/'
181
+ ]
182
+ patterns.extend(common_patterns)
183
+
184
+ return patterns
185
+
186
+
187
+ def _is_ignored(path: str, patterns: List[str], root_dir: str) -> bool:
188
+ """
189
+ Check if a path should be ignored based on gitignore patterns.
190
+
191
+ Args:
192
+ path: Path to check
193
+ patterns: List of gitignore patterns
194
+ root_dir: Root directory for relative paths
195
+
196
+ Returns:
197
+ True if the path should be ignored, False otherwise
198
+ """
199
+ # Get the relative path from the root directory
200
+ rel_path = os.path.relpath(path, root_dir)
201
+
202
+ # Convert to forward slashes for consistency with gitignore patterns
203
+ rel_path = rel_path.replace(os.sep, '/')
204
+
205
+ # Add trailing slash for directories
206
+ if os.path.isdir(path) and not rel_path.endswith('/'):
207
+ rel_path += '/'
208
+
209
+ for pattern in patterns:
210
+ # Handle negation patterns (those starting with !)
211
+ if pattern.startswith('!'):
212
+ continue # Skip negation patterns for simplicity
213
+
214
+ # Handle directory-specific patterns (those ending with /)
215
+ if pattern.endswith('/'):
216
+ if os.path.isdir(path) and fnmatch.fnmatch(rel_path, pattern + '*'):
217
+ return True
218
+
219
+ # Handle file patterns
220
+ if fnmatch.fnmatch(rel_path, pattern):
221
+ return True
222
+
223
+ # Handle patterns without wildcards as path prefixes
224
+ if '*' not in pattern and '?' not in pattern and rel_path.startswith(pattern):
225
+ return True
226
+
197
227
  return False
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "janito"
7
+ version = "0.10.1"
8
+ description = "Janito CLI tool"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ authors = [
12
+ {name = "João Pinto", email = "lamego.pinto@gmail.com"}
13
+ ]
14
+ urls = {Homepage = "https://github.com/joaompinto/janito"}
15
+ dependencies = [
16
+ "typer>=0.9.0",
17
+ "rich>=13.0.0",
18
+ "claudine>=0.1.0",
19
+ ]
20
+
21
+ [project.scripts]
22
+ janito = "janito.__main__:app"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["janito"]
26
+
27
+ [tool.hatch.build.targets.sdist]
28
+ include = ["janito", "README.md"]
29
+
30
+ [tool.hatch.build.force-include]
31
+ "janito/data" = "janito/data"
janito-0.9.0/MANIFEST.in DELETED
@@ -1 +0,0 @@
1
- include janito/data/*.txt
janito-0.9.0/PKG-INFO DELETED
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: janito
3
- Version: 0.9.0
4
- Summary: Janito CLI tool
5
- Requires-Python: >=3.8
6
- License-File: LICENSE
7
- Requires-Dist: typer>=0.9.0
8
- Requires-Dist: rich>=13.0.0
9
- Requires-Dist: claudine>=0.1.0
@@ -1,5 +0,0 @@
1
- """
2
- Janito package.
3
- """
4
-
5
- __version__ = "0.9.0"
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: janito
3
- Version: 0.9.0
4
- Summary: Janito CLI tool
5
- Requires-Python: >=3.8
6
- License-File: LICENSE
7
- Requires-Dist: typer>=0.9.0
8
- Requires-Dist: rich>=13.0.0
9
- Requires-Dist: claudine>=0.1.0
@@ -1,28 +0,0 @@
1
- LICENSE
2
- MANIFEST.in
3
- README.md
4
- pyproject.toml
5
- setup.py
6
- janito/__init__.py
7
- janito/__main__.py
8
- janito/callbacks.py
9
- janito/cli.py
10
- janito/config.py
11
- janito/test_file.py
12
- janito/token_report.py
13
- janito.egg-info/PKG-INFO
14
- janito.egg-info/SOURCES.txt
15
- janito.egg-info/dependency_links.txt
16
- janito.egg-info/entry_points.txt
17
- janito.egg-info/requires.txt
18
- janito.egg-info/top_level.txt
19
- janito/data/instructions.txt
20
- janito/tools/__init__.py
21
- janito/tools/decorators.py
22
- janito/tools/delete_file.py
23
- janito/tools/find_files.py
24
- janito/tools/search_text.py
25
- janito/tools/str_replace_editor/__init__.py
26
- janito/tools/str_replace_editor/editor.py
27
- janito/tools/str_replace_editor/handlers.py
28
- janito/tools/str_replace_editor/utils.py
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- janito = janito.__main__:app
@@ -1,3 +0,0 @@
1
- typer>=0.9.0
2
- rich>=13.0.0
3
- claudine>=0.1.0
@@ -1 +0,0 @@
1
- janito
@@ -1,20 +0,0 @@
1
- [build-system]
2
- requires = ["setuptools>=61.0", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "janito"
7
- version = "0.9.0"
8
- description = "Janito CLI tool"
9
- requires-python = ">=3.8"
10
- dependencies = [
11
- "typer>=0.9.0",
12
- "rich>=13.0.0",
13
- "claudine>=0.1.0",
14
- ]
15
-
16
- [project.scripts]
17
- janito = "janito.__main__:app"
18
-
19
- [tool.setuptools.package-data]
20
- "janito" = ["data/*.txt"]
janito-0.9.0/setup.cfg DELETED
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
janito-0.9.0/setup.py DELETED
@@ -1,7 +0,0 @@
1
- from setuptools import setup, find_packages
2
-
3
- setup(
4
- name="janito",
5
- packages=find_packages(),
6
- include_package_data=True,
7
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes