Compare commits

...

9 Commits

Author SHA1 Message Date
uncenter
e5410762c9
Merge 8ac8ffa236 into 4aaca4c432 2024-08-07 00:24:45 -04:00
三咲雅 · Misaki Masa
4aaca4c432
feat: supports Ghostty image rendering using kitty unicode placeholders (#1427) 2024-08-07 12:17:14 +08:00
Konrad Baran
f865910481
ci: add automatic nightly builds to the Github Actions workflow (#1397)
Co-authored-by: sxyazi <sxyazi@gmail.com>
2024-08-07 08:27:00 +08:00
uncenter
8ac8ffa236
Merge branch 'main' into pr-a8721e1e 2024-08-03 17:41:59 -04:00
uncenter
3f6498bc17
Merge branch 'main' into pr-a8721e1e 2024-08-01 12:51:36 -04:00
uncenter
0abe1e3cde
Merge branch 'main' into pr-a8721e1e 2024-07-31 13:42:14 -04:00
uncenter
97e622a03d
fix: clear fragment before saving remote 2024-07-27 10:34:15 -04:00
uncenter
da6976302a
fix: save remote to config for non-github remotes 2024-07-22 18:43:09 -04:00
uncenter
11838092cf
feat(yazi-cli/pack): support remotes other than github 2024-07-22 18:00:29 -04:00
17 changed files with 128 additions and 63 deletions

View File

@ -29,16 +29,7 @@ body:
attributes:
label: "`yazi --debug` output"
description: Please run `yazi --debug` and paste the debug information here.
value: |
<details>
```sh
##### ↓↓↓ Paste the output here: ↓↓↓ #####
```
</details>
render: Shell
validations:
required: true
- type: dropdown

View File

@ -8,16 +8,7 @@ body:
attributes:
label: "`yazi --debug` output"
description: Please run `yazi --debug` and paste the debug information here.
value: |
<details>
```sh
##### ↓↓↓ Paste the output here: ↓↓↓ #####
```
</details>
render: Shell
validations:
required: true
- type: textarea

View File

@ -1,8 +1,8 @@
name: Cachix
on:
push:
branches:
- main
branches: [main]
jobs:
publish:

View File

@ -4,6 +4,9 @@ on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
schedule:
- cron: "0 */6 * * *"
workflow_dispatch:
jobs:
build-unix:
@ -145,3 +148,31 @@ jobs:
yazi-*.zip
yazi-*.snap
generate_release_notes: true
nightly:
permissions:
contents: write
runs-on: ubuntu-latest
needs: [build-unix, build-windows, build-musl, build-snap]
steps:
- uses: actions/download-artifact@v4
with:
merge-multiple: true
- run: |
echo 'NIGHTLY_BODY<<EOF' >> $GITHUB_ENV
echo "From commit: ${GITHUB_SHA:0:8}" >> $GITHUB_ENV
echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Nightly
uses: softprops/action-gh-release@v1
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
with:
tag_name: nightly
prerelease: true
files: |
yazi-*.zip
yazi-*.snap
name: Nightly Build
body: ${{ env.NIGHTLY_BODY }}

1
Cargo.lock generated
View File

@ -3253,6 +3253,7 @@ dependencies = [
"serde_json",
"tokio",
"toml_edit",
"url",
"vergen-gitcl",
"yazi-boot",
"yazi-dds",

View File

@ -46,7 +46,7 @@ https://github.com/sxyazi/yazi/assets/17523360/92ff23fa-0cd5-4f04-b387-894c12265
| WezTerm | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
| Mintty (Git Bash) | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
| foot | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
| Ghostty | [Kitty old protocol](https://github.com/sxyazi/yazi/blob/main/yazi-adapter/src/kitty_old.rs) | ✅ Built-in |
| Ghostty | [Kitty unicode placeholders](https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders) | ✅ Built-in |
| Black Box | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
| VSCode | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
| Tabby | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |

View File

@ -58,8 +58,8 @@ impl Adapter {
pub fn image_erase(self, area: Rect) -> Result<()> {
match self {
Self::Kitty => Kitty::image_erase(area),
Self::Iterm2 => Iterm2::image_erase(area),
Self::KittyOld => KittyOld::image_erase(area),
Self::Iterm2 => Iterm2::image_erase(area),
Self::Sixel => Sixel::image_erase(area),
Self::X11 | Self::Wayland => Ueberzug::image_erase(area),
Self::Chafa => Chafa::image_erase(area),

View File

@ -37,7 +37,7 @@ impl Emulator {
Self::Iterm2 => vec![Adapter::Iterm2, Adapter::Sixel],
Self::WezTerm => vec![Adapter::Iterm2, Adapter::Sixel],
Self::Foot => vec![Adapter::Sixel],
Self::Ghostty => vec![Adapter::KittyOld],
Self::Ghostty => vec![Adapter::Kitty],
Self::BlackBox => vec![Adapter::Sixel],
Self::VSCode => vec![Adapter::Iterm2, Adapter::Sixel],
Self::Tabby => vec![Adapter::Iterm2, Adapter::Sixel],

View File

@ -21,6 +21,7 @@ md-5 = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
toml_edit = "0.22.20"
url = "2.5.2"
[build-dependencies]
yazi-shared = { path = "../yazi-shared", version = "0.3.0" }

View File

@ -9,7 +9,7 @@ impl Package {
let path = self.local();
if !must_exists(&path).await {
Git::clone(&self.remote(), &path).await?;
Git::clone(&self.remote, &path).await?;
} else {
Git::pull(&path).await?;
};

View File

@ -9,7 +9,7 @@ impl Package {
let path = self.local();
if !must_exists(&path).await {
Git::clone(&self.remote(), &path).await?;
Git::clone(&self.remote, &path).await?;
} else {
Git::fetch(&path).await?;
};

View File

@ -2,28 +2,59 @@ use std::{borrow::Cow, io::BufWriter, path::PathBuf};
use anyhow::Result;
use md5::{Digest, Md5};
use url::Url;
use yazi_shared::Xdg;
pub(crate) struct Package {
pub(crate) repo: String,
pub(crate) child: String,
pub(crate) remote: String,
pub(crate) commit: String,
pub(super) is_flavor: bool,
}
impl Package {
pub(super) fn new(url: &str, commit: Option<&str>) -> Self {
let mut parts = url.splitn(2, '#');
match Url::parse(url) {
Ok(mut url) => {
let repo = url.path().trim_start_matches('/').to_string();
let child = match url.fragment() {
Some(fragment) => format!("{fragment}.yazi"),
None => String::new(),
};
url.set_fragment(None);
let remote = url.to_string();
let mut repo = parts.next().unwrap_or_default().to_owned();
let child = if let Some(s) = parts.next() {
format!("{s}.yazi")
} else {
repo.push_str(".yazi");
String::new()
};
return Self {
repo,
child,
remote,
commit: commit.unwrap_or_default().to_owned(),
is_flavor: false,
};
}
Err(_) => {
let mut parts = url.splitn(2, '#');
Self { repo, child, commit: commit.unwrap_or_default().to_owned(), is_flavor: false }
let mut repo = parts.next().unwrap_or_default().to_owned();
let child = if let Some(s) = parts.next() {
format!("{s}.yazi")
} else {
repo.push_str(".yazi");
String::new()
};
let remote = format!("https://github.com/{}.git", repo);
return Self {
repo,
child,
remote,
commit: commit.unwrap_or_default().to_owned(),
is_flavor: false,
};
}
}
}
#[inline]
@ -50,13 +81,7 @@ impl Package {
pub(super) fn local(&self) -> PathBuf {
Xdg::state_dir()
.join("packages")
.join(format!("{:x}", Md5::new_with_prefix(self.remote()).finalize()))
}
#[inline]
pub(super) fn remote(&self) -> String {
// Support more Git hosting services in the future
format!("https://github.com/{}.git", self.repo)
.join(format!("{:x}", Md5::new_with_prefix(&self.remote).finalize()))
}
pub(super) fn header(&self, s: &str) -> Result<()> {

View File

@ -21,6 +21,9 @@ impl Package {
if !package.commit.is_empty() {
table.insert("commit", package.commit.into());
}
if !package.remote.starts_with("https://github.com") {
table.insert("remote", package.remote.into());
}
if package.is_flavor {
doc["flavor"]["deps"].as_array_mut().unwrap().push(table);
@ -47,9 +50,10 @@ impl Package {
for dep in deps.iter_mut() {
let dep = dep.as_inline_table_mut().context("Dependency must be an inline table")?;
let use_ = dep.get("use").and_then(|d| d.as_str()).context("Missing `use` field")?;
let remote = dep.get("remote").and_then(|d| d.as_str());
let commit = dep.get("commit").and_then(|d| d.as_str());
let mut package = Package::new(use_, commit);
let mut package = Package::new(if let Some(remote) = remote { remote } else { use_ }, commit);
if upgrade {
package.upgrade().await?;
} else {

View File

@ -1,4 +1,4 @@
use std::{path::PathBuf, str::FromStr, time::{SystemTime, UNIX_EPOCH}};
use std::{borrow::Cow, path::PathBuf, str::FromStr, time::{SystemTime, UNIX_EPOCH}};
use anyhow::Context;
use serde::{Deserialize, Serialize};
@ -29,6 +29,22 @@ impl Preview {
let time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards");
self.cache_dir.join(format!("{prefix}-{}", time.as_nanos() / 1000))
}
#[inline]
pub fn indent(&self) -> Cow<'static, str> {
match self.tab_size {
0 => Cow::Borrowed(""),
1 => Cow::Borrowed(" "),
2 => Cow::Borrowed(" "),
3 => Cow::Borrowed(" "),
4 => Cow::Borrowed(" "),
5 => Cow::Borrowed(" "),
6 => Cow::Borrowed(" "),
7 => Cow::Borrowed(" "),
8 => Cow::Borrowed(" "),
n => Cow::Owned(" ".repeat(n as usize)),
}
}
}
impl FromStr for Preview {

View File

@ -25,7 +25,7 @@ impl<'a> Input<'a> {
if let Some(syntax) = syntaxes.find_syntax_by_name("Bourne Again Shell (bash)") {
let mut h = HighlightLines::new(syntax, theme);
let regions = h.highlight_line(self.cx.input.value(), syntaxes)?;
return Ok(Highlighter::to_line_widget(regions, &" ".repeat(PREVIEW.tab_size as usize)));
return Ok(Highlighter::to_line_widget(regions, &PREVIEW.indent()));
}
bail!("Failed to find syntax")
}

View File

@ -34,15 +34,13 @@ function Status:style()
end
function Status:mode()
local mode = tostring(self._tab.mode):upper()
if mode == "UNSET" then
mode = "UN-SET"
end
local mode = tostring(self._tab.mode):sub(1, 3):upper()
local style = self:style()
return ui.Line {
ui.Span(THEME.status.separator_open):fg(style.bg),
ui.Span(" " .. mode .. " "):style(style),
ui.Span(THEME.status.separator_close):fg(style.bg):bg(THEME.status.separator_style.fg),
}
end
@ -106,11 +104,11 @@ function Status:percentage()
end
if percent == 0 then
percent = " Top "
percent = " Top "
elseif percent == 100 then
percent = " Bot "
percent = " Bot "
else
percent = string.format(" %3d%% ", percent)
percent = string.format(" %2d%% ", percent)
end
local style = self:style()
@ -126,6 +124,7 @@ function Status:position()
local style = self:style()
return ui.Line {
ui.Span(THEME.status.separator_open):fg(style.bg):bg(THEME.status.separator_style.fg),
ui.Span(string.format(" %2d/%-2d ", cursor + 1, length)):style(style),
ui.Span(THEME.status.separator_close):fg(style.bg),
}

View File

@ -60,9 +60,9 @@ impl Highlighter {
let mut reader = BufReader::new(File::open(&self.path).await?);
let syntax = Self::find_syntax(&self.path).await;
let mut plain = syntax.is_err();
let mut plain = syntax.is_err() as u8;
let mut before = Vec::with_capacity(if plain { 0 } else { skip });
let mut before = Vec::with_capacity(if plain == 0 { skip } else { 0 });
let mut after = Vec::with_capacity(limit);
let mut i = 0;
@ -73,8 +73,11 @@ impl Highlighter {
break;
}
if !plain && (buf.len() > 5000 || buf.contains(&0x1b)) {
plain = true;
if plain == 0 && buf.len() > 5000 {
plain = 1;
drop(mem::take(&mut before));
} else if plain == 0 && buf.contains(&0x1b) {
plain = 2;
drop(mem::take(&mut before));
}
@ -86,7 +89,7 @@ impl Highlighter {
if i > skip {
after.push(String::from_utf8_lossy(&buf).into_owned());
} else if !plain {
} else if plain == 0 {
before.push(String::from_utf8_lossy(&buf).into_owned());
}
buf.clear();
@ -96,11 +99,14 @@ impl Highlighter {
return Err(PeekError::Exceed(i.saturating_sub(limit)));
}
if plain {
let indent = " ".repeat(PREVIEW.tab_size as usize);
Ok(Text::from(after.join("").replace('\x1b', "^[").replace('\t', &indent)))
} else {
if plain == 0 {
Self::highlight_with(before, after, syntax.unwrap()).await
} else if plain == 1 {
Ok(Text::from(after.join("").replace('\t', &PREVIEW.indent())))
} else if plain == 2 {
Ok(Text::from(after.join("").replace('\x1b', "^[").replace('\t', &PREVIEW.indent())))
} else {
unreachable!()
}
}
@ -121,7 +127,7 @@ impl Highlighter {
h.highlight_line(&line, syntaxes).map_err(|e| anyhow!(e))?;
}
let indent = " ".repeat(PREVIEW.tab_size as usize);
let indent = PREVIEW.indent();
let mut lines = Vec::with_capacity(after.len());
for line in after {
if ticket != INCR.load(Ordering::Relaxed) {