kash-shell 0.3.28__py3-none-any.whl → 0.3.30__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.
- kash/actions/core/markdownify_html.py +1 -4
- kash/actions/core/minify_html.py +4 -5
- kash/actions/core/render_as_html.py +9 -7
- kash/actions/core/save_sidematter_meta.py +47 -0
- kash/actions/core/zip_sidematter.py +47 -0
- kash/commands/base/basic_file_commands.py +7 -4
- kash/commands/base/diff_commands.py +6 -4
- kash/commands/base/files_command.py +31 -30
- kash/commands/base/general_commands.py +3 -2
- kash/commands/base/logs_commands.py +6 -4
- kash/commands/base/reformat_command.py +3 -2
- kash/commands/base/search_command.py +4 -3
- kash/commands/base/show_command.py +9 -7
- kash/commands/help/assistant_commands.py +6 -4
- kash/commands/help/help_commands.py +7 -4
- kash/commands/workspace/selection_commands.py +18 -16
- kash/commands/workspace/workspace_commands.py +39 -26
- kash/config/setup.py +2 -27
- kash/docs/markdown/topics/a1_what_is_kash.md +26 -18
- kash/exec/action_decorators.py +2 -2
- kash/exec/action_exec.py +56 -50
- kash/exec/fetch_url_items.py +36 -9
- kash/exec/preconditions.py +2 -2
- kash/exec/resolve_args.py +4 -1
- kash/exec/runtime_settings.py +1 -0
- kash/file_storage/file_store.py +59 -23
- kash/file_storage/item_file_format.py +91 -26
- kash/help/help_types.py +1 -1
- kash/llm_utils/llms.py +6 -1
- kash/local_server/local_server_commands.py +2 -1
- kash/mcp/mcp_server_commands.py +3 -2
- kash/mcp/mcp_server_routes.py +1 -1
- kash/model/actions_model.py +31 -30
- kash/model/compound_actions_model.py +4 -3
- kash/model/exec_model.py +30 -3
- kash/model/items_model.py +114 -57
- kash/model/params_model.py +4 -4
- kash/shell/output/shell_output.py +1 -2
- kash/utils/file_formats/chat_format.py +7 -4
- kash/utils/file_utils/file_ext.py +1 -0
- kash/utils/file_utils/file_formats.py +4 -2
- kash/utils/file_utils/file_formats_model.py +12 -0
- kash/utils/text_handling/doc_normalization.py +1 -1
- kash/utils/text_handling/markdown_footnotes.py +224 -0
- kash/utils/text_handling/markdown_utils.py +532 -41
- kash/utils/text_handling/markdownify_utils.py +2 -1
- kash/web_gen/templates/components/tooltip_scripts.js.jinja +186 -1
- kash/web_gen/templates/components/youtube_popover_scripts.js.jinja +223 -0
- kash/web_gen/templates/components/youtube_popover_styles.css.jinja +150 -0
- kash/web_gen/templates/content_styles.css.jinja +53 -1
- kash/web_gen/templates/youtube_webpage.html.jinja +47 -0
- kash/web_gen/webpage_render.py +103 -0
- kash/workspaces/workspaces.py +0 -5
- kash/xonsh_custom/custom_shell.py +4 -3
- {kash_shell-0.3.28.dist-info → kash_shell-0.3.30.dist-info}/METADATA +33 -24
- {kash_shell-0.3.28.dist-info → kash_shell-0.3.30.dist-info}/RECORD +59 -54
- kash/llm_utils/llm_features.py +0 -72
- kash/web_gen/simple_webpage.py +0 -55
- {kash_shell-0.3.28.dist-info → kash_shell-0.3.30.dist-info}/WHEEL +0 -0
- {kash_shell-0.3.28.dist-info → kash_shell-0.3.30.dist-info}/entry_points.txt +0 -0
- {kash_shell-0.3.28.dist-info → kash_shell-0.3.30.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,7 +5,6 @@ from kash.exec import kash_action
|
|
|
5
5
|
from kash.exec.preconditions import has_html_body, is_url_resource
|
|
6
6
|
from kash.exec.runtime_settings import current_runtime_settings
|
|
7
7
|
from kash.model import Format, Item
|
|
8
|
-
from kash.model.items_model import ItemType
|
|
9
8
|
from kash.utils.text_handling.markdown_utils import first_heading
|
|
10
9
|
from kash.utils.text_handling.markdownify_utils import markdownify_custom
|
|
11
10
|
from kash.web_content.file_cache_utils import get_url_html
|
|
@@ -36,7 +35,5 @@ def markdownify_html(item: Item) -> Item:
|
|
|
36
35
|
# Insert a h1 at the top of the document
|
|
37
36
|
markdown_content = f"# {title}\n\n{markdown_content}"
|
|
38
37
|
|
|
39
|
-
output_item = item.derived_copy(
|
|
40
|
-
type=ItemType.doc, format=Format.markdown, body=markdown_content
|
|
41
|
-
)
|
|
38
|
+
output_item = item.derived_copy(format=Format.markdown, body=markdown_content)
|
|
42
39
|
return output_item
|
kash/actions/core/minify_html.py
CHANGED
|
@@ -14,13 +14,12 @@ from kash.workspaces.workspaces import current_ws
|
|
|
14
14
|
)
|
|
15
15
|
def minify_html(item: Item) -> Item:
|
|
16
16
|
"""
|
|
17
|
-
Minify an HTML item's content using [
|
|
18
|
-
|
|
17
|
+
Minify an HTML item's content using [tminify](https://github.com/jlevy/tminify).
|
|
19
18
|
Also supports Tailwind CSS v4 compilation and inlining, if any Tailwind
|
|
20
19
|
CSS v4 CDN script tags are found.
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
[minify-html](https://github.com/wilsonzlin/minify-html).
|
|
21
|
+
Tminify uses [html-minifier-terser](https://github.com/terser/html-minifier-terser).
|
|
22
|
+
This is a bit slower but more robust than [minify-html](https://github.com/wilsonzlin/minify-html).
|
|
24
23
|
"""
|
|
25
24
|
from tminify.main import tminify
|
|
26
25
|
|
|
@@ -31,7 +30,7 @@ def minify_html(item: Item) -> Item:
|
|
|
31
30
|
input_path = ws.base_dir / item.store_path
|
|
32
31
|
|
|
33
32
|
output_item = item.derived_copy(format=Format.html, body=None)
|
|
34
|
-
output_path = ws.
|
|
33
|
+
output_path = ws.assign_store_path(output_item)
|
|
35
34
|
|
|
36
35
|
tminify(input_path, output_path)
|
|
37
36
|
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
from kash.actions.core.tabbed_webpage_config import tabbed_webpage_config
|
|
2
2
|
from kash.actions.core.tabbed_webpage_generate import tabbed_webpage_generate
|
|
3
|
+
from kash.config.logger import get_logger
|
|
3
4
|
from kash.exec import kash_action
|
|
4
5
|
from kash.exec.preconditions import has_fullpage_html_body, has_html_body, has_simple_text_body
|
|
5
6
|
from kash.exec_model.args_model import ONE_OR_MORE_ARGS
|
|
6
7
|
from kash.model import ActionInput, ActionResult, Param
|
|
7
8
|
from kash.model.items_model import ItemType
|
|
8
9
|
from kash.utils.file_utils.file_formats_model import Format
|
|
9
|
-
from kash.web_gen.
|
|
10
|
+
from kash.web_gen.webpage_render import render_item_as_html
|
|
11
|
+
|
|
12
|
+
log = get_logger(__name__)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
@kash_action(
|
|
@@ -27,12 +30,11 @@ def render_as_html(input: ActionInput, no_title: bool = False) -> ActionResult:
|
|
|
27
30
|
"""
|
|
28
31
|
if len(input.items) == 1:
|
|
29
32
|
input_item = input.items[0]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
result_item = input_item
|
|
34
|
-
|
|
35
|
-
)
|
|
33
|
+
|
|
34
|
+
result_item = input_item.derived_copy(type=ItemType.export, format=Format.html)
|
|
35
|
+
|
|
36
|
+
result_item = render_item_as_html(input_item, result_item, add_title_h1=not no_title)
|
|
37
|
+
|
|
36
38
|
return ActionResult([result_item])
|
|
37
39
|
else:
|
|
38
40
|
config_result = tabbed_webpage_config(input)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from prettyfmt import fmt_lines
|
|
2
|
+
from sidematter_format import Sidematter
|
|
3
|
+
|
|
4
|
+
from kash.config.logger import get_logger
|
|
5
|
+
from kash.exec import kash_action
|
|
6
|
+
from kash.exec_model.args_model import ONE_OR_MORE_ARGS
|
|
7
|
+
from kash.model.actions_model import ActionInput, ActionResult
|
|
8
|
+
from kash.workspaces.workspaces import current_ws
|
|
9
|
+
|
|
10
|
+
log = get_logger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@kash_action(expected_args=ONE_OR_MORE_ARGS)
|
|
14
|
+
def save_sidematter_meta(input: ActionInput) -> ActionResult:
|
|
15
|
+
"""
|
|
16
|
+
Write the item's metadata as a [sidematter format](https://github.com/jlevy/sidematter-format)
|
|
17
|
+
as `.meta.yml` and `.meta.json` files.
|
|
18
|
+
|
|
19
|
+
If additional data items are provided, their data is merged into the primary item's metadata.
|
|
20
|
+
This is useful for link data etc.
|
|
21
|
+
"""
|
|
22
|
+
items = input.items
|
|
23
|
+
assert items
|
|
24
|
+
|
|
25
|
+
primary = items[0]
|
|
26
|
+
assert primary.store_path
|
|
27
|
+
|
|
28
|
+
ws = current_ws()
|
|
29
|
+
sm = Sidematter(ws.base_dir / primary.store_path)
|
|
30
|
+
|
|
31
|
+
metadata_dict = primary.metadata()
|
|
32
|
+
|
|
33
|
+
for item in items[1:]:
|
|
34
|
+
assert item.store_path
|
|
35
|
+
metadata_dict = metadata_dict | item.read_as_data()
|
|
36
|
+
|
|
37
|
+
# Write both JSON and YAML sidematter metadata
|
|
38
|
+
sm.write_meta(metadata_dict, formats="all", make_parents=True)
|
|
39
|
+
|
|
40
|
+
log.message(
|
|
41
|
+
"Wrote sidematter metadata:\n%s",
|
|
42
|
+
fmt_lines(
|
|
43
|
+
[sm.meta_json_path.relative_to(ws.base_dir), sm.meta_yaml_path.relative_to(ws.base_dir)]
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return ActionResult(items=[primary])
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import zipfile
|
|
2
|
+
|
|
3
|
+
from sidematter_format import Sidematter
|
|
4
|
+
|
|
5
|
+
from kash.config.logger import get_logger
|
|
6
|
+
from kash.exec import kash_action
|
|
7
|
+
from kash.model.items_model import Item, ItemType
|
|
8
|
+
from kash.utils.file_utils.file_formats_model import Format
|
|
9
|
+
from kash.workspaces.workspaces import current_ws
|
|
10
|
+
|
|
11
|
+
log = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@kash_action()
|
|
15
|
+
def zip_sidematter(item: Item) -> Item:
|
|
16
|
+
"""
|
|
17
|
+
Zip all contents of the item, its sidematter metadata and items.
|
|
18
|
+
"""
|
|
19
|
+
assert item.store_path
|
|
20
|
+
ws = current_ws()
|
|
21
|
+
sm = Sidematter(ws.base_dir / item.store_path)
|
|
22
|
+
|
|
23
|
+
base_dir = sm.primary.parent
|
|
24
|
+
|
|
25
|
+
# Collect all files to include; store paths relative to the primary's directory
|
|
26
|
+
files_to_zip: list[tuple] = []
|
|
27
|
+
|
|
28
|
+
files_to_zip.append((sm.primary, sm.primary.relative_to(base_dir)))
|
|
29
|
+
if sm.meta_json_path.exists():
|
|
30
|
+
files_to_zip.append((sm.meta_json_path, sm.meta_json_path.relative_to(base_dir)))
|
|
31
|
+
if sm.meta_yaml_path.exists():
|
|
32
|
+
files_to_zip.append((sm.meta_yaml_path, sm.meta_yaml_path.relative_to(base_dir)))
|
|
33
|
+
if sm.assets_dir.exists():
|
|
34
|
+
for p in sm.assets_dir.rglob("*"):
|
|
35
|
+
if p.is_file():
|
|
36
|
+
files_to_zip.append((p, p.relative_to(base_dir)))
|
|
37
|
+
|
|
38
|
+
output_item = item.derived_copy(type=ItemType.export, format=Format.zip)
|
|
39
|
+
target = ws.assign_store_path(output_item)
|
|
40
|
+
|
|
41
|
+
with zipfile.ZipFile(
|
|
42
|
+
target, mode="w", compression=zipfile.ZIP_DEFLATED, compresslevel=9
|
|
43
|
+
) as zipf:
|
|
44
|
+
for path, arcname in files_to_zip:
|
|
45
|
+
zipf.write(path, arcname)
|
|
46
|
+
|
|
47
|
+
return output_item
|
|
@@ -33,7 +33,8 @@ def clipboard_copy(path: str | None = None, raw: bool = False) -> None:
|
|
|
33
33
|
Copy the contents of a file (or the first file in the selection) to the OS-native
|
|
34
34
|
clipboard. Similar to `pbcopy` on macOS.
|
|
35
35
|
|
|
36
|
-
:
|
|
36
|
+
Args:
|
|
37
|
+
raw: Copy the full exact contents of the file. Otherwise frontmatter is omitted.
|
|
37
38
|
"""
|
|
38
39
|
# TODO: Get this to work for images!
|
|
39
40
|
import pyperclip
|
|
@@ -95,7 +96,8 @@ def edit(path: str | None = None, all: bool = False) -> None:
|
|
|
95
96
|
"""
|
|
96
97
|
Edit the contents of a file using the user's default editor (or defaulting to nano).
|
|
97
98
|
|
|
98
|
-
:
|
|
99
|
+
Args:
|
|
100
|
+
all: Normally edits only the first file given. This passes all files to the editor.
|
|
99
101
|
"""
|
|
100
102
|
input_paths = assemble_path_args(path)
|
|
101
103
|
if not all:
|
|
@@ -111,8 +113,9 @@ def file_info(*paths: str, size_summary: bool = False, format: bool = False) ->
|
|
|
111
113
|
structure of the items at the given paths (for text documents) and the detected
|
|
112
114
|
mime type.
|
|
113
115
|
|
|
114
|
-
:
|
|
115
|
-
|
|
116
|
+
Args:
|
|
117
|
+
size_summary: Only show size summary (words, sentences, paragraphs for a text document).
|
|
118
|
+
format: Only show detected file format.
|
|
116
119
|
"""
|
|
117
120
|
if not size_summary and not format:
|
|
118
121
|
size_summary = format = True
|
|
@@ -57,8 +57,9 @@ def diff_items(*paths: str, force: bool = False) -> ShellResult:
|
|
|
57
57
|
as items themselves, so this works on items. Items are imported as usual into the
|
|
58
58
|
global workspace if they are not already in the store.
|
|
59
59
|
|
|
60
|
-
:
|
|
61
|
-
|
|
60
|
+
Args:
|
|
61
|
+
stat: Only show the diffstat summary.
|
|
62
|
+
force: If true, will run the diff even if the items are of different formats.
|
|
62
63
|
"""
|
|
63
64
|
ws = current_ws()
|
|
64
65
|
if len(paths) == 2:
|
|
@@ -90,8 +91,9 @@ def diff_files(*paths: str, diffstat: bool = False, save: bool = False) -> Shell
|
|
|
90
91
|
Show the unified diff between the given files. This works on any files, not
|
|
91
92
|
just items, so helpful for quick analysis without importing the files.
|
|
92
93
|
|
|
93
|
-
:
|
|
94
|
-
|
|
94
|
+
Args:
|
|
95
|
+
diffstat: Only show the diffstat summary.
|
|
96
|
+
save: Save the diff as an item in the store.
|
|
95
97
|
"""
|
|
96
98
|
if len(paths) == 2:
|
|
97
99
|
[path1, path2] = paths
|
|
@@ -111,36 +111,37 @@ def files(
|
|
|
111
111
|
with limited depth and breadth, and more control over recursion, sorting,
|
|
112
112
|
and grouping.
|
|
113
113
|
|
|
114
|
-
:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
114
|
+
Args:
|
|
115
|
+
overview: Recurse a couple levels and show files, but not too many.
|
|
116
|
+
Same as `--groupby=parent --depth=2 --max_per_group=100 --omit_dirs`
|
|
117
|
+
except also scales down `max_per_group` to 25 or 50 if there are many files.
|
|
118
|
+
recent: Only shows the most recently modified files in each directory.
|
|
119
|
+
Same as `--sort=modified --reverse --groupby=parent --max_per_group=100`
|
|
120
|
+
except also scales down `max_per_group` to 25 or 50 if there are many files.
|
|
121
|
+
recursive: List all files recursively. Same as `--depth=-1`.
|
|
122
|
+
flat: Show files in a flat list, rather than grouped by parent directory.
|
|
123
|
+
Same as `--groupby=flat`.
|
|
124
|
+
omit_dirs: Normally directories are included. This option omits them,
|
|
125
|
+
which is useful when recursing into subdirectories.
|
|
126
|
+
depth: Maximum depth to recurse into directories. -1 means no limit.
|
|
127
|
+
max_files: Maximum number of files to yield per input path.
|
|
128
|
+
-1 means no limit.
|
|
129
|
+
max_per_subdir: Maximum number of files to yield per subdirectory
|
|
130
|
+
(not including the top level). -1 means no limit.
|
|
131
|
+
max_per_group: Limit the first number of items displayed per group
|
|
132
|
+
(if groupby is used) or in total. 0 means show all.
|
|
133
|
+
no_max: Disable limits on depth and number of files. Same as
|
|
134
|
+
`--depth=-1 --max_files=-1 --max_per_subdir=-1 --max_per_group=-1`.
|
|
135
|
+
no_ignore: Disable ignoring hidden files.
|
|
136
|
+
all: Same as `--no_ignore --no_max`. Does not change `--depth`.
|
|
137
|
+
save: Save the listing as a CSV file item.
|
|
138
|
+
sort: Sort by `filename`, `size`, `accessed`, `created`, or `modified`.
|
|
139
|
+
reverse: Reverse the sorting order.
|
|
140
|
+
since: Filter files modified since a given time (e.g., '1 day', '2 hours').
|
|
141
|
+
groupby: Group results. Can be `flat` (no grouping, and by default implies
|
|
142
|
+
recursive), `parent`, or `suffix`. Defaults to 'parent'.
|
|
143
|
+
iso_time: Show time in ISO format (default is human-readable age).
|
|
144
|
+
pager: Use the pager when displaying the output.
|
|
144
145
|
"""
|
|
145
146
|
if global_settings().use_nerd_icons:
|
|
146
147
|
from kash.shell.file_icons.nerd_icons import icon_for_file
|
|
@@ -160,8 +160,9 @@ def check_system_tools(warn_only: bool = False, brief: bool = False) -> None:
|
|
|
160
160
|
"""
|
|
161
161
|
Check that all tools are installed.
|
|
162
162
|
|
|
163
|
-
:
|
|
164
|
-
|
|
163
|
+
Args:
|
|
164
|
+
warn_only: Only warn if tools are missing.
|
|
165
|
+
brief: Print summary as a single line.
|
|
165
166
|
"""
|
|
166
167
|
if warn_only:
|
|
167
168
|
pkg_check().warn_if_missing()
|
|
@@ -23,7 +23,8 @@ def logs(follow: bool = False) -> None:
|
|
|
23
23
|
"""
|
|
24
24
|
Page through the logs for the current workspace.
|
|
25
25
|
|
|
26
|
-
:
|
|
26
|
+
Args:
|
|
27
|
+
follow: Follow the file as it grows.
|
|
27
28
|
"""
|
|
28
29
|
tail_file(get_log_settings().log_file_path, follow=follow)
|
|
29
30
|
|
|
@@ -51,9 +52,10 @@ def log_level(level: str | None = None, console: bool = False, file: bool = Fals
|
|
|
51
52
|
"""
|
|
52
53
|
Set or show the log level. Applies to both console and file log levels unless specified.
|
|
53
54
|
|
|
54
|
-
:
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
Args:
|
|
56
|
+
level: The log level to set. If not specified, will show current level.
|
|
57
|
+
console: Set console log level only.
|
|
58
|
+
file: Set file log level only.
|
|
57
59
|
"""
|
|
58
60
|
if not console and not file:
|
|
59
61
|
console = True
|
|
@@ -22,8 +22,9 @@ def reformat(*paths: str, inplace: bool = False) -> ShellResult:
|
|
|
22
22
|
|
|
23
23
|
TODO: Also handle JSON and YAML.
|
|
24
24
|
|
|
25
|
-
:
|
|
26
|
-
|
|
25
|
+
Args:
|
|
26
|
+
inplace: Overwrite the original file. Otherwise save to a new
|
|
27
|
+
file with `_formatted` appended to the original name.
|
|
27
28
|
"""
|
|
28
29
|
resolved_paths = assemble_path_args(*paths)
|
|
29
30
|
final_paths = []
|
|
@@ -30,9 +30,10 @@ def search(
|
|
|
30
30
|
|
|
31
31
|
search "youtube.com" resources/ --sort=modified
|
|
32
32
|
|
|
33
|
-
:
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
Args:
|
|
34
|
+
sort: How to sort results. Can be `path` or `modified` or `created` (as with `rg`).
|
|
35
|
+
ignore_case: Ignore case when searching.
|
|
36
|
+
verbose: Also print the ripgrep command line.
|
|
36
37
|
"""
|
|
37
38
|
pkg_check().require("ripgrep")
|
|
38
39
|
from ripgrepy import RipGrepNotFound, Ripgrepy
|
|
@@ -30,12 +30,13 @@ def show(
|
|
|
30
30
|
Will use `bat` if available to show files in the console, including syntax
|
|
31
31
|
highlighting and git diffs.
|
|
32
32
|
|
|
33
|
-
:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
Args:
|
|
34
|
+
console: Force display to console (not browser or native apps).
|
|
35
|
+
native: Force display with a native app (depending on your system configuration).
|
|
36
|
+
thumbnail: If there is a thumbnail image, show it too.
|
|
37
|
+
browser: Force display with your default web browser.
|
|
38
|
+
plain: Use plain view in the console (this is `bat`'s `plain` style).
|
|
39
|
+
noselect: Disable default behavior where `show` also will `select` the file.
|
|
39
40
|
"""
|
|
40
41
|
view_mode = (
|
|
41
42
|
ViewMode.console
|
|
@@ -69,7 +70,8 @@ def show(
|
|
|
69
70
|
if not noselect:
|
|
70
71
|
from kash.commands.workspace.selection_commands import select
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
if isinstance(input_path, StorePath):
|
|
74
|
+
select(input_path)
|
|
73
75
|
return ShellResult(show_selection=True)
|
|
74
76
|
except (InvalidInput, InvalidState):
|
|
75
77
|
if path:
|
|
@@ -31,9 +31,10 @@ def assist(
|
|
|
31
31
|
Invoke the kash assistant. You don't normally need this command as it is the same as just
|
|
32
32
|
asking a question (a question ending with ?) on the kash console.
|
|
33
33
|
|
|
34
|
-
:
|
|
35
|
-
|
|
36
|
-
for the assistant
|
|
34
|
+
Args:
|
|
35
|
+
type: The type of assistance to use.
|
|
36
|
+
model: The model to use for the assistant. If not provided, the default model
|
|
37
|
+
for the assistant type is used.
|
|
37
38
|
"""
|
|
38
39
|
if not input:
|
|
39
40
|
input = input_simple_string(
|
|
@@ -81,7 +82,8 @@ def assistant_history(follow: bool = False) -> None:
|
|
|
81
82
|
"""
|
|
82
83
|
Show the assistant history for the current workspace.
|
|
83
84
|
|
|
84
|
-
:
|
|
85
|
+
Args:
|
|
86
|
+
follow: Follow the file as it grows.
|
|
85
87
|
"""
|
|
86
88
|
ws = current_ws()
|
|
87
89
|
tail_file(ws.base_dir / ws.dirs.assistant_history_yml, follow=follow)
|
|
@@ -37,8 +37,9 @@ def help(query: str | None = None, search: bool = False) -> None:
|
|
|
37
37
|
Note that if you want Python `help()` and not kash help, use the
|
|
38
38
|
alias `pyhelp`.
|
|
39
39
|
|
|
40
|
-
:
|
|
41
|
-
|
|
40
|
+
Args:
|
|
41
|
+
search: If true, does a simple search of help docs
|
|
42
|
+
(same as `search_help`).
|
|
42
43
|
"""
|
|
43
44
|
if not search and not query:
|
|
44
45
|
manual()
|
|
@@ -53,7 +54,8 @@ def commands(no_pager: bool = False, full: bool = False) -> None:
|
|
|
53
54
|
"""
|
|
54
55
|
Show help on all kash commands.
|
|
55
56
|
|
|
56
|
-
:
|
|
57
|
+
Args:
|
|
58
|
+
full: If true, show full help for each command.
|
|
57
59
|
"""
|
|
58
60
|
from kash.help.help_pages import print_builtin_commands_help
|
|
59
61
|
|
|
@@ -73,7 +75,8 @@ def actions(no_pager: bool = False, full: bool = False) -> None:
|
|
|
73
75
|
"""
|
|
74
76
|
Show help on the full list of currently loaded actions.
|
|
75
77
|
|
|
76
|
-
:
|
|
78
|
+
Args:
|
|
79
|
+
full: If true, show full help for each action.
|
|
77
80
|
"""
|
|
78
81
|
from kash.help.help_pages import print_actions_help
|
|
79
82
|
|
|
@@ -43,17 +43,18 @@ def select(
|
|
|
43
43
|
If any other flags are given, they show or modify the selection history.
|
|
44
44
|
They must be used individually (and without paths).
|
|
45
45
|
|
|
46
|
-
:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
Args:
|
|
47
|
+
history: Show the full selection history.
|
|
48
|
+
last: Show the last `last` selections in the history.
|
|
49
|
+
back: Move back in the selection history by `back` steps.
|
|
50
|
+
forward: Move forward in the selection history by `forward` steps.
|
|
51
|
+
previous: Move back in the selection history to the previous selection.
|
|
52
|
+
next: Move forward in the selection history to the next selection.
|
|
53
|
+
pop: Pop the current selection from the history.
|
|
54
|
+
clear_all: Clear the full selection history.
|
|
55
|
+
clear_future: Clear all selections from history after the current one.
|
|
56
|
+
refresh: Refresh the current selection to drop any paths that no longer exist.
|
|
57
|
+
no_check: Do not check if the paths exist.
|
|
57
58
|
"""
|
|
58
59
|
ws = current_ws()
|
|
59
60
|
|
|
@@ -182,11 +183,12 @@ def save(parent: str | None = None, to: str | None = None, no_frontmatter: bool
|
|
|
182
183
|
Save the current selection to the given directory, or to the current directory if no
|
|
183
184
|
target given.
|
|
184
185
|
|
|
185
|
-
:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
Args:
|
|
187
|
+
parent: The directory to save the files to. If not given, it will be the
|
|
188
|
+
current directory.
|
|
189
|
+
to: If only one file is selected, a name to save it as. If it exists, it will
|
|
190
|
+
overwrite (and make a backup).
|
|
191
|
+
no_frontmatter: If true, will not include YAML frontmatter in the output.
|
|
190
192
|
"""
|
|
191
193
|
ws = current_ws()
|
|
192
194
|
store_paths = ws.selections.current.paths
|
|
@@ -100,8 +100,9 @@ def cache_list(media: bool = False, content: bool = False, workspace: str | None
|
|
|
100
100
|
"""
|
|
101
101
|
List the contents of the workspace media and content caches. By default lists both caches.
|
|
102
102
|
|
|
103
|
-
:
|
|
104
|
-
|
|
103
|
+
Args:
|
|
104
|
+
media: List media cache only.
|
|
105
|
+
content: List content cache only.
|
|
105
106
|
"""
|
|
106
107
|
if not media and not content:
|
|
107
108
|
media = True
|
|
@@ -131,9 +132,10 @@ def clear_cache(media: bool = False, content: bool = False, workspace: str | Non
|
|
|
131
132
|
"""
|
|
132
133
|
Clear the media and content caches. By default clears both caches.
|
|
133
134
|
|
|
134
|
-
:
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
Args:
|
|
136
|
+
media: Clear media cache only.
|
|
137
|
+
content: Clear content cache only.
|
|
138
|
+
global_cache: If in a workspace, clear the global caches, not the workspace caches.
|
|
137
139
|
"""
|
|
138
140
|
if not media and not content:
|
|
139
141
|
media = True
|
|
@@ -193,8 +195,9 @@ def history(max: int = 30, raw: bool = False) -> None:
|
|
|
193
195
|
|
|
194
196
|
For xonsh's built-in history, use `xhistory`.
|
|
195
197
|
|
|
196
|
-
:
|
|
197
|
-
|
|
198
|
+
Args:
|
|
199
|
+
max: Show at most the last `max` commands.
|
|
200
|
+
raw: Show raw command history by tailing the history file directly.
|
|
198
201
|
"""
|
|
199
202
|
# TODO: Customize this by time frame.
|
|
200
203
|
ws = current_ws()
|
|
@@ -395,15 +398,21 @@ def params(full: bool = False) -> None:
|
|
|
395
398
|
|
|
396
399
|
@kash_command
|
|
397
400
|
def import_item(
|
|
398
|
-
*files_or_urls: str,
|
|
401
|
+
*files_or_urls: str,
|
|
402
|
+
type: ItemType | None = None,
|
|
403
|
+
inplace: bool = False,
|
|
404
|
+
with_sidematter: bool = False,
|
|
399
405
|
) -> ShellResult:
|
|
400
406
|
"""
|
|
401
407
|
Add a file or URL resource to the workspace as an item.
|
|
402
408
|
|
|
403
|
-
:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
409
|
+
Args:
|
|
410
|
+
inplace: If set and the item is already in the store, reimport the item,
|
|
411
|
+
adding or rewriting metadata frontmatter.
|
|
412
|
+
type: Change the item type. Usually items are auto-detected from the file
|
|
413
|
+
format (typically doc or resource), but you can override this with this option.
|
|
414
|
+
with_sidematter: If set, will copy any sidematter-format files (metadata/assets)
|
|
415
|
+
to the destination.
|
|
407
416
|
"""
|
|
408
417
|
if not files_or_urls:
|
|
409
418
|
raise InvalidInput("No files or URLs provided")
|
|
@@ -412,7 +421,9 @@ def import_item(
|
|
|
412
421
|
store_paths = []
|
|
413
422
|
|
|
414
423
|
locators = [resolve_locator_arg(r) for r in files_or_urls]
|
|
415
|
-
store_paths = ws.import_items(
|
|
424
|
+
store_paths = ws.import_items(
|
|
425
|
+
*locators, as_type=type, reimport=inplace, with_sidematter=with_sidematter
|
|
426
|
+
)
|
|
416
427
|
|
|
417
428
|
print_status(
|
|
418
429
|
"Imported %s %s:\n%s",
|
|
@@ -434,9 +445,10 @@ def save_clipboard(
|
|
|
434
445
|
"""
|
|
435
446
|
Import the contents of the OS-native clipboard as a new item in the workspace.
|
|
436
447
|
|
|
437
|
-
:
|
|
438
|
-
|
|
439
|
-
|
|
448
|
+
Args:
|
|
449
|
+
title: The title of the new item (default: "pasted_text").
|
|
450
|
+
type: The type of the new item (default: resource).
|
|
451
|
+
format: The format of the new item (default: plaintext).
|
|
440
452
|
"""
|
|
441
453
|
import pyperclip
|
|
442
454
|
|
|
@@ -537,8 +549,9 @@ def applicable_actions(*paths: str, brief: bool = False, all: bool = False) -> N
|
|
|
537
549
|
Show the actions that are applicable to the current selection.
|
|
538
550
|
This is a great command to use at any point to see what actions are available!
|
|
539
551
|
|
|
540
|
-
:
|
|
541
|
-
|
|
552
|
+
Args:
|
|
553
|
+
brief: Show only action names. Otherwise show actions and descriptions.
|
|
554
|
+
all: Include actions with no preconditions.
|
|
542
555
|
"""
|
|
543
556
|
store_paths = assemble_store_path_args(*paths)
|
|
544
557
|
ws = current_ws()
|
|
@@ -592,19 +605,19 @@ def applicable_actions(*paths: str, brief: bool = False, all: bool = False) -> N
|
|
|
592
605
|
|
|
593
606
|
|
|
594
607
|
@kash_command
|
|
595
|
-
def preconditions() -> None:
|
|
608
|
+
def preconditions(path: str | None = None) -> None:
|
|
596
609
|
"""
|
|
597
|
-
List all preconditions and if the current selection meets them.
|
|
610
|
+
List all preconditions and if the current selection or specified path meets them.
|
|
598
611
|
"""
|
|
599
612
|
|
|
600
613
|
ws = current_ws()
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
raise InvalidInput("No selection")
|
|
604
|
-
|
|
605
|
-
items = [ws.load(item) for item in selection]
|
|
614
|
+
input_paths = assemble_path_args(path)
|
|
615
|
+
items = [ws.load(item) for item in input_paths]
|
|
606
616
|
|
|
607
|
-
|
|
617
|
+
if path:
|
|
618
|
+
print_status("Precondition check for path:\n%s", fmt_lines([fmt_loc(path)]))
|
|
619
|
+
else:
|
|
620
|
+
print_status("Precondition check for selection:\n%s", fmt_lines(input_paths))
|
|
608
621
|
|
|
609
622
|
for precondition in get_all_preconditions().values():
|
|
610
623
|
satisfied = all(precondition(item) for item in items)
|