Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[target.wasm32-wasip1]
rustflags = [
"-L/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi",
"-Clink-arg=-lc++",
"-Clink-arg=-lc++abi"
]
14 changes: 14 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ jobs:
# detects that they need cross).
- target: x86_64-unknown-linux-musl
os: ubuntu-22.04
- target: wasm32-wasip1
os: ubuntu-24.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-22.04
- target: aarch64-pc-windows-msvc
Expand All @@ -46,6 +48,13 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
# v4.2.2
- run: |
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.deb
sudo apt-get install ./wasi-sdk-29.0-x86_64-linux.deb
rm ./wasi-sdk-29.0-x86_64-linux.deb
rustup override set stable
rustup target add wasm32-wasip1
if: ${{ matrix.target == 'wasm32-wasip1' }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: taiki-e/upload-rust-binary-action@v1
with:
Expand All @@ -59,6 +68,11 @@ jobs:
env:
# (required)
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WASI_SDK_PATH: /opt/wasi-sdk
WASI_SYSROOT: /opt/wasi-sdk/share/wasi-sysroot
CC_wasm32_wasip1: /opt/wasi-sdk/bin/clang
AR_wasm32_wasip1: /opt/wasi-sdk/bin/llvm-ar
CFLAGS_wasm32_wasip1: "--sysroot=/opt/wasi-sdk/share/wasi-sysroot"

push_crates_io:
runs-on: ubuntu-22.04
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ tree_magic_mini = "3.1.6"

bumpalo = "3.16.0"
unicode-width = "0.1.9"
crossterm = { version = "0.28.0", features = ["windows"] }
glob = "0.3.1"
strum = { version = "0.26", features = ["derive"] }
hashbrown = "0.14.0"
Expand Down Expand Up @@ -128,7 +127,10 @@ tree-sitter-xml = "0.7.0"
tree-sitter-yaml = "0.7.0"
tree-sitter-zig = "1.1.2"

[target.'cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))'.dependencies]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
crossterm = { version = "0.28.0", features = ["windows"] }

[target.'cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd", target_arch = "wasm32")))'.dependencies]
tikv-jemallocator = "0.6"

[dev-dependencies]
Expand Down
17 changes: 16 additions & 1 deletion src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ fn read_file_arg(file_arg: &FileArgument) -> std::io::Result<Vec<u8>> {
}

/// Write a human-friendly description of `e` to stderr.
#[cfg(not(target_arch = "wasm32"))]
fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
match e.kind() {
std::io::ErrorKind::NotFound => {
Expand All @@ -95,12 +96,26 @@ fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
};
}

#[cfg(target_arch = "wasm32")]
fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
// For the browser/WASM demo, fail softly so we can keep running.
println!("WASM read error on {} ({:?})", file_arg, e.kind());
}

pub(crate) fn read_or_die(path: &Path) -> Vec<u8> {
match fs::read(path) {
Ok(src) => src,
Err(e) => {
eprint_read_error(&FileArgument::NamedPath(path.to_path_buf()), &e);
std::process::exit(EXIT_BAD_ARGUMENTS);
#[cfg(target_arch = "wasm32")]
{
// Return empty content in WASM to avoid aborting the demo.
return Vec::new();
}
#[cfg(not(target_arch = "wasm32"))]
{
std::process::exit(EXIT_BAD_ARGUMENTS);
}
}
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,20 @@ use crate::parse::syntax;
///
/// For reference, Jemalloc uses 10-20% more time (although up to 33%
/// more instructions) when testing on sample files.
#[cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))]
#[cfg(not(any(
target_env = "msvc",
target_os = "illumos",
target_os = "freebsd",
target_arch = "wasm32"
)))]
use tikv_jemallocator::Jemalloc;

#[cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))]
#[cfg(not(any(
target_env = "msvc",
target_os = "illumos",
target_os = "freebsd",
target_arch = "wasm32"
)))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;

Expand Down
42 changes: 35 additions & 7 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use std::{
};

use clap::{crate_authors, crate_description, value_parser, Arg, ArgAction, Command};
use crossterm::tty::IsTty;
use owo_colors::OwoColorize as _;

use crate::{
Expand Down Expand Up @@ -51,6 +50,30 @@ pub(crate) struct DisplayOptions {

pub(crate) const DEFAULT_TERMINAL_WIDTH: usize = 80;

#[cfg(not(target_arch = "wasm32"))]
fn stdout_is_tty() -> bool {
use crossterm::tty::IsTty;
std::io::stdout().is_tty()
}

#[cfg(target_arch = "wasm32")]
fn stdout_is_tty() -> bool {
false
}

#[cfg(not(target_arch = "wasm32"))]
fn terminal_columns() -> Option<usize> {
crossterm::terminal::size()
.ok()
.map(|(cols, _rows)| cols as usize)
.filter(|cols| *cols > 0)
}

#[cfg(target_arch = "wasm32")]
fn terminal_columns() -> Option<usize> {
None
}

impl Default for DisplayOptions {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -125,7 +148,7 @@ fn app() -> clap::Command {
));

after_help.push_str("\n\nSee the full manual at ");
if std::io::stdout().is_tty() {
if stdout_is_tty() {
// Make the link to the manual clickable in terminals that
// support OSC 8, the ANSI escape code for hyperlinks.
//
Expand Down Expand Up @@ -596,6 +619,7 @@ fn common_path_suffix(lhs_path: &Path, rhs_path: &Path) -> Option<String> {
}

/// Does `path` look like "/tmp/git-blob-abcdef/modified_field.txt"?
#[cfg(not(target_arch = "wasm32"))]
fn is_git_tmpfile(path: &Path) -> bool {
let Ok(rel_path) = path.strip_prefix(std::env::temp_dir()) else {
return false;
Expand All @@ -612,6 +636,12 @@ fn is_git_tmpfile(path: &Path) -> bool {
.starts_with("git-blob-")
}

#[cfg(target_arch = "wasm32")]
fn is_git_tmpfile(_path: &Path) -> bool {
// WASI environments may not have a writable /tmp; skip special-casing.
false
}

fn build_display_path(lhs_path: &FileArgument, rhs_path: &FileArgument) -> String {
match (lhs_path, rhs_path) {
(FileArgument::NamedPath(lhs), FileArgument::NamedPath(rhs)) => {
Expand Down Expand Up @@ -1002,10 +1032,8 @@ pub(crate) fn parse_args() -> Mode {
/// Try to work out the width of the terminal we're on, or fall back
/// to a sensible default value.
fn detect_terminal_width() -> usize {
if let Ok((columns, _rows)) = crossterm::terminal::size() {
if columns > 0 {
return columns.into();
}
if let Some(columns) = terminal_columns() {
return columns;
}

// If crossterm couldn't detect the terminal width, use the
Expand Down Expand Up @@ -1036,7 +1064,7 @@ pub(crate) fn should_use_color(color_output: ColorOutput) -> bool {
fn detect_color_support() -> bool {
// TODO: consider following the env parsing logic in git_config_bool
// in config.c.
std::io::stdout().is_tty() || env::var("GIT_PAGER_IN_USE").is_ok()
stdout_is_tty() || env::var("GIT_PAGER_IN_USE").is_ok()
}

#[cfg(test)]
Expand Down
Loading