@andespindola/crow-term-linux-x64 0.0.0-bootstrap.1 → 0.1.0-alpha.5
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.
- package/LICENSE +55 -0
- package/NOTICE.md +25 -0
- package/README.md +5 -0
- package/THIRD_PARTY_LICENSES.txt +71128 -0
- package/assets/fonts/OFL.txt +96 -0
- package/assets/theme-license.txt +21 -0
- package/bin/crow-term +4 -0
- package/bin/shell/README.md +37 -0
- package/bin/shell/plugins.lock.json +63 -0
- package/bin/shell/setup.py +241 -0
- package/bin/shell/vendor/fisher/LICENSE.md +7 -0
- package/bin/shell/vendor/fisher/completions/fisher.fish +7 -0
- package/bin/shell/vendor/fisher/functions/fisher.fish +251 -0
- package/bin/shell/vendor/z/LICENSE +21 -0
- package/bin/shell/vendor/z/conf.d/z.fish +63 -0
- package/bin/shell/vendor/z/functions/__z.fish +178 -0
- package/bin/shell/vendor/z/functions/__z_add.fish +49 -0
- package/bin/shell/vendor/z/functions/__z_clean.fish +11 -0
- package/bin/shell/vendor/z/functions/__z_complete.fish +13 -0
- package/bin/shell/vendor/zsh-autosuggestions/LICENSE +23 -0
- package/bin/shell/vendor/zsh-autosuggestions/zsh-autosuggestions.zsh +867 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/.revision-hash +1 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/.version +1 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/COPYING.md +23 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/brackets/brackets-highlighter.zsh +107 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/cursor/cursor-highlighter.zsh +47 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/line/line-highlighter.zsh +44 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/main/main-highlighter.zsh +1853 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/pattern/pattern-highlighter.zsh +60 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/regexp/regexp-highlighter.zsh +62 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/highlighters/root/root-highlighter.zsh +44 -0
- package/bin/shell/vendor/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh +587 -0
- package/package.json +35 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Copyright 2015-2024 Belleve Invis (The Iosevka Project, https://github.com/be5invis/Iosevka)
|
|
2
|
+
Copyright 2026 The Crowquill Mono Project Authors (https://github.com/andersonflima/crowquill-mono)
|
|
3
|
+
|
|
4
|
+
Crowquill Mono is built from a custom build of Iosevka (a "Curly" ss20 variant
|
|
5
|
+
with handwritten forms, a cursive italic and a widened advance). The added
|
|
6
|
+
keyword-bold OpenType feature and the bold keyword glyph variants are original
|
|
7
|
+
to this work.
|
|
8
|
+
|
|
9
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
10
|
+
This license is copied below, and is also available with a FAQ at:
|
|
11
|
+
https://openfontlicense.org
|
|
12
|
+
|
|
13
|
+
-----------------------------------------------------------
|
|
14
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
15
|
+
-----------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
PREAMBLE
|
|
18
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
19
|
+
development of collaborative font projects, to support the font creation
|
|
20
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
21
|
+
open framework in which fonts may be shared and improved in partnership
|
|
22
|
+
with others.
|
|
23
|
+
|
|
24
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
25
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
26
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
27
|
+
redistributed and/or sold with any software provided that any reserved
|
|
28
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
29
|
+
however, cannot be released under any other type of license. The
|
|
30
|
+
requirement for fonts to remain under this license does not apply to any
|
|
31
|
+
document created using the fonts or their derivatives.
|
|
32
|
+
|
|
33
|
+
DEFINITIONS
|
|
34
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
35
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
36
|
+
include source files, build scripts and documentation.
|
|
37
|
+
|
|
38
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
39
|
+
copyright statement(s).
|
|
40
|
+
|
|
41
|
+
"Original Version" refers to the collection of Font Software components as
|
|
42
|
+
distributed by the Copyright Holder(s).
|
|
43
|
+
|
|
44
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
45
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
46
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
47
|
+
new environment.
|
|
48
|
+
|
|
49
|
+
"Author" refers to any designer, engineer, programmer, technical writer or
|
|
50
|
+
other person who contributed to the Font Software.
|
|
51
|
+
|
|
52
|
+
PERMISSION & CONDITIONS
|
|
53
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
54
|
+
copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
55
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
56
|
+
Software, subject to the following conditions:
|
|
57
|
+
|
|
58
|
+
1) Neither the Font Software nor any of its individual components, in
|
|
59
|
+
Original or Modified Versions, may be sold by itself.
|
|
60
|
+
|
|
61
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
62
|
+
redistributed and/or sold with any software, provided that each copy
|
|
63
|
+
contains the above copyright notice and this license. These can be
|
|
64
|
+
included either as stand-alone text files, human-readable headers or in
|
|
65
|
+
the appropriate machine-readable metadata fields within text or binary
|
|
66
|
+
files as long as those fields can be easily viewed by the user.
|
|
67
|
+
|
|
68
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
69
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
70
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
71
|
+
presented to the users.
|
|
72
|
+
|
|
73
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
74
|
+
Software shall not be used to promote, endorse or advertise any Modified
|
|
75
|
+
Version, except to acknowledge the contribution(s) of the Copyright
|
|
76
|
+
Holder(s) and the Author(s) or with their explicit written permission.
|
|
77
|
+
|
|
78
|
+
5) The Font Software, modified or unmodified, in part or in whole, must be
|
|
79
|
+
distributed entirely under this license, and must not be distributed under
|
|
80
|
+
any other license. The requirement for fonts to remain under this license
|
|
81
|
+
does not apply to any document created using the Font Software.
|
|
82
|
+
|
|
83
|
+
TERMINATION
|
|
84
|
+
This license becomes null and void if any of the above conditions are not
|
|
85
|
+
met.
|
|
86
|
+
|
|
87
|
+
DISCLAIMER
|
|
88
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
89
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
90
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
|
91
|
+
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
92
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
93
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
94
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
95
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
|
96
|
+
DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anderson Faustino Lima
|
|
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.
|
package/bin/crow-term
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Reproducible, opt-in shell profiles
|
|
2
|
+
|
|
3
|
+
Run `python3 shell/setup.py --help`. Requires Python 3.9+ on Unix/macOS/WSL.
|
|
4
|
+
Profiles are separate from personal startup files; installation and launching
|
|
5
|
+
are two explicit operations. Nothing calls `chsh`, a package manager, `curl|sh`,
|
|
6
|
+
`git clone`, Fisher, or a plugin's installer.
|
|
7
|
+
|
|
8
|
+
`vendor/` contains only the runtime source files and required license notices
|
|
9
|
+
listed in `plugins.lock.json`. The lock records official repository URLs,
|
|
10
|
+
immutable upstream commits, upstream archive SHA256 and every copied file's
|
|
11
|
+
SHA256. Files are unmodified, except that unrelated upstream files are omitted.
|
|
12
|
+
Setup verifies each selected vendored file before writing any target. No network
|
|
13
|
+
is used by setup, dry-run, or tests.
|
|
14
|
+
|
|
15
|
+
| Plugin | Upstream commit | License notice |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| [Fisher](https://github.com/jorgebucaran/fisher) | `791da644d33d392216f6b1a9b5fc1e470db6d7f2` | `vendor/fisher/LICENSE.md` (MIT) |
|
|
18
|
+
| [fish z](https://github.com/jethrokuan/z) | `26a50962bc68f5cb60fc488ee008b3d4d5be75f4` | `vendor/z/LICENSE` (MIT) |
|
|
19
|
+
| [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) | `85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc5` | `vendor/zsh-autosuggestions/LICENSE` (MIT) |
|
|
20
|
+
| [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) | `e6683f20e5c38d3e5447f45845d04ddda75d0f23` | `vendor/zsh-syntax-highlighting/COPYING.md` (BSD-3-Clause) |
|
|
21
|
+
|
|
22
|
+
These exact official archives were downloaded and hashed on 2026-10-28. This
|
|
23
|
+
is a reproducibility pin, not a promise that upstream code is vulnerability-free.
|
|
24
|
+
To update: review upstream changes and licenses, fetch a chosen immutable commit
|
|
25
|
+
from its official repository, replace only this allowlist and regenerate/review
|
|
26
|
+
the SHA256 entries together. Changing a digest alone to suppress an unexplained
|
|
27
|
+
mismatch is not a valid update. Profiles installed by an older lock are never
|
|
28
|
+
overwritten: choose a new versioned prefix or back up and manage them explicitly.
|
|
29
|
+
|
|
30
|
+
The fuller source setup declared Fisher, z, Shellder, Tide v5 and Catppuccin fish,
|
|
31
|
+
while invoking Starship. Crow Term intentionally chooses only Fisher + z, native
|
|
32
|
+
fish editing/completions and one small built-in monochrome prompt. It does not
|
|
33
|
+
stack competing prompt engines. The zsh choice is a new minimal portable profile,
|
|
34
|
+
not a claim that these plugins were discovered in the owner's `.zshrc`.
|
|
35
|
+
|
|
36
|
+
See [shell integration](../docs/shell-integration.md) for launch semantics,
|
|
37
|
+
platform limits and the boundary between a terminal and a shell.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"plugins": [
|
|
4
|
+
{
|
|
5
|
+
"name": "fisher",
|
|
6
|
+
"repository": "https://github.com/jorgebucaran/fisher",
|
|
7
|
+
"commit": "791da644d33d392216f6b1a9b5fc1e470db6d7f2",
|
|
8
|
+
"archive_url": "https://codeload.github.com/jorgebucaran/fisher/tar.gz/791da644d33d392216f6b1a9b5fc1e470db6d7f2",
|
|
9
|
+
"archive_sha256": "3450711cf552c2032e93e775c3cebb082c0a321ee1dd046d2d41cbc7b77d707f",
|
|
10
|
+
"files": {
|
|
11
|
+
"LICENSE.md": "f101c761d255d0dddc77dd8a9327733b03d381798ec54a1bb718367207b48a8e",
|
|
12
|
+
"functions/fisher.fish": "0fb6c81ae3003e95b5671766fa6c25c3597066e29965b7772f6c1b007387356d",
|
|
13
|
+
"completions/fisher.fish": "6ef51da07e11ed534ce828770dfa3135551bafe9aa3c28700cee1fc5f053cd48"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "z",
|
|
18
|
+
"repository": "https://github.com/jethrokuan/z",
|
|
19
|
+
"commit": "26a50962bc68f5cb60fc488ee008b3d4d5be75f4",
|
|
20
|
+
"archive_url": "https://codeload.github.com/jethrokuan/z/tar.gz/26a50962bc68f5cb60fc488ee008b3d4d5be75f4",
|
|
21
|
+
"archive_sha256": "58bbb82d1b5e8e9a5f4a9d793115c99d20a183bb1dfbd5d4e2285f8c5579582d",
|
|
22
|
+
"files": {
|
|
23
|
+
"LICENSE": "6768e40ee8241d60df364bcf60a1d2dba0dfa7ecb699a658c186c4ef98157e02",
|
|
24
|
+
"conf.d/z.fish": "8d8499125844a249b29a5a312182373ac268bfafe9c1468c764edde6081b7f62",
|
|
25
|
+
"functions/__z.fish": "f379818b6ec429db4f8fe1d4cf0baeb57fc9dabbd8603fb219b21b1164c7d6e0",
|
|
26
|
+
"functions/__z_add.fish": "98c54603a89ff2f4c9262a127a66b072f22e6ad752dd2ad97adb17b4f98da1dc",
|
|
27
|
+
"functions/__z_clean.fish": "dafc74f9cd1f9607c0ece6727402ea7ac3e7bf4554626fe9eb237e1b07440215",
|
|
28
|
+
"functions/__z_complete.fish": "73a08d410621594a0730128d9c997e5fb0008f278c9c42ff156a460014a42328"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "zsh-autosuggestions",
|
|
33
|
+
"repository": "https://github.com/zsh-users/zsh-autosuggestions",
|
|
34
|
+
"commit": "85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc5",
|
|
35
|
+
"archive_url": "https://codeload.github.com/zsh-users/zsh-autosuggestions/tar.gz/85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc5",
|
|
36
|
+
"archive_sha256": "20665e469e720e674964a66854d5534b9af78cdfd438512746ecd1ade8e819ce",
|
|
37
|
+
"files": {
|
|
38
|
+
"LICENSE": "4598a6be0b8d7f2b708da5259d2a30d4e15e59b3c66781bab9e27744a9f859d8",
|
|
39
|
+
"zsh-autosuggestions.zsh": "eec7ba8f7a71414ace0ea0fab0908d005b24cf65d83b169c0ff97815d3cfc51a"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "zsh-syntax-highlighting",
|
|
44
|
+
"repository": "https://github.com/zsh-users/zsh-syntax-highlighting",
|
|
45
|
+
"commit": "e6683f20e5c38d3e5447f45845d04ddda75d0f23",
|
|
46
|
+
"archive_url": "https://codeload.github.com/zsh-users/zsh-syntax-highlighting/tar.gz/e6683f20e5c38d3e5447f45845d04ddda75d0f23",
|
|
47
|
+
"archive_sha256": "6e8258a74e6f3cac03e1bb5ee72504bc4d819904e9aa742d62f60833168db265",
|
|
48
|
+
"files": {
|
|
49
|
+
"COPYING.md": "d810908db3cb75d30e46f5e55b18c8f483e1bc625b8f7dc5a581f5ad353af82e",
|
|
50
|
+
".version": "97fd9d491486c9c26ce918b0ad429584dddd807f34655f2342872d8175383094",
|
|
51
|
+
".revision-hash": "0e4e0c3aaec5a3efe933c7b41cb940fe5e6c28874f5075a9f68427f63135abde",
|
|
52
|
+
"zsh-syntax-highlighting.zsh": "156ebe9530eb991dcef54d476967e2ff4338d35dabaaff9e5462673a287cc63b",
|
|
53
|
+
"highlighters/brackets/brackets-highlighter.zsh": "b3ac4a66edf133b8f029332e787b7d36e2e1d7cabec0d271f7e5fe6724490dd3",
|
|
54
|
+
"highlighters/cursor/cursor-highlighter.zsh": "bd6ef3aae900fee57ff132360b3dd9d68df5aab150a33e32259fd5adbe8efd49",
|
|
55
|
+
"highlighters/line/line-highlighter.zsh": "1a12c094770bc00276395dc71a398a63fd768c433453d35f4e47e5d315dfacf0",
|
|
56
|
+
"highlighters/main/main-highlighter.zsh": "1f59176bc1e5fd8ac8eaa85dd7a4cd2a95083ee7c689a430ff4a5e2e9eee0061",
|
|
57
|
+
"highlighters/pattern/pattern-highlighter.zsh": "c2d5b50db13936421672b5ce16c0d7ec4f1abfeded34ea3a23bb39d2499b953b",
|
|
58
|
+
"highlighters/regexp/regexp-highlighter.zsh": "f567458da4fb89cae8ea220b8febea11ed67ab6f6c8f5e0d6723ea7285e932e7",
|
|
59
|
+
"highlighters/root/root-highlighter.zsh": "7a038444d4cd60f9eaf07993b6a14d0055ad8706e09a32780cb65ea0a90530ee"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Create an opt-in Crow Term shell profile; never edit a personal dotfile.
|
|
3
|
+
|
|
4
|
+
Only Python's standard library is required. Plugin installation is offline and
|
|
5
|
+
copies an allowlist of vendored, pinned, SHA256-verified upstream files.
|
|
6
|
+
"""
|
|
7
|
+
import argparse
|
|
8
|
+
import hashlib
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path, PurePosixPath
|
|
12
|
+
import stat
|
|
13
|
+
import sys
|
|
14
|
+
import tempfile
|
|
15
|
+
|
|
16
|
+
HERE = Path(__file__).resolve().parent
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def quote_fish(value):
|
|
20
|
+
return "'" + str(value).replace("\\", "\\\\").replace("'", "\\'") + "'"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def quote_zsh(value):
|
|
24
|
+
return "'" + str(value).replace("'", "'\\''") + "'"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def checked_prefix(value):
|
|
28
|
+
path = Path(os.path.abspath(os.path.expanduser(value)))
|
|
29
|
+
if any(ord(c) < 32 or ord(c) == 127 for c in str(path)):
|
|
30
|
+
raise ValueError("prefix must not contain control characters")
|
|
31
|
+
if path.is_symlink():
|
|
32
|
+
raise ValueError("prefix must not be a symlink")
|
|
33
|
+
path = path.resolve()
|
|
34
|
+
if path in (Path(path.anchor), Path.home().resolve()):
|
|
35
|
+
raise ValueError("choose a dedicated profile directory, not root or HOME")
|
|
36
|
+
if path.exists() and not path.is_dir():
|
|
37
|
+
raise ValueError("prefix is not a directory")
|
|
38
|
+
return path
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def fish_profile(prefix):
|
|
42
|
+
q = quote_fish
|
|
43
|
+
return f"""# Crow Term isolated profile. Generated; no personal dotfiles are sourced.
|
|
44
|
+
set -g fisher_path {q(prefix / 'fish-managed')}
|
|
45
|
+
set -g fish_function_path {q(prefix / 'fish-managed/functions')} {q(prefix / 'plugins/fisher/functions')} {q(prefix / 'plugins/z/functions')} $fish_function_path
|
|
46
|
+
set -g fish_complete_path {q(prefix / 'plugins/fisher/completions')} $fish_complete_path
|
|
47
|
+
set -gx Z_DATA_DIR {q(prefix / 'data/z')}
|
|
48
|
+
set -gx Z_DATA {q(prefix / 'data/z/data')}
|
|
49
|
+
if test -f {q(prefix / 'plugins/z/conf.d/z.fish')}
|
|
50
|
+
source {q(prefix / 'plugins/z/conf.d/z.fish')}
|
|
51
|
+
end
|
|
52
|
+
set -g fish_color_command normal --bold
|
|
53
|
+
set -g fish_color_keyword normal --bold
|
|
54
|
+
set -g fish_color_quote 606060
|
|
55
|
+
set -g fish_color_comment 6A6A6A --italics
|
|
56
|
+
set -g fish_color_param normal
|
|
57
|
+
set -g fish_color_operator normal
|
|
58
|
+
set -g fish_color_redirection normal
|
|
59
|
+
set -g fish_color_end normal
|
|
60
|
+
set -g fish_color_error normal --bold
|
|
61
|
+
set -g fish_color_autosuggestion 808080
|
|
62
|
+
set -g fish_color_selection --reverse
|
|
63
|
+
set -g fish_color_search_match --reverse
|
|
64
|
+
function fish_prompt
|
|
65
|
+
set -l last_status $status
|
|
66
|
+
set_color normal
|
|
67
|
+
printf '%s' (prompt_pwd)
|
|
68
|
+
if test $last_status -ne 0
|
|
69
|
+
printf ' [%s]' $last_status
|
|
70
|
+
end
|
|
71
|
+
printf ' > '
|
|
72
|
+
set_color normal
|
|
73
|
+
end
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def zsh_profile(prefix):
|
|
78
|
+
q = quote_zsh
|
|
79
|
+
return f"""# Crow Term isolated profile; no personal dotfiles or framework.
|
|
80
|
+
HISTFILE={q(prefix / 'data/zsh-history')}
|
|
81
|
+
HISTSIZE=10000
|
|
82
|
+
SAVEHIST=10000
|
|
83
|
+
setopt HIST_IGNORE_SPACE
|
|
84
|
+
PROMPT='%f%~ > '
|
|
85
|
+
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#808080'
|
|
86
|
+
if [[ -f {q(prefix / 'plugins/zsh-autosuggestions/zsh-autosuggestions.zsh')} ]]; then
|
|
87
|
+
source {q(prefix / 'plugins/zsh-autosuggestions/zsh-autosuggestions.zsh')}
|
|
88
|
+
fi
|
|
89
|
+
typeset -gA ZSH_HIGHLIGHT_STYLES
|
|
90
|
+
ZSH_HIGHLIGHT_STYLES[command]='bold'
|
|
91
|
+
ZSH_HIGHLIGHT_STYLES[builtin]='bold'
|
|
92
|
+
ZSH_HIGHLIGHT_STYLES[reserved-word]='bold'
|
|
93
|
+
ZSH_HIGHLIGHT_STYLES[comment]='fg=#6A6A6A,italic'
|
|
94
|
+
ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=#606060'
|
|
95
|
+
ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=#606060'
|
|
96
|
+
# Must remain the final sourced plugin (upstream requirement).
|
|
97
|
+
if [[ -f {q(prefix / 'plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh')} ]]; then
|
|
98
|
+
source {q(prefix / 'plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh')}
|
|
99
|
+
fi
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def launcher(prefix, shell):
|
|
104
|
+
# Embed data as Python literals, not shell substitutions. execvpe receives an
|
|
105
|
+
# argument array, and profile path quoting is only for fish's -C expression.
|
|
106
|
+
args = (["--no-config", "--init-command", "source " + quote_fish(prefix / "fish/config.fish")]
|
|
107
|
+
if shell == "fish" else ["-d", "-i"])
|
|
108
|
+
return f"""#!/usr/bin/env python3
|
|
109
|
+
import os
|
|
110
|
+
from pathlib import Path
|
|
111
|
+
import shutil
|
|
112
|
+
import sys
|
|
113
|
+
prefix = Path({str(prefix)!r})
|
|
114
|
+
env = os.environ.copy()
|
|
115
|
+
# Isolate shell universal variables, history, plugin state and completion cache.
|
|
116
|
+
# Child applications inherit these XDG directories too; this is opt-in.
|
|
117
|
+
for key, rel in {{'XDG_CONFIG_HOME': 'config', 'XDG_DATA_HOME': 'data', 'XDG_CACHE_HOME': 'cache', 'XDG_STATE_HOME': 'state'}}.items():
|
|
118
|
+
folder = prefix / rel
|
|
119
|
+
folder.mkdir(mode=0o700, parents=True, exist_ok=True)
|
|
120
|
+
env[key] = str(folder)
|
|
121
|
+
env['ZDOTDIR'] = str(prefix / 'zsh')
|
|
122
|
+
program = shutil.which({shell!r})
|
|
123
|
+
if not program:
|
|
124
|
+
sys.exit('Required shell not found on PATH: {shell}')
|
|
125
|
+
os.execvpe(program, [program] + {args!r} + sys.argv[1:], env)
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def plan_files(prefix, shell, install_plugins=False):
|
|
130
|
+
profile = ("fish/config.fish", fish_profile(prefix)) if shell == "fish" else ("zsh/.zshrc", zsh_profile(prefix))
|
|
131
|
+
plan = {profile[0]: (profile[1].encode(), 0o600),
|
|
132
|
+
f"launch-{shell}.py": (launcher(prefix, shell).encode(), 0o700)}
|
|
133
|
+
lock_data = (HERE / "plugins.lock.json").read_bytes()
|
|
134
|
+
lock = json.loads(lock_data)
|
|
135
|
+
if lock.get("schema") != 1:
|
|
136
|
+
raise ValueError("unsupported plugin lock schema")
|
|
137
|
+
if install_plugins:
|
|
138
|
+
selected = {"fisher", "z"} if shell == "fish" else {"zsh-autosuggestions", "zsh-syntax-highlighting"}
|
|
139
|
+
for plugin in lock["plugins"]:
|
|
140
|
+
if plugin["name"] not in selected:
|
|
141
|
+
continue
|
|
142
|
+
for rel, digest in plugin["files"].items():
|
|
143
|
+
path = PurePosixPath(rel)
|
|
144
|
+
if path.is_absolute() or ".." in path.parts:
|
|
145
|
+
raise ValueError("invalid path in plugin lock")
|
|
146
|
+
source = HERE / "vendor" / plugin["name"] / rel
|
|
147
|
+
if source.is_symlink() or not source.is_file():
|
|
148
|
+
raise ValueError(f"missing/nonregular vendored file: {source}")
|
|
149
|
+
content = source.read_bytes()
|
|
150
|
+
if hashlib.sha256(content).hexdigest() != digest:
|
|
151
|
+
raise ValueError(f"SHA256 mismatch: {source}")
|
|
152
|
+
plan[f"plugins/{plugin['name']}/{rel}"] = (content, 0o600)
|
|
153
|
+
plan["plugins.lock.json"] = (lock_data, 0o600)
|
|
154
|
+
if shell == "fish":
|
|
155
|
+
pins = [p['repository'].removeprefix('https://github.com/') + '@' + p['commit']
|
|
156
|
+
for p in lock['plugins'] if p['name'] in selected]
|
|
157
|
+
plan["fish-managed/fish_plugins"] = (("\n".join(pins) + "\n").encode(), 0o600)
|
|
158
|
+
return plan
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def check_destination(prefix, rel, data):
|
|
162
|
+
dest = prefix / rel
|
|
163
|
+
for current in [prefix] + list(dest.relative_to(prefix).parents)[::-1]:
|
|
164
|
+
# Relative parents are handled below; only inspect paths beneath prefix.
|
|
165
|
+
if not current.is_absolute():
|
|
166
|
+
current = prefix / current
|
|
167
|
+
if current.is_symlink():
|
|
168
|
+
raise ValueError(f"refusing symlink directory: {current}")
|
|
169
|
+
if current.exists() and not current.is_dir():
|
|
170
|
+
raise ValueError(f"not a directory: {current}")
|
|
171
|
+
if dest.is_symlink():
|
|
172
|
+
raise ValueError(f"refusing symlink file: {dest}")
|
|
173
|
+
if dest.exists():
|
|
174
|
+
if not stat.S_ISREG(dest.stat().st_mode) or dest.read_bytes() != data:
|
|
175
|
+
raise ValueError(f"existing file differs; refusing overwrite: {dest}")
|
|
176
|
+
return False
|
|
177
|
+
return True
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def create_directory(path):
|
|
181
|
+
missing = []
|
|
182
|
+
while not path.exists():
|
|
183
|
+
missing.append(path)
|
|
184
|
+
path = path.parent
|
|
185
|
+
if path.is_symlink() or not path.is_dir():
|
|
186
|
+
raise ValueError(f"unsafe directory: {path}")
|
|
187
|
+
for directory in reversed(missing):
|
|
188
|
+
directory.mkdir(mode=0o700)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def write_new(prefix, rel, data, mode):
|
|
192
|
+
if not check_destination(prefix, rel, data):
|
|
193
|
+
return
|
|
194
|
+
dest = prefix / rel
|
|
195
|
+
create_directory(dest.parent)
|
|
196
|
+
temporary = None
|
|
197
|
+
try:
|
|
198
|
+
with tempfile.NamedTemporaryFile(dir=dest.parent, prefix=".crow-term-", delete=False) as file:
|
|
199
|
+
temporary = Path(file.name)
|
|
200
|
+
os.fchmod(file.fileno(), mode)
|
|
201
|
+
file.write(data)
|
|
202
|
+
file.flush()
|
|
203
|
+
os.fsync(file.fileno())
|
|
204
|
+
# Atomic no-clobber publish. Unlike replace()/rename(), link() cannot
|
|
205
|
+
# overwrite an existing destination, even if another setup races us.
|
|
206
|
+
try:
|
|
207
|
+
os.link(temporary, dest)
|
|
208
|
+
except FileExistsError:
|
|
209
|
+
if check_destination(prefix, rel, data):
|
|
210
|
+
raise
|
|
211
|
+
finally:
|
|
212
|
+
if temporary is not None:
|
|
213
|
+
temporary.unlink(missing_ok=True)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def main(argv=None):
|
|
217
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
218
|
+
parser.add_argument("--shell", required=True, choices=("fish", "zsh"))
|
|
219
|
+
parser.add_argument("--prefix", required=True, help="dedicated Crow Term profile directory")
|
|
220
|
+
parser.add_argument("--install-plugins", action="store_true", help="copy verified vendored plugins (offline)")
|
|
221
|
+
parser.add_argument("--dry-run", action="store_true", help="validate and print plan without writing")
|
|
222
|
+
args = parser.parse_args(argv)
|
|
223
|
+
try:
|
|
224
|
+
prefix = checked_prefix(args.prefix)
|
|
225
|
+
plan = plan_files(prefix, args.shell, args.install_plugins)
|
|
226
|
+
# Preflight every target before the first write. Interrupted execution
|
|
227
|
+
# may leave a partial set of complete files; rerun safely resumes it.
|
|
228
|
+
changes = {rel: check_destination(prefix, rel, data) for rel, (data, _) in plan.items()}
|
|
229
|
+
for rel, (data, mode) in plan.items():
|
|
230
|
+
print(("create " if changes[rel] else "keep ") + str(prefix / rel))
|
|
231
|
+
if not args.dry_run:
|
|
232
|
+
write_new(prefix, rel, data, mode)
|
|
233
|
+
print(("Would launch: " if args.dry_run else "Launch explicitly: ") + f"python3 {str(prefix / ('launch-' + args.shell + '.py'))!r}")
|
|
234
|
+
return 0
|
|
235
|
+
except (OSError, ValueError, KeyError, TypeError) as error:
|
|
236
|
+
print(f"shell setup: {error}", file=sys.stderr)
|
|
237
|
+
return 1
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
if __name__ == "__main__":
|
|
241
|
+
sys.exit(main())
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright © Jorge Bucaran <<https://jorgebucaran.com>>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
complete --command fisher --exclusive --long help --description "Print help"
|
|
2
|
+
complete --command fisher --exclusive --long version --description "Print version"
|
|
3
|
+
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments install --description "Install plugins"
|
|
4
|
+
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments update --description "Update installed plugins"
|
|
5
|
+
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments remove --description "Remove installed plugins"
|
|
6
|
+
complete --command fisher --exclusive --condition __fish_use_subcommand --arguments list --description "List installed plugins matching regex"
|
|
7
|
+
complete --command fisher --exclusive --condition "__fish_seen_subcommand_from update remove" --arguments "(fisher list)"
|