npcsh 1.1.12__py3-none-any.whl → 1.1.14__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 (99) hide show
  1. npcsh/_state.py +700 -377
  2. npcsh/alicanto.py +54 -1153
  3. npcsh/completion.py +206 -0
  4. npcsh/config.py +163 -0
  5. npcsh/corca.py +35 -1462
  6. npcsh/execution.py +185 -0
  7. npcsh/guac.py +31 -1986
  8. npcsh/npc_team/jinxs/code/sh.jinx +11 -15
  9. npcsh/npc_team/jinxs/modes/alicanto.jinx +186 -80
  10. npcsh/npc_team/jinxs/modes/corca.jinx +243 -22
  11. npcsh/npc_team/jinxs/modes/guac.jinx +313 -42
  12. npcsh/npc_team/jinxs/modes/plonk.jinx +209 -48
  13. npcsh/npc_team/jinxs/modes/pti.jinx +167 -25
  14. npcsh/npc_team/jinxs/modes/spool.jinx +158 -37
  15. npcsh/npc_team/jinxs/modes/wander.jinx +179 -74
  16. npcsh/npc_team/jinxs/modes/yap.jinx +258 -21
  17. npcsh/npc_team/jinxs/utils/chat.jinx +39 -12
  18. npcsh/npc_team/jinxs/utils/cmd.jinx +44 -0
  19. npcsh/npc_team/jinxs/utils/search.jinx +3 -3
  20. npcsh/npc_team/jinxs/utils/usage.jinx +33 -0
  21. npcsh/npcsh.py +76 -20
  22. npcsh/parsing.py +118 -0
  23. npcsh/plonk.py +41 -329
  24. npcsh/pti.py +41 -201
  25. npcsh/spool.py +34 -239
  26. npcsh/ui.py +199 -0
  27. npcsh/wander.py +54 -542
  28. npcsh/yap.py +38 -570
  29. npcsh-1.1.14.data/data/npcsh/npc_team/alicanto.jinx +194 -0
  30. npcsh-1.1.14.data/data/npcsh/npc_team/chat.jinx +44 -0
  31. npcsh-1.1.14.data/data/npcsh/npc_team/cmd.jinx +44 -0
  32. npcsh-1.1.14.data/data/npcsh/npc_team/corca.jinx +249 -0
  33. npcsh-1.1.14.data/data/npcsh/npc_team/guac.jinx +317 -0
  34. npcsh-1.1.14.data/data/npcsh/npc_team/plonk.jinx +214 -0
  35. npcsh-1.1.14.data/data/npcsh/npc_team/pti.jinx +170 -0
  36. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/search.jinx +3 -3
  37. npcsh-1.1.14.data/data/npcsh/npc_team/sh.jinx +34 -0
  38. npcsh-1.1.14.data/data/npcsh/npc_team/spool.jinx +161 -0
  39. npcsh-1.1.14.data/data/npcsh/npc_team/usage.jinx +33 -0
  40. npcsh-1.1.14.data/data/npcsh/npc_team/wander.jinx +186 -0
  41. npcsh-1.1.14.data/data/npcsh/npc_team/yap.jinx +262 -0
  42. {npcsh-1.1.12.dist-info → npcsh-1.1.14.dist-info}/METADATA +1 -1
  43. npcsh-1.1.14.dist-info/RECORD +135 -0
  44. npcsh-1.1.12.data/data/npcsh/npc_team/alicanto.jinx +0 -88
  45. npcsh-1.1.12.data/data/npcsh/npc_team/chat.jinx +0 -17
  46. npcsh-1.1.12.data/data/npcsh/npc_team/corca.jinx +0 -28
  47. npcsh-1.1.12.data/data/npcsh/npc_team/guac.jinx +0 -46
  48. npcsh-1.1.12.data/data/npcsh/npc_team/plonk.jinx +0 -53
  49. npcsh-1.1.12.data/data/npcsh/npc_team/pti.jinx +0 -28
  50. npcsh-1.1.12.data/data/npcsh/npc_team/sh.jinx +0 -38
  51. npcsh-1.1.12.data/data/npcsh/npc_team/spool.jinx +0 -40
  52. npcsh-1.1.12.data/data/npcsh/npc_team/wander.jinx +0 -81
  53. npcsh-1.1.12.data/data/npcsh/npc_team/yap.jinx +0 -25
  54. npcsh-1.1.12.dist-info/RECORD +0 -126
  55. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/agent.jinx +0 -0
  56. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/alicanto.npc +0 -0
  57. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/alicanto.png +0 -0
  58. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/build.jinx +0 -0
  59. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/compile.jinx +0 -0
  60. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/compress.jinx +0 -0
  61. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/corca.npc +0 -0
  62. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/corca.png +0 -0
  63. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/corca_example.png +0 -0
  64. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/edit_file.jinx +0 -0
  65. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/foreman.npc +0 -0
  66. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/frederic.npc +0 -0
  67. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/frederic4.png +0 -0
  68. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/guac.png +0 -0
  69. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/help.jinx +0 -0
  70. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/init.jinx +0 -0
  71. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/jinxs.jinx +0 -0
  72. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
  73. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  74. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/load_file.jinx +0 -0
  75. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/npc-studio.jinx +0 -0
  76. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
  77. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  78. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/ots.jinx +0 -0
  79. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/plonk.npc +0 -0
  80. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/plonk.png +0 -0
  81. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
  82. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  83. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/python.jinx +0 -0
  84. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/roll.jinx +0 -0
  85. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/sample.jinx +0 -0
  86. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/serve.jinx +0 -0
  87. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/set.jinx +0 -0
  88. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/sibiji.npc +0 -0
  89. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/sibiji.png +0 -0
  90. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/sleep.jinx +0 -0
  91. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/spool.png +0 -0
  92. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/sql.jinx +0 -0
  93. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/trigger.jinx +0 -0
  94. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/vixynt.jinx +0 -0
  95. {npcsh-1.1.12.data → npcsh-1.1.14.data}/data/npcsh/npc_team/yap.png +0 -0
  96. {npcsh-1.1.12.dist-info → npcsh-1.1.14.dist-info}/WHEEL +0 -0
  97. {npcsh-1.1.12.dist-info → npcsh-1.1.14.dist-info}/entry_points.txt +0 -0
  98. {npcsh-1.1.12.dist-info → npcsh-1.1.14.dist-info}/licenses/LICENSE +0 -0
  99. {npcsh-1.1.12.dist-info → npcsh-1.1.14.dist-info}/top_level.txt +0 -0
