just-bash 0.1.5__py3-none-any.whl

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 (193) hide show
  1. just_bash/__init__.py +55 -0
  2. just_bash/ast/__init__.py +213 -0
  3. just_bash/ast/factory.py +320 -0
  4. just_bash/ast/types.py +953 -0
  5. just_bash/bash.py +220 -0
  6. just_bash/commands/__init__.py +23 -0
  7. just_bash/commands/argv/__init__.py +5 -0
  8. just_bash/commands/argv/argv.py +21 -0
  9. just_bash/commands/awk/__init__.py +5 -0
  10. just_bash/commands/awk/awk.py +1168 -0
  11. just_bash/commands/base64/__init__.py +5 -0
  12. just_bash/commands/base64/base64.py +138 -0
  13. just_bash/commands/basename/__init__.py +5 -0
  14. just_bash/commands/basename/basename.py +72 -0
  15. just_bash/commands/bash/__init__.py +5 -0
  16. just_bash/commands/bash/bash.py +188 -0
  17. just_bash/commands/cat/__init__.py +5 -0
  18. just_bash/commands/cat/cat.py +173 -0
  19. just_bash/commands/checksum/__init__.py +5 -0
  20. just_bash/commands/checksum/checksum.py +179 -0
  21. just_bash/commands/chmod/__init__.py +5 -0
  22. just_bash/commands/chmod/chmod.py +216 -0
  23. just_bash/commands/column/__init__.py +5 -0
  24. just_bash/commands/column/column.py +180 -0
  25. just_bash/commands/comm/__init__.py +5 -0
  26. just_bash/commands/comm/comm.py +150 -0
  27. just_bash/commands/compression/__init__.py +5 -0
  28. just_bash/commands/compression/compression.py +298 -0
  29. just_bash/commands/cp/__init__.py +5 -0
  30. just_bash/commands/cp/cp.py +149 -0
  31. just_bash/commands/curl/__init__.py +5 -0
  32. just_bash/commands/curl/curl.py +801 -0
  33. just_bash/commands/cut/__init__.py +5 -0
  34. just_bash/commands/cut/cut.py +327 -0
  35. just_bash/commands/date/__init__.py +5 -0
  36. just_bash/commands/date/date.py +258 -0
  37. just_bash/commands/diff/__init__.py +5 -0
  38. just_bash/commands/diff/diff.py +118 -0
  39. just_bash/commands/dirname/__init__.py +5 -0
  40. just_bash/commands/dirname/dirname.py +56 -0
  41. just_bash/commands/du/__init__.py +5 -0
  42. just_bash/commands/du/du.py +150 -0
  43. just_bash/commands/echo/__init__.py +5 -0
  44. just_bash/commands/echo/echo.py +125 -0
  45. just_bash/commands/env/__init__.py +5 -0
  46. just_bash/commands/env/env.py +163 -0
  47. just_bash/commands/expand/__init__.py +5 -0
  48. just_bash/commands/expand/expand.py +299 -0
  49. just_bash/commands/expr/__init__.py +5 -0
  50. just_bash/commands/expr/expr.py +273 -0
  51. just_bash/commands/file/__init__.py +5 -0
  52. just_bash/commands/file/file.py +274 -0
  53. just_bash/commands/find/__init__.py +5 -0
  54. just_bash/commands/find/find.py +623 -0
  55. just_bash/commands/fold/__init__.py +5 -0
  56. just_bash/commands/fold/fold.py +160 -0
  57. just_bash/commands/grep/__init__.py +5 -0
  58. just_bash/commands/grep/grep.py +418 -0
  59. just_bash/commands/head/__init__.py +5 -0
  60. just_bash/commands/head/head.py +167 -0
  61. just_bash/commands/help/__init__.py +5 -0
  62. just_bash/commands/help/help.py +67 -0
  63. just_bash/commands/hostname/__init__.py +5 -0
  64. just_bash/commands/hostname/hostname.py +21 -0
  65. just_bash/commands/html_to_markdown/__init__.py +5 -0
  66. just_bash/commands/html_to_markdown/html_to_markdown.py +191 -0
  67. just_bash/commands/join/__init__.py +5 -0
  68. just_bash/commands/join/join.py +252 -0
  69. just_bash/commands/jq/__init__.py +5 -0
  70. just_bash/commands/jq/jq.py +280 -0
  71. just_bash/commands/ln/__init__.py +5 -0
  72. just_bash/commands/ln/ln.py +127 -0
  73. just_bash/commands/ls/__init__.py +5 -0
  74. just_bash/commands/ls/ls.py +280 -0
  75. just_bash/commands/mkdir/__init__.py +5 -0
  76. just_bash/commands/mkdir/mkdir.py +92 -0
  77. just_bash/commands/mv/__init__.py +5 -0
  78. just_bash/commands/mv/mv.py +142 -0
  79. just_bash/commands/nl/__init__.py +5 -0
  80. just_bash/commands/nl/nl.py +180 -0
  81. just_bash/commands/od/__init__.py +5 -0
  82. just_bash/commands/od/od.py +157 -0
  83. just_bash/commands/paste/__init__.py +5 -0
  84. just_bash/commands/paste/paste.py +100 -0
  85. just_bash/commands/printf/__init__.py +5 -0
  86. just_bash/commands/printf/printf.py +157 -0
  87. just_bash/commands/pwd/__init__.py +5 -0
  88. just_bash/commands/pwd/pwd.py +23 -0
  89. just_bash/commands/read/__init__.py +5 -0
  90. just_bash/commands/read/read.py +185 -0
  91. just_bash/commands/readlink/__init__.py +5 -0
  92. just_bash/commands/readlink/readlink.py +86 -0
  93. just_bash/commands/registry.py +844 -0
  94. just_bash/commands/rev/__init__.py +5 -0
  95. just_bash/commands/rev/rev.py +74 -0
  96. just_bash/commands/rg/__init__.py +5 -0
  97. just_bash/commands/rg/rg.py +1048 -0
  98. just_bash/commands/rm/__init__.py +5 -0
  99. just_bash/commands/rm/rm.py +106 -0
  100. just_bash/commands/search_engine/__init__.py +13 -0
  101. just_bash/commands/search_engine/matcher.py +170 -0
  102. just_bash/commands/search_engine/regex.py +159 -0
  103. just_bash/commands/sed/__init__.py +5 -0
  104. just_bash/commands/sed/sed.py +863 -0
  105. just_bash/commands/seq/__init__.py +5 -0
  106. just_bash/commands/seq/seq.py +190 -0
  107. just_bash/commands/shell/__init__.py +5 -0
  108. just_bash/commands/shell/shell.py +206 -0
  109. just_bash/commands/sleep/__init__.py +5 -0
  110. just_bash/commands/sleep/sleep.py +62 -0
  111. just_bash/commands/sort/__init__.py +5 -0
  112. just_bash/commands/sort/sort.py +411 -0
  113. just_bash/commands/split/__init__.py +5 -0
  114. just_bash/commands/split/split.py +237 -0
  115. just_bash/commands/sqlite3/__init__.py +5 -0
  116. just_bash/commands/sqlite3/sqlite3_cmd.py +505 -0
  117. just_bash/commands/stat/__init__.py +5 -0
  118. just_bash/commands/stat/stat.py +150 -0
  119. just_bash/commands/strings/__init__.py +5 -0
  120. just_bash/commands/strings/strings.py +150 -0
  121. just_bash/commands/tac/__init__.py +5 -0
  122. just_bash/commands/tac/tac.py +158 -0
  123. just_bash/commands/tail/__init__.py +5 -0
  124. just_bash/commands/tail/tail.py +180 -0
  125. just_bash/commands/tar/__init__.py +5 -0
  126. just_bash/commands/tar/tar.py +1067 -0
  127. just_bash/commands/tee/__init__.py +5 -0
  128. just_bash/commands/tee/tee.py +63 -0
  129. just_bash/commands/timeout/__init__.py +5 -0
  130. just_bash/commands/timeout/timeout.py +188 -0
  131. just_bash/commands/touch/__init__.py +5 -0
  132. just_bash/commands/touch/touch.py +91 -0
  133. just_bash/commands/tr/__init__.py +5 -0
  134. just_bash/commands/tr/tr.py +297 -0
  135. just_bash/commands/tree/__init__.py +5 -0
  136. just_bash/commands/tree/tree.py +139 -0
  137. just_bash/commands/true/__init__.py +5 -0
  138. just_bash/commands/true/true.py +32 -0
  139. just_bash/commands/uniq/__init__.py +5 -0
  140. just_bash/commands/uniq/uniq.py +323 -0
  141. just_bash/commands/wc/__init__.py +5 -0
  142. just_bash/commands/wc/wc.py +169 -0
  143. just_bash/commands/which/__init__.py +5 -0
  144. just_bash/commands/which/which.py +52 -0
  145. just_bash/commands/xan/__init__.py +5 -0
  146. just_bash/commands/xan/xan.py +1663 -0
  147. just_bash/commands/xargs/__init__.py +5 -0
  148. just_bash/commands/xargs/xargs.py +136 -0
  149. just_bash/commands/yq/__init__.py +5 -0
  150. just_bash/commands/yq/yq.py +848 -0
  151. just_bash/fs/__init__.py +29 -0
  152. just_bash/fs/in_memory_fs.py +621 -0
  153. just_bash/fs/mountable_fs.py +504 -0
  154. just_bash/fs/overlay_fs.py +894 -0
  155. just_bash/fs/read_write_fs.py +455 -0
  156. just_bash/interpreter/__init__.py +37 -0
  157. just_bash/interpreter/builtins/__init__.py +92 -0
  158. just_bash/interpreter/builtins/alias.py +154 -0
  159. just_bash/interpreter/builtins/cd.py +76 -0
  160. just_bash/interpreter/builtins/control.py +127 -0
  161. just_bash/interpreter/builtins/declare.py +336 -0
  162. just_bash/interpreter/builtins/export.py +56 -0
  163. just_bash/interpreter/builtins/let.py +44 -0
  164. just_bash/interpreter/builtins/local.py +57 -0
  165. just_bash/interpreter/builtins/mapfile.py +152 -0
  166. just_bash/interpreter/builtins/misc.py +378 -0
  167. just_bash/interpreter/builtins/readonly.py +80 -0
  168. just_bash/interpreter/builtins/set.py +234 -0
  169. just_bash/interpreter/builtins/shopt.py +201 -0
  170. just_bash/interpreter/builtins/source.py +136 -0
  171. just_bash/interpreter/builtins/test.py +290 -0
  172. just_bash/interpreter/builtins/unset.py +53 -0
  173. just_bash/interpreter/conditionals.py +387 -0
  174. just_bash/interpreter/control_flow.py +381 -0
  175. just_bash/interpreter/errors.py +116 -0
  176. just_bash/interpreter/expansion.py +1156 -0
  177. just_bash/interpreter/interpreter.py +813 -0
  178. just_bash/interpreter/types.py +134 -0
  179. just_bash/network/__init__.py +1 -0
  180. just_bash/parser/__init__.py +39 -0
  181. just_bash/parser/lexer.py +948 -0
  182. just_bash/parser/parser.py +2162 -0
  183. just_bash/py.typed +0 -0
  184. just_bash/query_engine/__init__.py +83 -0
  185. just_bash/query_engine/builtins/__init__.py +1283 -0
  186. just_bash/query_engine/evaluator.py +578 -0
  187. just_bash/query_engine/parser.py +525 -0
  188. just_bash/query_engine/tokenizer.py +329 -0
  189. just_bash/query_engine/types.py +373 -0
  190. just_bash/types.py +180 -0
  191. just_bash-0.1.5.dist-info/METADATA +410 -0
  192. just_bash-0.1.5.dist-info/RECORD +193 -0
  193. just_bash-0.1.5.dist-info/WHEEL +4 -0
