- 设置左栏「关键字高亮」下面新增「键盘快捷键」,通用、标签、终端、 编辑器四组主要功能。点按键后按下新组合即换上,Esc 放弃;每行可禁用、 恢复默认。没有修饰键的键,以及同一处已被占用或输入框等内置功能使用 的组合会被拒绝,并提示被谁占用。 - 新增标签切换:下一个 / 上一个标签(⌘⇧] / ⌘⇧[,其他平台 Ctrl+Tab / Ctrl+Shift+Tab),切换到第 1…9 个标签(⌘1…⌘9,Alt+1…9)。 - ⌘= / ⌘- / ⌘0 在终端里调终端字号并记进设置,在终端外仍缩放界面。 - 终端字号范围改为 10–28。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
207 lines
5.7 KiB
Rust
207 lines
5.7 KiB
Rust
use std::borrow::Cow;
|
|
|
|
use gpui_kit::assets::icon_assets;
|
|
use gpui_kit::{AssetSource, Result, SharedString};
|
|
|
|
// Icons beyond the default component bundle, embedded from the Lucide
|
|
// catalog shipped with `gpui-kit-assets`.
|
|
icon_assets!(
|
|
ExtraIcons,
|
|
[
|
|
Server,
|
|
Terminal,
|
|
Upload,
|
|
Download,
|
|
Trash,
|
|
Pencil,
|
|
RefreshCw,
|
|
Plug,
|
|
Unplug,
|
|
FolderTree,
|
|
FolderPlus,
|
|
Eraser,
|
|
ClipboardPaste,
|
|
ClipboardCopy,
|
|
House,
|
|
FolderUp,
|
|
FolderRoot,
|
|
FolderSymlink,
|
|
FileSymlink,
|
|
FilePlus,
|
|
Bookmark,
|
|
SquarePen,
|
|
Settings,
|
|
Palette,
|
|
SquareTerminal,
|
|
CircleMinus,
|
|
Play,
|
|
Square,
|
|
ArrowLeftRight,
|
|
ArrowRightToLine,
|
|
ArrowLeftToLine,
|
|
Laptop,
|
|
Lock,
|
|
CircleAlert,
|
|
Target,
|
|
KeyRound,
|
|
RectangleEllipsis,
|
|
FileKey,
|
|
UserRoundKey,
|
|
CircleArrowUp,
|
|
CodeXml,
|
|
RotateCcwClock,
|
|
Activity,
|
|
Monitor,
|
|
AppWindow,
|
|
Keyboard,
|
|
RotateCcw,
|
|
Network,
|
|
RadioTower,
|
|
ArrowDownLeft,
|
|
ArrowUpRight,
|
|
ListFilter,
|
|
CircleStop,
|
|
OctagonX,
|
|
ServerCog,
|
|
RotateCw,
|
|
CircleCheck,
|
|
Ban,
|
|
CircleDot,
|
|
FileText,
|
|
FilePenLine,
|
|
Save,
|
|
Eye,
|
|
EyeOff,
|
|
ZoomIn,
|
|
ZoomOut,
|
|
Zap,
|
|
ExternalLink,
|
|
Highlighter,
|
|
GripVertical
|
|
]
|
|
);
|
|
|
|
/// Names of the icons in `ExtraIcons`, usable anywhere an `Icon` is built.
|
|
pub use gpui_kit::assets::IconName as CatalogIcon;
|
|
|
|
/// Operating-system marks for the host tree, one file per
|
|
/// [`crate::host::HostOs`] variant.
|
|
///
|
|
/// These are brand logos, not Lucide glyphs, because an approximation cannot
|
|
/// say "this is a Debian box". The artwork comes from Simple Icons (CC0); the
|
|
/// Windows mark is a plain four-pane square drawn here, since Simple Icons no
|
|
/// longer ships one. GPUI paints an SVG as a tinted mask, so single-path
|
|
/// monochrome files are all that is needed.
|
|
macro_rules! os_icons {
|
|
($($path:literal => $file:literal,)*) => {
|
|
const OS_ICONS: &[(&str, &[u8])] = &[
|
|
$(($path, include_bytes!(concat!("../../assets/icons/os/", $file, ".svg")))),*
|
|
];
|
|
};
|
|
}
|
|
|
|
os_icons! {
|
|
"icons/os/ubuntu.svg" => "ubuntu",
|
|
"icons/os/debian.svg" => "debian",
|
|
"icons/os/fedora.svg" => "fedora",
|
|
"icons/os/redhat.svg" => "redhat",
|
|
"icons/os/centos.svg" => "centos",
|
|
"icons/os/rockylinux.svg" => "rockylinux",
|
|
"icons/os/almalinux.svg" => "almalinux",
|
|
"icons/os/archlinux.svg" => "archlinux",
|
|
"icons/os/alpinelinux.svg" => "alpinelinux",
|
|
"icons/os/opensuse.svg" => "opensuse",
|
|
"icons/os/gentoo.svg" => "gentoo",
|
|
"icons/os/kalilinux.svg" => "kalilinux",
|
|
"icons/os/manjaro.svg" => "manjaro",
|
|
"icons/os/raspberrypi.svg" => "raspberrypi",
|
|
"icons/os/linux.svg" => "linux",
|
|
"icons/os/apple.svg" => "apple",
|
|
"icons/os/windows.svg" => "windows",
|
|
"icons/os/freebsd.svg" => "freebsd",
|
|
"icons/os/openbsd.svg" => "openbsd",
|
|
"icons/os/netbsd.svg" => "netbsd",
|
|
}
|
|
|
|
/// Brand marks that Lucide, which draws no brands, cannot stand in for:
|
|
/// Docker's whale on the right sidebar's Docker tool. From Simple Icons (CC0),
|
|
/// single-path and monochrome like the operating-system marks.
|
|
const BRAND_ICONS: &[(&str, &[u8])] = &[(
|
|
DOCKER_ICON,
|
|
include_bytes!("../../assets/icons/brand/docker.svg"),
|
|
)];
|
|
|
|
/// Docker's whale, for `Icon::path`.
|
|
pub const DOCKER_ICON: &str = "icons/brand/docker.svg";
|
|
|
|
/// Asset source for the application: the default component bundle plus the
|
|
/// extra icons and the marks above.
|
|
pub struct AppAssets;
|
|
|
|
impl AssetSource for AppAssets {
|
|
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
|
if let Some((_, bytes)) = OS_ICONS
|
|
.iter()
|
|
.chain(BRAND_ICONS)
|
|
.find(|(name, _)| *name == path)
|
|
{
|
|
return Ok(Some(Cow::Borrowed(bytes)));
|
|
}
|
|
if let Some(bytes) = ExtraIcons.load(path)? {
|
|
return Ok(Some(bytes));
|
|
}
|
|
gpui_kit::assets::Assets.load(path)
|
|
}
|
|
|
|
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
|
|
let mut paths = gpui_kit::assets::Assets.list(path)?;
|
|
paths.extend(ExtraIcons.list(path)?);
|
|
paths.extend(
|
|
OS_ICONS
|
|
.iter()
|
|
.chain(BRAND_ICONS)
|
|
.map(|(name, _)| *name)
|
|
.filter(|name| name.starts_with(path))
|
|
.map(SharedString::from),
|
|
);
|
|
paths.sort();
|
|
paths.dedup();
|
|
Ok(paths)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::AppAssets;
|
|
use crate::host::HostOs;
|
|
use gpui_kit::AssetSource as _;
|
|
|
|
#[test]
|
|
fn every_operating_system_has_an_icon_in_the_bundle() {
|
|
for os in HostOs::ALL {
|
|
let path = os.icon_path();
|
|
let bytes = AppAssets
|
|
.load(path)
|
|
.unwrap_or_else(|error| panic!("{path} 加载失败:{error}"))
|
|
.unwrap_or_else(|| panic!("{path} 不在资源包里"));
|
|
assert!(bytes.starts_with(b"<svg"), "{path} 不是 SVG");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_docker_tool_has_dockers_whale() {
|
|
let bytes = AppAssets
|
|
.load(super::DOCKER_ICON)
|
|
.unwrap()
|
|
.expect("in the bundle");
|
|
assert!(bytes.starts_with(b"<svg"));
|
|
assert!(String::from_utf8_lossy(&bytes).contains("<title>Docker</title>"));
|
|
}
|
|
|
|
#[test]
|
|
fn the_bundle_lists_the_operating_system_icons() {
|
|
let listed = AppAssets.list("icons/os/").unwrap();
|
|
assert_eq!(listed.len(), HostOs::ALL.len());
|
|
}
|
|
}
|