npcsh/execution.py ADDED
@@ -0,0 +1,185 @@
1
+ """
2
+ Command execution utilities for npcsh
3
+ """
4
+ import os
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ from typing import List, Tuple, Any, Optional
9
+
10
+ from termcolor import colored
11
+
12
+
13
+ # Commands that require interactive terminal handling
14
+ TERMINAL_EDITORS = ['vim', 'nvim', 'nano', 'vi', 'emacs', 'less', 'more', 'man']
15
+
16
+ # Interactive commands that need special handling (command -> args)
17
+ INTERACTIVE_COMMANDS = {
18
+ 'ipython': ['ipython'],
19
+ 'python': ['python', '-i'],
20
+ 'python3': ['python3', '-i'],
21
+ 'node': ['node'],
22
+ 'irb': ['irb'],
23
+ 'ghci': ['ghci'],
24
+ 'mysql': ['mysql'],
25
+ 'psql': ['psql'],
26
+ 'sqlite3': ['sqlite3'],
27
+ 'redis-cli': ['redis-cli'],
28
+ 'mongo': ['mongo'],
29
+ 'ssh': ['ssh'],
30
+ 'telnet': ['telnet'],
31
+ 'ftp': ['ftp'],
32
+ 'sftp': ['sftp'],
33
+ 'top': ['top'],
34
+ 'htop': ['htop'],
35
+ 'watch': ['watch'],
36
+ 'r': ['R', '--interactive'],
37
+ }
38
+
39
+
40
+ def validate_bash_command(command_parts: List[str]) -> bool:
41
+ """
42
+ Check if the command is a valid bash command.
43
+
44
+ Returns True if the command exists in PATH or is a shell builtin.
45
+ """
46
+ if not command_parts:
47
+ return False
48
+
49
+ cmd = command_parts[0]
50
+
51
+ # Check shell builtins
52
+ builtins = {'cd', 'pwd', 'echo', 'export', 'source', 'alias', 'unalias',
53
+ 'history', 'set', 'unset', 'read', 'eval', 'exec', 'exit',
54
+ 'return', 'shift', 'trap', 'wait', 'jobs', 'fg', 'bg',
55
+ 'kill', 'ulimit', 'umask', 'type', 'hash', 'true', 'false'}
56
+
57
+ if cmd in builtins:
58
+ return True
59
+
60
+ # Check if command exists in PATH
61
+ return shutil.which(cmd) is not None
62
+
63
+
64
+ def handle_bash_command(
65
+ cmd_parts: List[str],
66
+ full_cmd: str,
67
+ stdin_input: Optional[str],
68
+ state: Any
69
+ ) -> Tuple[bool, str]:
70
+ """
71
+ Execute a bash command and return the result.
72
+
73
+ Args:
74
+ cmd_parts: Parsed command parts
75
+ full_cmd: Full command string
76
+ stdin_input: Input to pipe to command
77
+ state: Shell state
78
+
79
+ Returns:
80
+ Tuple of (success, output)
81
+ """
82
+ try:
83
+ result = subprocess.run(
84
+ full_cmd,
85
+ shell=True,
86
+ capture_output=True,
87
+ text=True,
88
+ cwd=state.current_path,
89
+ input=stdin_input,
90
+ timeout=300
91
+ )
92
+
93
+ if result.returncode == 0:
94
+ output = result.stdout
95
+ if result.stderr:
96
+ output += f"\n{result.stderr}"
97
+ return True, output.strip()
98
+ else:
99
+ error = result.stderr or result.stdout or f"Command exited with code {result.returncode}"
100
+ return False, error.strip()
101
+
102
+ except subprocess.TimeoutExpired:
103
+ return False, "Command timed out after 5 minutes"
104
+ except Exception as e:
105
+ return False, str(e)
106
+
107
+
108
+ def open_terminal_editor(command: str) -> str:
109
+ """Open a terminal editor command interactively"""
110
+ try:
111
+ subprocess.run(command, shell=True)
112
+ return "Editor session completed"
113
+ except Exception as e:
114
+ return f"Editor error: {e}"
115
+
116
+
117
+ def handle_cd_command(cmd_parts: List[str], state: Any) -> Tuple[Any, str]:
118
+ """Handle the cd command"""
119
+ if len(cmd_parts) < 2:
120
+ new_path = os.path.expanduser("~")
121
+ else:
122
+ new_path = os.path.expanduser(cmd_parts[1])
123
+
124
+ if not os.path.isabs(new_path):
125
+ new_path = os.path.join(state.current_path, new_path)
126
+
127
+ new_path = os.path.normpath(new_path)
128
+
129
+ if os.path.isdir(new_path):
130
+ state.current_path = new_path
131
+ os.chdir(new_path)
132
+ return state, f"Changed to: {new_path}"
133
+ else:
134
+ return state, colored(f"Directory not found: {new_path}", "red")
135
+
136
+
137
+ def handle_interactive_command(cmd_parts: List[str], state: Any) -> Tuple[Any, str]:
138
+ """Handle interactive commands by running them in a subprocess"""
139
+ command = ' '.join(cmd_parts)
140
+ try:
141
+ subprocess.run(command, shell=True, cwd=state.current_path)
142
+ return state, f"Interactive session ({cmd_parts[0]}) completed"
143
+ except KeyboardInterrupt:
144
+ return state, colored("Session interrupted", "yellow")
145
+ except Exception as e:
146
+ return state, colored(f"Error: {e}", "red")
147
+
148
+
149
+ def start_interactive_session(command: str) -> int:
150
+ """Start an interactive shell session"""
151
+ try:
152
+ return subprocess.call(command, shell=True)
153
+ except Exception as e:
154
+ print(colored(f"Error starting session: {e}", "red"))
155
+ return 1
156
+
157
+
158
+ def list_directory(args: List[str]) -> None:
159
+ """List directory contents with formatting"""
160
+ path = args[0] if args else "."
161
+ path = os.path.expanduser(path)
162
+
163
+ if not os.path.exists(path):
164
+ print(colored(f"Path not found: {path}", "red"))
165
+ return
166
+
167
+ if os.path.isfile(path):
168
+ print(path)
169
+ return
170
+
171
+ try:
172
+ entries = os.listdir(path)
173
+ entries.sort()
174
+
175
+ for entry in entries:
176
+ full_path = os.path.join(path, entry)
177
+ if os.path.isdir(full_path):
178
+ print(colored(entry + "/", "blue", attrs=["bold"]))
179
+ elif os.access(full_path, os.X_OK):
180
+ print(colored(entry, "green", attrs=["bold"]))
181
+ else:
182
+ print(entry)
183
+
184
+ except PermissionError:
185
+ print(colored(f"Permission denied: {path}", "red"))