@@ -0,0 +1,274 @@
1
+ """File command implementation - determine file type."""
2
+
3
+ from ...types import CommandContext, ExecResult
4
+
5
+
6
+ class FileCommand:
7
+ """The file command - determine file type."""
8
+
9
+ name = "file"
10
+
11
+ # Magic bytes for common file types (ordered by specificity - longer prefixes first)
12
+ MAGIC_BYTES: list[tuple[bytes, str]] = [
13
+ # Images
14
+ (b"\x89PNG\r\n\x1a\n", "PNG image data"),
15
+ (b"GIF87a", "GIF image data, version 87a"),
16
+ (b"GIF89a", "GIF image data, version 89a"),
17
+ (b"\xff\xd8\xff", "JPEG image data"),
18
+ (b"RIFF", "RIFF data"),
19
+ (b"BM", "PC bitmap"),
20
+ (b"\x00\x00\x01\x00", "MS Windows icon resource"),
21
+ (b"\x00\x00\x02\x00", "MS Windows cursor resource"),
22
+
23
+ # Archives
24
+ (b"PK\x03\x04", "Zip archive data"),
25
+ (b"PK\x05\x06", "Zip archive data (empty)"),
26
+ (b"Rar!\x1a\x07", "RAR archive data"),
27
+ (b"7z\xbc\xaf\x27\x1c", "7-zip archive data"),
28
+
29
+ # Compressed
30
+ (b"\x1f\x8b", "gzip compressed data"),
31
+ (b"BZh", "bzip2 compressed data"),
32
+ (b"\xfd7zXZ\x00", "XZ compressed data"),
33
+
34
+ # Documents
35
+ (b"%PDF", "PDF document"),
36
+
37
+ # Executables
38
+ (b"\x7fELF", "ELF"),
39
+ (b"MZ", "DOS/Windows executable"),
40
+ (b"\xca\xfe\xba\xbe", "Mach-O universal binary"),
41
+ (b"\xfe\xed\xfa\xce", "Mach-O 32-bit executable"),
42
+ (b"\xfe\xed\xfa\xcf", "Mach-O 64-bit executable"),
43
+ (b"\xcf\xfa\xed\xfe", "Mach-O 64-bit executable"),
44
+ (b"\xce\xfa\xed\xfe", "Mach-O 32-bit executable"),
45
+
46
+ # Databases
47
+ (b"SQLite format 3", "SQLite 3.x database"),
48
+
49
+ # Audio/Video
50
+ (b"ID3", "Audio file with ID3 tag"),
51
+ (b"\xff\xfb", "MPEG ADTS, layer III (MP3)"),
52
+ (b"\xff\xfa", "MPEG ADTS, layer III (MP3)"),
53
+ (b"OggS", "Ogg data"),
54
+ (b"fLaC", "FLAC audio"),
55
+
56
+ # Web/Data
57
+ (b"<!DOCTYPE html", "HTML document"),
58
+ (b"<!doctype html", "HTML document"),
59
+ (b"<html", "HTML document"),
60
+ (b"<?xml", "XML document"),
61
+ ]
62
+
63
+ MIME_TYPES = {
64
+ "PNG image data": "image/png",
65
+ "GIF image data, version 87a": "image/gif",
66
+ "GIF image data, version 89a": "image/gif",
67
+ "GIF image data": "image/gif",
68
+ "JPEG image data": "image/jpeg",
69
+ "Zip archive data": "application/zip",
70
+ "Zip archive data (empty)": "application/zip",
71
+ "PDF document": "application/pdf",
72
+ "gzip compressed data": "application/gzip",
73
+ "bzip2 compressed data": "application/x-bzip2",
74
+ "ASCII text": "text/plain",
75
+ "directory": "inode/directory",
76
+ "empty": "inode/x-empty",
77
+ "JSON text data": "application/json",
78
+ "ELF": "application/x-executable",
79
+ "Mach-O 64-bit executable": "application/x-mach-binary",
80
+ "Mach-O 32-bit executable": "application/x-mach-binary",
81
+ "Mach-O universal binary": "application/x-mach-binary",
82
+ "SQLite 3.x database": "application/x-sqlite3",
83
+ "XML document": "text/xml",
84
+ "HTML document": "text/html",
85
+ }
86
+
87
+ # Extension-based detection
88
+ EXTENSION_MAP: dict[str, tuple[str, str]] = {
89
+ # Programming languages
90
+ ".py": ("Python script", "text/x-python"),
91
+ ".js": ("JavaScript source", "text/javascript"),
92
+ ".ts": ("TypeScript source", "text/typescript"),
93
+ ".jsx": ("JavaScript JSX source", "text/jsx"),
94
+ ".tsx": ("TypeScript JSX source", "text/tsx"),
95
+ ".rb": ("Ruby script", "text/x-ruby"),
96
+ ".go": ("Go source", "text/x-go"),
97
+ ".rs": ("Rust source", "text/x-rust"),
98
+ ".c": ("C source", "text/x-c"),
99
+ ".cpp": ("C++ source", "text/x-c++"),
100
+ ".h": ("C header", "text/x-c"),
101
+ ".java": ("Java source", "text/x-java"),
102
+ ".kt": ("Kotlin source", "text/x-kotlin"),
103
+ ".swift": ("Swift source", "text/x-swift"),
104
+ ".php": ("PHP script", "text/x-php"),
105
+ ".pl": ("Perl script", "text/x-perl"),
106
+ ".sh": ("Bourne-Again shell script", "text/x-shellscript"),
107
+ ".bash": ("Bourne-Again shell script", "text/x-shellscript"),
108
+ ".zsh": ("Zsh script", "text/x-shellscript"),
109
+
110
+ # Data formats
111
+ ".json": ("JSON text data", "application/json"),
112
+ ".yaml": ("YAML document", "text/yaml"),
113
+ ".yml": ("YAML document", "text/yaml"),
114
+ ".xml": ("XML document", "text/xml"),
115
+ ".csv": ("CSV text", "text/csv"),
116
+ ".toml": ("TOML document", "text/toml"),
117
+
118
+ # Documentation
119
+ ".md": ("Markdown document", "text/markdown"),
120
+ ".rst": ("reStructuredText document", "text/x-rst"),
121
+ ".txt": ("ASCII text", "text/plain"),
122
+
123
+ # Config
124
+ ".ini": ("INI configuration", "text/plain"),
125
+ ".conf": ("Configuration file", "text/plain"),
126
+ ".cfg": ("Configuration file", "text/plain"),
127
+ ".env": ("Environment file", "text/plain"),
128
+
129
+ # Web
130
+ ".html": ("HTML document", "text/html"),
131
+ ".htm": ("HTML document", "text/html"),
132
+ ".css": ("CSS stylesheet", "text/css"),
133
+ ".scss": ("Sass stylesheet", "text/x-scss"),
134
+ ".less": ("Less stylesheet", "text/x-less"),
135
+ ".svg": ("SVG image", "image/svg+xml"),
136
+ }
137
+
138
+ # Shebang interpreter detection
139
+ SHEBANG_MAP = {
140
+ "python": "Python script",
141
+ "python3": "Python script",
142
+ "python2": "Python script",
143
+ "node": "Node.js script",
144
+ "nodejs": "Node.js script",
145
+ "bash": "Bourne-Again shell script",
146
+ "sh": "POSIX shell script",
147
+ "zsh": "Zsh script",
148
+ "ruby": "Ruby script",
149
+ "perl": "Perl script",
150
+ "php": "PHP script",
151
+ }
152
+
153
+ async def execute(self, args: list[str], ctx: CommandContext) -> ExecResult:
154
+ """Execute the file command."""
155
+ mime_mode = False
156
+ brief_mode = False
157
+ paths: list[str] = []
158
+
159
+ i = 0
160
+ while i < len(args):
161
+ arg = args[i]
162
+ if arg in ("-i", "--mime"):
163
+ mime_mode = True
164
+ elif arg in ("-b", "--brief"):
165
+ brief_mode = True
166
+ elif arg == "--help":
167
+ return ExecResult(
168
+ stdout="Usage: file [OPTION...] [FILE...]\n",
169
+ stderr="",
170
+ exit_code=0,
171
+ )
172
+ elif arg.startswith("-"):
173
+ pass # Ignore unknown options
174
+ else:
175
+ paths.append(arg)
176
+ i += 1
177
+
178
+ if not paths:
179
+ return ExecResult(
180
+ stdout="",
181
+ stderr="file: missing file operand\n",
182
+ exit_code=1,
183
+ )
184
+
185
+ output_lines = []
186
+ exit_code = 0
187
+
188
+ for path in paths:
189
+ try:
190
+ resolved = ctx.fs.resolve_path(ctx.cwd, path)
191
+ stat = await ctx.fs.stat(resolved)
192
+
193
+ if stat.is_directory:
194
+ file_type = "directory"
195
+ else:
196
+ content = await ctx.fs.read_file(resolved)
197
+ # Check for empty file
198
+ if len(content) == 0:
199
+ file_type = "empty"
200
+ else:
201
+ file_type = self._detect_type(path, content)
202
+
203
+ if mime_mode:
204
+ mime = self.MIME_TYPES.get(file_type, "application/octet-stream")
205
+ if file_type == "ASCII text":
206
+ mime += "; charset=us-ascii"
207
+ result = mime
208
+ else:
209
+ result = file_type
210
+
211
+ if brief_mode:
212
+ output_lines.append(result)
213
+ else:
214
+ output_lines.append(f"{path}: {result}")
215
+
216
+ except FileNotFoundError:
217
+ output_lines.append(f"{path}: cannot open (No such file or directory)")
218
+ exit_code = 1
219
+ except Exception as e:
220
+ output_lines.append(f"{path}: cannot open ({e})")
221
+ exit_code = 1
222
+
223
+ return ExecResult(
224
+ stdout="\n".join(output_lines) + "\n",
225
+ stderr="",
226
+ exit_code=exit_code,
227
+ )
228
+
229
+ def _detect_type(self, path: str, content: str) -> str:
230
+ """Detect file type from content."""
231
+ # Try binary detection first (magic bytes)
232
+ try:
233
+ content_bytes = content.encode("latin-1")
234
+
235
+ for magic, file_type in self.MAGIC_BYTES:
236
+ if content_bytes.startswith(magic):
237
+ return file_type
238
+ except Exception:
239
+ pass
240
+
241
+ # Check for shebang
242
+ if content.startswith("#!"):
243
+ first_line = content.split("\n")[0]
244
+ # Parse the interpreter from shebang
245
+ shebang = first_line[2:].strip()
246
+ parts = shebang.split()
247
+ if parts:
248
+ # Handle /usr/bin/env <interpreter>
249
+ interpreter = parts[0].rsplit("/", 1)[-1]
250
+ if interpreter == "env" and len(parts) > 1:
251
+ interpreter = parts[1].rsplit("/", 1)[-1]
252
+
253
+ # Check against SHEBANG_MAP
254
+ for key, script_type in self.SHEBANG_MAP.items():
255
+ if interpreter.startswith(key):
256
+ return f"{script_type}, ASCII text executable"
257
+
258
+ # Fallback for unknown interpreters
259
+ return "script, ASCII text executable"
260
+
261
+ # Check extension using EXTENSION_MAP
262
+ if "." in path:
263
+ ext = "." + path.rsplit(".", 1)[-1].lower()
264
+ if ext in self.EXTENSION_MAP:
265
+ return self.EXTENSION_MAP[ext][0]
266
+
267
+ # Check for text
268
+ try:
269
+ content.encode("ascii")
270
+ if "\r\n" in content:
271
+ return "ASCII text, with CRLF line terminators"
272
+ return "ASCII text"
273
+ except UnicodeEncodeError:
274
+ return "UTF-8 Unicode text"
@@ -0,0 +1,5 @@
1
+ """Find command implementation."""
2
+
3
+ from .find import FindCommand
4
+
5
+ __all__ = ["FindCommand"]