Full Code of microsoft/edit for AI

main baa3cb05b473 cached
96 files
999.2 KB
293.9k tokens
1363 symbols
1 requests
Download .txt
Showing preview only (1,039K chars total). Download the full file or copy to clipboard to get everything.
Repository: microsoft/edit
Branch: main
Commit: baa3cb05b473
Files: 96
Total size: 999.2 KB

Directory structure:
gitextract_909sqtf7/

├── .cargo/
│   ├── release-nightly.toml
│   ├── release-windows-ms.toml
│   └── release.toml
├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   └── workflows/
│       ├── ci.yml
│       └── winget.yml
├── .gitignore
├── .pipelines/
│   ├── release.yml
│   └── tsa.json
├── .vscode/
│   ├── launch.json
│   └── tasks.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── README.md
├── SECURITY.md
├── assets/
│   ├── com.microsoft.edit.desktop
│   ├── editing-traces/
│   │   ├── README.md
│   │   └── rustcode.json.zst
│   ├── highlighting-tests/
│   │   └── json.json
│   ├── manpage/
│   │   └── edit.1
│   ├── microsoft.sixel
│   └── snapcraft.yaml
├── crates/
│   ├── edit/
│   │   ├── Cargo.toml
│   │   ├── benches/
│   │   │   └── lib.rs
│   │   ├── build/
│   │   │   ├── helpers.rs
│   │   │   ├── i18n.rs
│   │   │   └── main.rs
│   │   └── src/
│   │       ├── base64.rs
│   │       ├── bin/
│   │       │   └── edit/
│   │       │       ├── apperr.rs
│   │       │       ├── documents.rs
│   │       │       ├── draw_editor.rs
│   │       │       ├── draw_filepicker.rs
│   │       │       ├── draw_menubar.rs
│   │       │       ├── draw_statusbar.rs
│   │       │       ├── edit.exe.manifest
│   │       │       ├── localization.rs
│   │       │       ├── main.rs
│   │       │       └── state.rs
│   │       ├── buffer/
│   │       │   ├── gap_buffer.rs
│   │       │   ├── line_cache.rs
│   │       │   ├── mod.rs
│   │       │   └── navigation.rs
│   │       ├── cell.rs
│   │       ├── clipboard.rs
│   │       ├── document.rs
│   │       ├── framebuffer.rs
│   │       ├── fuzzy.rs
│   │       ├── glob.rs
│   │       ├── hash.rs
│   │       ├── helpers.rs
│   │       ├── icu.rs
│   │       ├── input.rs
│   │       ├── json.rs
│   │       ├── lib.rs
│   │       ├── oklab.rs
│   │       ├── path.rs
│   │       ├── simd/
│   │       │   ├── lines_bwd.rs
│   │       │   ├── lines_fwd.rs
│   │       │   ├── memchr2.rs
│   │       │   └── mod.rs
│   │       ├── sys/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       ├── tui.rs
│   │       ├── unicode/
│   │       │   ├── measurement.rs
│   │       │   ├── mod.rs
│   │       │   └── tables.rs
│   │       └── vt.rs
│   ├── stdext/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── alloc.rs
│   │       ├── arena/
│   │       │   ├── debug.rs
│   │       │   ├── fs.rs
│   │       │   ├── mod.rs
│   │       │   ├── release.rs
│   │       │   └── scratch.rs
│   │       ├── collections/
│   │       │   ├── mod.rs
│   │       │   ├── string.rs
│   │       │   └── vec.rs
│   │       ├── helpers.rs
│   │       ├── lib.rs
│   │       ├── simd/
│   │       │   ├── memset.rs
│   │       │   └── mod.rs
│   │       ├── sys/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       └── unicode/
│   │           ├── mod.rs
│   │           └── utf8.rs
│   └── unicode-gen/
│       ├── Cargo.toml
│       ├── README.md
│       └── src/
│           ├── main.rs
│           └── rules.rs
├── i18n/
│   └── edit.toml
├── rust-toolchain.toml
└── rustfmt.toml

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/release-nightly.toml
================================================
[profile.release]
panic = "immediate-abort"

[target.'cfg(all(target_os = "windows", target_env = "msvc"))']
rustflags = [
    "-Ctarget-feature=+crt-static",
    "-Clink-args=/DEFAULTLIB:ucrt.lib",
    "-Clink-args=/NODEFAULTLIB:vcruntime.lib",
    "-Clink-args=/NODEFAULTLIB:msvcrt.lib",
    "-Clink-args=/NODEFAULTLIB:libucrt.lib",
]

[unstable]
panic-immediate-abort = true
build-std = ["std", "panic_abort"]


================================================
FILE: .cargo/release-windows-ms.toml
================================================
# vvv The following parts are identical to release.toml vvv

# Avoid linking with vcruntime140.dll by statically linking everything,
# and then explicitly linking with ucrtbase.dll dynamically.
# We do this, because vcruntime140.dll is an optional Windows component.
[target.'cfg(target_os = "windows")']
rustflags = [
    "-Ctarget-feature=+crt-static",
    "-Clink-args=/DEFAULTLIB:ucrt.lib",
    "-Clink-args=/NODEFAULTLIB:vcruntime.lib",
    "-Clink-args=/NODEFAULTLIB:msvcrt.lib",
    "-Clink-args=/NODEFAULTLIB:libucrt.lib",
]

# The backtrace code for panics in Rust is almost as large as the entire editor.
# = Huge reduction in binary size by removing all that.
[unstable]
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort", "optimize_for_size"]

# vvv The following parts are specific to official Windows builds. vvv
# (The use of internal registries, security features, etc., are mandatory.)

# Enable shadow stacks: https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat
[target.'cfg(all(target_os = "windows", any(target_arch = "x86", target_arch = "x86_64")))']
rustflags = ["-Clink-args=/DYNAMICBASE", "-Clink-args=/CETCOMPAT"]

[registries.Edit_PublicPackages]
index = "sparse+https://pkgs.dev.azure.com/microsoft/Dart/_packaging/Edit_PublicPackages/Cargo/index/"

[source.crates-io]
replace-with = "Edit_PublicPackages"


================================================
FILE: .cargo/release.toml
================================================
# The following is not used by default via .cargo/config.toml,
# because `build-std-features` cannot be keyed by profile.
# This breaks the bench profile which doesn't support panic=abort.
# See: https://github.com/rust-lang/cargo/issues/11214
# See: https://github.com/rust-lang/cargo/issues/13894

# Avoid linking with vcruntime140.dll by statically linking everything,
# and then explicitly linking with ucrtbase.dll dynamically.
# We do this, because vcruntime140.dll is an optional Windows component.
[target.'cfg(all(target_os = "windows", target_env = "msvc"))']
rustflags = [
    "-Ctarget-feature=+crt-static",
    "-Clink-args=/DEFAULTLIB:ucrt.lib",
    "-Clink-args=/NODEFAULTLIB:vcruntime.lib",
    "-Clink-args=/NODEFAULTLIB:msvcrt.lib",
    "-Clink-args=/NODEFAULTLIB:libucrt.lib",
]

# The backtrace code for panics in Rust is almost as large as the entire editor.
# = Huge reduction in binary size by removing all that.
[unstable]
build-std = ["std", "panic_abort"]
build-std-features = ["default", "panic_immediate_abort", "optimize_for_size"]


================================================
FILE: .devcontainer/devcontainer.json
================================================
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/rust
{
    "name": "Rust",
    "image": "mcr.microsoft.com/devcontainers/rust:1-1-bookworm"
}


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

env:
  CARGO_TERM_COLOR: always

jobs:
  check:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - ubuntu-latest
          - windows-latest
    steps:
      # The Windows runners have autocrlf enabled by default.
      - name: Disable git autocrlf
        run: git config --global core.autocrlf false
        if: matrix.os == 'windows-latest'
      - name: Checkout
        uses: actions/checkout@v4
      # https://github.com/actions/cache/blob/main/examples.md#rust---cargo
      # Depends on `Cargo.lock` --> Has to be after checkout.
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
      - name: Install Rust
        run: rustup toolchain install nightly --no-self-update --profile minimal --component rust-src,rustfmt,clippy
      - name: Check formatting
        run: cargo fmt --all -- --check
      - name: Run tests
        run: cargo test --all-features --all-targets
      - name: Run clippy
        run: cargo clippy --all-features --all-targets -- --no-deps --deny warnings


================================================
FILE: .github/workflows/winget.yml
================================================
name: Submit release to the WinGet community repository

on:
  release:
    types: [published]

jobs:
  publish-winget:
    name: Submit to WinGet repository

    # winget-create is only supported on Windows
    runs-on: windows-latest

    # winget-create will read the following environment variable to access the GitHub token needed for submitting a PR
    # See https://aka.ms/winget-create-token
    env:
      WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}

    # Only submit stable releases
    if: ${{ !github.event.release.prerelease }}
    steps:
      - name: Submit package using wingetcreate
        run: |
          # Get installer info from release event
          $assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
          $x64InstallerUrl = $assets | Where-Object -Property name -like '*x86_64-windows.zip' | Select-Object -ExpandProperty browser_download_url
          $arm64InstallerUrl = $assets | Where-Object -Property name -like '*aarch64-windows.zip' | Select-Object -ExpandProperty browser_download_url
          $packageVersion = (${{ toJSON(github.event.release.tag_name) }}).Trim('v')

          # Update package using wingetcreate
          curl.exe -JLO https://aka.ms/wingetcreate/latest
          .\wingetcreate.exe update Microsoft.Edit `
            --version $packageVersion `
            --urls $x64InstallerUrl $arm64InstallerUrl `
            --submit


================================================
FILE: .gitignore
================================================
.idea
.vs
*.profraw
lcov.info
target


================================================
FILE: .pipelines/release.yml
================================================
# Documentation:  https://aka.ms/obpipelines

trigger: none

parameters:
  - name: debug
    displayName: Enable debug output
    type: boolean
    default: false
  - name: official
    displayName: Whether to build Official or NonOfficial
    type: string
    default: NonOfficial
    values:
      - NonOfficial
      - Official
  - name: createvpack
    displayName: Enable vpack creation
    type: boolean
    default: false
  - name: buildPlatforms
    type: object
    default:
      - x86_64-pc-windows-msvc
      - aarch64-pc-windows-msvc

variables:
  system.debug: ${{parameters.debug}}
  WindowsContainerImage: onebranch.azurecr.io/windows/ltsc2022/vse2022:latest
  # CDP_DEFINITION_BUILD_COUNT is needed for onebranch.pipeline.version task.
  # See: https://aka.ms/obpipelines/versioning
  CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)]
  # LOAD BEARING - the vpack task fails without these
  ROOT: $(Build.SourcesDirectory)
  REPOROOT: $(Build.SourcesDirectory)
  OUTPUTROOT: $(REPOROOT)\out
  NUGET_XMLDOC_MODE: none

resources:
  repositories:
    - repository: GovernedTemplates
      type: git
      name: OneBranch.Pipelines/GovernedTemplates
      ref: refs/heads/main

extends:
  template: v2/Microsoft.${{parameters.official}}.yml@GovernedTemplates
  parameters:
    featureFlags:
      WindowsHostVersion:
        Version: 2022
        Network: R1
    platform:
      name: windows_undocked
      product: edit
    # https://aka.ms/obpipelines/cloudvault
    cloudvault:
      enabled: false
    # https://aka.ms/obpipelines/sdl
    globalSdl:
      binskim:
        # > Due to some legacy reasons, 1ES PT is scanning full sources directory
        # > for BinSkim tool instead of just scanning the output directory [...]
        scanOutputDirectoryOnly: true
      isNativeCode: true
      tsa:
        enabled: ${{eq(parameters.official, 'Official')}}
        configFile: "$(Build.SourcesDirectory)/.pipelines/tsa.json"
    stages:
      # Our Build stage will build all three targets in one job, so we don't need
      # to repeat most of the boilerplate work in three separate jobs.
      - stage: Build
        jobs:
          - job: Windows
            pool:
              type: windows
            variables:
              # Binaries will go here.
              # More settings at https://aka.ms/obpipelines/yaml/jobs
              ob_outputDirectory: "$(Build.SourcesDirectory)/out"
              # The vPack gets created from stuff in here.
              # It will have a structure like:
              # .../vpack/
              #      - amd64/
              #         - edit.exe
              #      - i386/
              #         - edit.exe
              #      - arm64/
              #         - edit.exe
              ob_createvpack_enabled: ${{parameters.createvpack}}
              ob_createvpack_vpackdirectory: "$(ob_outputDirectory)/vpack"
              ob_createvpack_packagename: "windows_edit.$(Build.SourceBranchName)"
              ob_createvpack_owneralias: lhecker@microsoft.com
              ob_createvpack_description: Microsoft Edit
              ob_createvpack_targetDestinationDirectory: "$(Destination)"
              ob_createvpack_propsFile: false
              ob_createvpack_provData: true
              ob_createvpack_versionAs: string
              ob_createvpack_version: "$(EditVersion)-$(CDP_DEFINITION_BUILD_COUNT)"
              ob_createvpack_metadata: "$(Build.SourceVersion)"
              ob_createvpack_topLevelRetries: 0
              ob_createvpack_failOnStdErr: true
              ob_createvpack_verbose: ${{ parameters.debug }}
              # For details on this cargo_target_dir setting, see:
              # https://eng.ms/docs/more/rust/topics/onebranch-workaround
              CARGO_TARGET_DIR: C:\cargo_target_dir
              # msrustup only supports stable toolchains, but this project requires nightly.
              # We were told RUSTC_BOOTSTRAP=1 is a supported workaround.
              RUSTC_BOOTSTRAP: 1
            steps:
              # NOTE: Step objects have ordered keys and you MUST have "task" as the first key.
              # Objects with ordered keys... lol
              - task: RustInstaller@1
                displayName: Install Rust toolchain
                inputs:
                  rustVersion: ms-stable
                  additionalTargets: x86_64-pc-windows-msvc aarch64-pc-windows-msvc
                  # URL of an Azure Artifacts feed configured with a crates.io upstream. Must be within the current ADO collection.
                  # NOTE: Azure Artifacts support for Rust is not yet public, but it is enabled for internal ADO organizations.
                  # https://learn.microsoft.com/en-us/azure/devops/artifacts/how-to/set-up-upstream-sources?view=azure-devops
                  cratesIoFeedOverride: sparse+https://pkgs.dev.azure.com/microsoft/Dart/_packaging/Edit_PublicPackages/Cargo/index/
                  # URL of an Azure Artifacts NuGet feed configured with the mscodehub Rust feed as an upstream.
                  # * The feed must be within the current ADO collection.
                  # * The CI account, usually "Project Collection Build Service (org-name)", must have at least "Collaborator" permission.
                  # When setting up the upstream NuGet feed, use following Azure Artifacts feed locator:
                  #   azure-feed://mscodehub/Rust/Rust@Release
                  toolchainFeed: https://pkgs.dev.azure.com/microsoft/_packaging/RustTools/nuget/v3/index.json
              - task: CargoAuthenticate@0
                displayName: Authenticate with Azure Artifacts
                inputs:
                  configFile: ".cargo/release-windows-ms.toml"
              # We recommend making a separate `cargo fetch` step, as some build systems perform
              # fetching entirely prior to the build, and perform the build with the network disabled.
              - script: cargo fetch --config .cargo/release-windows-ms.toml
                displayName: Fetch crates
              - ${{ each platform in parameters.buildPlatforms }}:
                  - script: cargo build --config .cargo/release-windows-ms.toml --frozen --release --target ${{platform}}
                    displayName: Build ${{platform}} Release
                  - task: CopyFiles@2
                    displayName: Copy files to vpack (${{platform}})
                    inputs:
                      sourceFolder: "$(CARGO_TARGET_DIR)/${{platform}}/release"
                      ${{ if eq(platform, 'i686-pc-windows-msvc') }}:
                        targetFolder: "$(ob_createvpack_vpackdirectory)/i386"
                      ${{ elseif eq(platform, 'x86_64-pc-windows-msvc') }}:
                        targetFolder: "$(ob_createvpack_vpackdirectory)/amd64"
                      ${{ else }}: # aarch64-pc-windows-msvc
                        targetFolder: "$(ob_createvpack_vpackdirectory)/arm64"
                      contents: |
                        *.exe
                        *.pdb
              # Extract the version for `ob_createvpack_version`.
              - script: |-
                  @echo off
                  for /f "tokens=3 delims=- " %%x in ('findstr /c:"version = " Cargo.toml') do (
                      echo ##vso[task.setvariable variable=EditVersion]%%~x
                      goto :EOF
                  )
                displayName: "Set EditVersion"
              - task: onebranch.pipeline.signing@1
                displayName: "Sign files"
                inputs:
                  command: "sign"
                  signing_profile: "external_distribution"
                  files_to_sign: "**/edit.exe"
                  search_root: "$(ob_createvpack_vpackdirectory)"
                  use_testsign: false
                  in_container: true

              - ${{ each platform in parameters.buildPlatforms }}:
                - pwsh: |-
                    $Dest = New-Item -Type Directory "_staging/${env:RELEASE_NAME}"
                    Write-Host "Staging files from ${env:VPACK_ROOT} at $Dest"
                    Get-ChildItem "${env:VPACK_ROOT}\*" -Include *.exe, *.pdb | Copy-Item -Destination $Dest -Verbose
                    tar.exe -c -v --format=zip -f "$(ob_outputDirectory)\${env:RELEASE_NAME}.zip" -C _staging $env:RELEASE_NAME
                  env:
                    RELEASE_NAME: edit-$(EditVersion)-${{ replace(platform, 'pc-windows-msvc', 'windows') }}
                    ${{ if eq(platform, 'i686-pc-windows-msvc') }}:
                      VPACK_ROOT: "$(ob_createvpack_vpackdirectory)/i386"
                    ${{ elseif eq(platform, 'x86_64-pc-windows-msvc') }}:
                      VPACK_ROOT: "$(ob_createvpack_vpackdirectory)/amd64"
                    ${{ else }}: # aarch64-pc-windows-msvc
                      VPACK_ROOT: "$(ob_createvpack_vpackdirectory)/arm64"
                  displayName: Produce ${{platform}} release archive


================================================
FILE: .pipelines/tsa.json
================================================
{
    "instanceUrl": "https://microsoft.visualstudio.com",
    "projectName": "OS",
    "areaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SHINE\\Commandline Tooling",
    "notificationAliases": ["condev@microsoft.com", "duhowett@microsoft.com"],
    "template": "VSTS_Microsoft_OSGS"
}


================================================
FILE: .vscode/launch.json
================================================
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch edit (Windows)",
            "preLaunchTask": "rust: cargo build",
            "type": "cppvsdbg",
            "request": "launch",
            "console": "externalTerminal",
            "program": "${workspaceFolder}/target/debug/edit",
            "cwd": "${workspaceFolder}",
            "args": [
                "${workspaceFolder}/crates/edit/src/bin/edit/main.rs"
            ],
        },
        {
            "name": "Launch edit (GDB, Linux)",
            "preLaunchTask": "rust: cargo build",
            "type": "cppdbg",
            "request": "launch",
            "miDebuggerPath": "rust-gdb",
            "externalConsole": true,
            "program": "${workspaceFolder}/target/debug/edit",
            "cwd": "${workspaceFolder}",
            "args": [
                "${workspaceFolder}/crates/edit/src/bin/edit/main.rs"
            ],
        },
        {
            // NOTE for macOS: In order for this task to work you have to:
            // 1. Run the "Fix externalConsole on macOS" task once
            // 2. Add the following to your VS Code settings:
            //    "lldb-dap.environment": {
            //        "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES"
            //    }
            "name": "Launch edit (lldb-dap, macOS)",
            "preLaunchTask": "rust: cargo build",
            "type": "lldb-dap",
            "request": "launch",
            "program": "${workspaceFolder}/target/debug/edit",
            "cwd": "${workspaceFolder}",
            "args": [
                "${workspaceFolder}/crates/edit/src/bin/edit/main.rs"
            ],
        },
        {
            // This is a workaround for https://github.com/microsoft/vscode-cpptools/issues/5079
            "name": "Fix externalConsole on macOS",
            "type": "node-terminal",
            "request": "launch",
            "command": "osascript -e 'tell application \"Terminal\"\ndo script \"echo hello\"\nend tell'"
        },
    ]
}


================================================
FILE: .vscode/tasks.json
================================================
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "rust: cargo build",
            "type": "process",
            "command": "cargo",
            "args": [
                "build",
                "--package",
                "edit",
                "--features",
                "debug-latency"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$rustc"
            ]
        }
    ]
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Microsoft Open Source Code of Conduct

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).

Resources:

- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
- Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support)


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

## Translation improvements

You can find our translations in [`i18n/edit.toml`](./i18n/edit.toml).
Please feel free to open a pull request with your changes at any time.
If you'd like to discuss your changes first, please feel free to open an issue.

## Bug reports

If you find any bugs, we gladly accept pull requests without prior discussion.
Otherwise, you can of course always open an issue for us to look into.

## Feature requests

Please open a new issue for any feature requests you have in mind.
Keeping the binary size of the editor small is a priority for us and so we may need to discuss any new features first until we have support for plugins.

## Code changes

The project has a focus on a small binary size and sufficient (good) performance.
As such, we generally do not accept pull requests that introduce dependencies (there are always exceptions of course).
Otherwise, you can consider this project a playground for trying out any cool ideas you have.

The overall architecture of the project can be summarized as follows:
* The underlying text buffer in `src/buffer` doesn't keep track of line breaks in the document.
  This is a crucial design aspect that permeates throughout the entire codebase.

  To oversimplify, the *only* state that is kept is the current cursor position.
  When the user asks to move to another line, the editor will `O(n)` seek through the underlying document until it found the corresponding number of line breaks.
  * As a result, `src/simd` contains crucial `memchr2` functions to quickly find the next or previous line break (runs at up to >100GB/s).
  * Furthermore, `src/unicode` implements an `Utf8Chars` iterator which transparently inserts U+FFFD replacements during iteration (runs at up to 4GB/s).
  * Furthermore, `src/unicode` also implements grapheme cluster segmentation and cluster width measurement via its `MeasurementConfig` (runs at up to 600MB/s).
  * If word wrap is disabled, `memchr2` is used for all navigation across lines, allowing us to breeze through 1GB large files as if they were 1MB.
  * Even if word-wrap is enabled, it's still sufficiently smooth thanks to `MeasurementConfig`. This is only possible because these base functions are heavily optimized.
* `src/framebuffer.rs` implements a "framebuffer" like in video games.
  It allows us to draw the UI output into an intermediate buffer first, accumulating all changes and handling things like color blending.
  Then, it can compare the accumulated output with the previous frame and only send the necessary changes to the terminal.
* `src/tui.rs` implements an immediate mode UI. Its module implementation gives an overview how it works and I recommend reading it.
* `src/vt.rs` implements our VT parser.
* `src/sys` contains our platform abstractions.
* Finally, `src/bin/edit` ties everything together.
  It's roughly 90% UI code and business logic.
  It contains a little bit of VT logic in `setup_terminal`.

If you have an issue with your terminal, the places of interest are the aforementioned:
* VT parser in `src/vt.rs`
* Platform specific code in `src/sys`
* And the `setup_terminal` function in `src/bin/edit/main.rs`


================================================
FILE: Cargo.toml
================================================
[workspace]
default-members = ["crates/edit"]
members = ["crates/*"]
resolver = "2"

[workspace.package]
edition = "2024"
license = "MIT"
repository = "https://github.com/microsoft/edit"
rust-version = "1.93"

# We use `opt-level = "s"` as it significantly reduces binary size.
# We could then use the `#[optimize(speed)]` attribute for spot optimizations.
# Unfortunately, that attribute currently doesn't work on intrinsics such as memset.
[profile.release]
codegen-units = 1           # reduces binary size by ~2%
debug = "full"              # No one needs an undebuggable release binary
lto = true                  # reduces binary size by ~14%
opt-level = "s"             # reduces binary size by ~25%
panic = "abort"             # reduces binary size by ~50% in combination with -Zbuild-std-features=panic_immediate_abort
split-debuginfo = "packed"  # generates a separate *.dwp/*.dSYM so the binary can get stripped
strip = "symbols"           # See split-debuginfo - allows us to drop the size by ~65%
incremental = true          # Improves re-compile times

[profile.bench]
codegen-units = 16          # Make compiling criterion faster (16 is the default, but profile.release sets it to 1)
lto = "thin"                # Similarly, speed up linking by a ton

[workspace.dependencies]
edit = { path = "./crates/edit" }
stdext = { path = "./crates/stdext" }
unicode-gen = { path = "./crates/unicode-gen" }


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) Microsoft Corporation. All rights reserved.

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:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

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.


================================================
FILE: README.md
================================================
# ![Application Icon for Edit](./assets/edit.svg) Edit

A simple editor for simple needs.

This editor pays homage to the classic [MS-DOS Editor](https://en.wikipedia.org/wiki/MS-DOS_Editor), but with a modern interface and input controls similar to VS Code. The goal is to provide an accessible editor that even users largely unfamiliar with terminals can easily use.

![Screenshot of Edit with the About dialog in the foreground](./assets/edit_hero_image.png)

## Installation

[![Packaging status](https://repology.org/badge/vertical-allrepos/microsoft-edit.svg?exclude_unsupported=1)](https://repology.org/project/microsoft-edit/versions)

You can also download binaries from [our Releases page](https://github.com/microsoft/edit/releases/latest).

### Windows

You can install the latest version with WinGet:
```powershell
winget install Microsoft.Edit
```

## Build Instructions

* [Install Rust](https://www.rust-lang.org/tools/install)
* Install the nightly toolchain: `rustup install nightly`
  * Alternatively, set the environment variable `RUSTC_BOOTSTRAP=1`
* Clone the repository
* For a release build, run:
  * Rust 1.90 or earlier: `cargo build --config .cargo/release.toml --release`
  * otherwise: `cargo build --config .cargo/release-nightly.toml --release`

### Build Configuration

During compilation you can set various environment variables to configure the build. The following table lists the available configuration options:

Environment variable | Description
--- | ---
`EDIT_CFG_ICU*` | See [ICU library name (SONAME)](#icu-library-name-soname) for details.
`EDIT_CFG_LANGUAGES` | A comma-separated list of languages to include in the build. See [i18n/edit.toml](i18n/edit.toml) for available languages.

## Notes to Package Maintainers

### Package Naming

The canonical executable name is "edit" and the alternative name is "msedit".
We're aware of the potential conflict of "edit" with existing commands and recommend alternatively naming packages and executables "msedit".
Names such as "ms-edit" should be avoided.
Assigning an "edit" alias is recommended, if possible.

### ICU library name (SONAME)

This project _optionally_ depends on the ICU library for its Search and Replace functionality.
By default, the project will look for a SONAME without version suffix:
* Windows: `icuuc.dll`
* macOS: `libicuuc.dylib`
* UNIX, and other OS: `libicuuc.so`

If your installation uses a different SONAME, please set the following environment variable at build time:
* `EDIT_CFG_ICUUC_SONAME`:
  For instance, `libicuuc.so.76`.
* `EDIT_CFG_ICUI18N_SONAME`:
  For instance, `libicui18n.so.76`.

Additionally, this project assumes that the ICU exports are exported without `_` prefix and without version suffix, such as `u_errorName`.
If your installation uses versioned exports, please set:
* `EDIT_CFG_ICU_CPP_EXPORTS`:
  If set to `true`, it'll look for C++ symbols such as `_u_errorName`.
  Enabled by default on macOS.
* `EDIT_CFG_ICU_RENAMING_VERSION`:
  If set to a version number, such as `76`, it'll look for symbols such as `u_errorName_76`.

Finally, you can set the following environment variables:
* `EDIT_CFG_ICU_RENAMING_AUTO_DETECT`:
  If set to `true`, the executable will try to detect the `EDIT_CFG_ICU_RENAMING_VERSION` value at runtime.
  The way it does this is not officially supported by ICU and as such is not recommended to be relied upon.
  Enabled by default on UNIX (excluding macOS) if no other options are set.

To test your settings, run `cargo test` again but with the `--ignored` flag. For instance:
```sh
cargo test -- --ignored
```


================================================
FILE: SECURITY.md
================================================
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->

## Security

Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).

If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.

## Reporting Security Issues

**Please do not report security vulnerabilities through public GitHub issues.**

Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).

If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).

You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).

Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:

  * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
  * Full paths of source file(s) related to the manifestation of the issue
  * The location of the affected source code (tag/branch/commit or direct URL)
  * Any special configuration required to reproduce the issue
  * Step-by-step instructions to reproduce the issue
  * Proof-of-concept or exploit code (if possible)
  * Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.

## Preferred Languages

We prefer all communications to be in English.

## Policy

Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).

<!-- END MICROSOFT SECURITY.MD BLOCK -->


================================================
FILE: assets/com.microsoft.edit.desktop
================================================
[Desktop Entry]
Type=Application
Name=Microsoft Edit
GenericName=Text Editor
Comment=A simple editor for simple needs
Icon=edit
Exec=edit %F
Terminal=true
Categories=Utility;TextEditor;
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Keywords=text;editor


================================================
FILE: assets/editing-traces/README.md
================================================
# editing-traces

This directory contains Seph Gentle's ASCII-only `rustcode` editing traces from: https://github.com/josephg/editing-traces

The trace was provided under the [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) license.


================================================
FILE: assets/highlighting-tests/json.json
================================================
{
    // Object with various value types
    "string": "Hello, world!", // string literal
    "numberInt": 42, // integer number
    "numberFloat": -3.14e+2, // floating point with exponent
    "booleanTrue": true, // boolean true
    "booleanFalse": false, // boolean false
    "nullValue": null, // null literal
    "array": [
        "item1", // string in array
        2, // number in array
        false, // boolean in array
        null, // null in array
        {
            "nested": "object"
        } // object in array
    ],
    "emptyObject": {}, // empty object
    "emptyArray": [], // empty array
    /* Multi-line comment:
         This is a block comment
         inside JSONC.
    */
    "unicodeString": "Emoji: \uD83D\uDE03", // Unicode escape
    "escapedChars": "Line1\nLine2\tTabbed\\Backslash\"Quote" // Escaped characters
}


================================================
FILE: assets/manpage/edit.1
================================================
.TH EDIT 1 "version 1.2.1" "December 2025"
.SH NAME
edit \- a simple text editor
.SH SYNOPSIS
\fBedit\fP [\fIOPTIONS\fP]... [\fIARGUMENTS\fP]...
.SH DESCRIPTION
edit is a simple text editor inspired by MS-DOS edit.
.SH EDITING
Edit is an interactive mode-less editor. Use F10 to access the menus.
.SH ARGUMENTS
.TP
\fIFILE[:LINE[:COLUMN]]\fP
The file to open, optionally with line and column (e.g., \fBfoo.txt:123:45\fP).
.SH OPTIONS
.TP
\fB\-h\fP, \fB\-\-help\fP
Print the help message.
.TP
\fB\-v\fP, \fB\-\-version\fP
Print the version number.
.SH COPYRIGHT
Copyright \(co Microsoft Corporation.
.br
Licensed under the MIT License.
.SH SEE ALSO
.UR https://github.com/microsoft/edit
.UE


================================================
FILE: assets/microsoft.sixel
================================================
P;1q"1;1;300;60#0;2;100;100;100#0!42?_ow{}!12?_ow{}!6?_ow{}}!5?_ow{{}}}!17~^NFbpw{}!8~!4}{wwo_!12?_oow{{{!4}!6~!4}{{wwo__!4?_ow{{}}}!23~^Nfrxw{{}}}!9~!4}{{woo_!12?_ow{}!15~^NFbpw{}!17~^NFB@-!36?_ow{}!6~!6?_ow{}!6~??w{}!7~?o{}!10~^^!10NFBpw{}!6~!8N^!9~{_!4?_o{}!8~^^!9N^^!9~{w}!8~^!18NFbx{}!9~^^!8N^^!9~}{o???ow{}!6~!11NFB@GKM!5N!10~!4NFB@-!30?_ow{}!12~_ow{}!12~??!20~FB@!15?!10~!10?r!9~???{!8~NB@!15?@FN!16~!4{!4wooo__!5?_}!8~^FB!16?@F^!8~{o!10~!9o!13?!10~-!24?_ow{}!35~??!19~x!18?!10~?CK[!4{}!9~^B??N!8~x!21?!10~N^^!18~}{o!10~!22?!29~!13?!10~-!18?_ow{}!8~^NFB@?!11~^NFB@?!10~??!10~F!9~}{wo__!12?!10~!5?@BFN^!9~}{wof^!7~}wo__!11?__o{!9~N@!7?!6@Bb!10~N!9~{o__!12?__o{}!8~F@!10~!9B!13?!10~-!12?_ow{}!8~^NFB@!7?!5~^NFB@!7?!10~??!10~??@FN^!20~??!10~!11?@BFN^!23~!7}!10~^NFB~!12}!12~^NB??BFN^!9~!10}!9~^NF@???!10~!22?!5~^NFB@-!6?_ow{}!8~^NFB@!13?FFB@!13?!10F??!10F!7?@@BB!15F??!10F!17?@BFN^!10~|zrfFF!10NFFFBB@@!5?!21FBB@!11?@BBFFNNN!10^NNNFFBB@!8?!10~!22?NFB@-_ow{}!8~^NFB@!119?@BFN^!9~}{wo!88?!10~-!7~^NFB@!131?@BFN^!7~!88?!7~^NF-~^NFB@!143?@BFN^~!88?~^NFB@\


================================================
FILE: assets/snapcraft.yaml
================================================
name: msedit
base: core24
version: '1.2.1'
summary: Edit is an MS-DOS inspired text editor from Microsoft
description: |
  Edit pays homage to the classic MS-DOS Editor, but with a modern interface and input controls similar to VS Code. Learn more at https://github.com/microsoft/edit

  Disclaimer: This is an unofficial Snap and it is not endorsed by nor affiliated officially with Microsoft Corporation.

grade: stable
confinement: strict

apps:
  msedit:
    command: bin/edit
    plugs:
      - home

parts:
  edit:
    source: https://github.com/microsoft/edit.git
    source-type: git
    plugin: rust
    build-packages:
      - build-essential


================================================
FILE: crates/edit/Cargo.toml
================================================
[package]
name = "edit"
version = "1.2.1"

edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true

build = "build/main.rs"
categories = ["text-editors"]

[[bench]]
name = "lib"
harness = false

[features]
# Display editor latency in the top-right corner
debug-latency = []

[dependencies]
stdext.workspace = true

[target.'cfg(unix)'.dependencies]
libc = "0.2"

[build-dependencies]
stdext.workspace = true
# The default toml crate bundles its dependencies with bad compile times. Thanks.
# Thankfully toml-span exists. FWIW the alternative is yaml-rust (without the 2 suffix).
toml-span = { version = "0.6", default-features = false }

[target.'cfg(windows)'.build-dependencies]
winresource = { version = "0.1", default-features = false }

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.61"
features = [
    "Win32_Globalization",
    "Win32_Security",
    "Win32_Storage_FileSystem",
    "Win32_System_Console",
    "Win32_System_IO",
    "Win32_System_LibraryLoader",
    "Win32_System_Threading",
]

[dev-dependencies]
criterion = { version = "0.8", features = ["html_reports"] }
zstd = { version = "0.13", default-features = false }


================================================
FILE: crates/edit/benches/lib.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::hint::black_box;
use std::io::Cursor;
use std::{mem, vec};

use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main};
use edit::helpers::*;
use edit::{buffer, glob, hash, json, oklab, simd, unicode};
use stdext::arena::{self, scratch_arena};
use stdext::collections::BVec;
use stdext::unicode::Utf8Chars;

struct EditingTracePatch<'a>(usize, usize, &'a str);

struct EditingTraceTransaction<'a> {
    patches: BVec<'a, EditingTracePatch<'a>>,
}

struct EditingTraceData<'a> {
    start_content: &'a str,
    end_content: &'a str,
    txns: BVec<'a, EditingTraceTransaction<'a>>,
}

fn bench_buffer(c: &mut Criterion) {
    let scratch = scratch_arena(None);
    let data = {
        let data = include_bytes!("../../../assets/editing-traces/rustcode.json.zst");
        let data = zstd::decode_all(Cursor::new(data)).unwrap();
        let data = str::from_utf8(&data).unwrap();

        let data = json::parse(&scratch, data).unwrap();
        let root = data.as_object().unwrap();
        let txns = root.get_array("txns").unwrap();

        let mut res = EditingTraceData {
            start_content: root.get_str("startContent").unwrap(),
            end_content: root.get_str("endContent").unwrap(),
            txns: BVec::empty(),
        };
        res.txns.reserve(&*scratch, txns.len());

        for txn in txns {
            let txn = txn.as_object().unwrap();
            let patches = txn.get_array("patches").unwrap();
            let mut txn = EditingTraceTransaction { patches: BVec::empty() };
            txn.patches.reserve(&*scratch, patches.len());

            for patch in patches {
                let patch = patch.as_array().unwrap();
                let offset = patch[0].as_number().unwrap() as usize;
                let del_len = patch[1].as_number().unwrap() as usize;
                let ins_str = patch[2].as_str().unwrap();
                txn.patches.push(&*scratch, EditingTracePatch(offset, del_len, ins_str));
            }

            res.txns.push(&*scratch, txn);
        }

        res
    };

    let mut patches_with_coords = Vec::new();
    {
        let mut tb = buffer::TextBuffer::new(false).unwrap();
        tb.set_crlf(false);
        tb.write_raw(data.start_content.as_bytes());

        for t in &data.txns {
            for p in &t.patches {
                tb.cursor_move_to_offset(p.0);
                let beg = tb.cursor_logical_pos();

                tb.delete(buffer::CursorMovement::Grapheme, p.1 as CoordType);

                tb.write_raw(p.2.as_bytes());
                patches_with_coords.push((beg, p.1 as CoordType, p.2));
            }
        }

        let mut actual = String::new();
        tb.save_as_string(&mut actual);
        assert_eq!(actual, data.end_content);
    }

    let bench_gap_buffer = || {
        let mut buf = buffer::GapBuffer::new(false).unwrap();
        buf.replace(0..usize::MAX, data.start_content.as_bytes());

        for t in &data.txns {
            for p in &t.patches {
                buf.replace(p.0..p.0 + p.1, p.2.as_bytes());
            }
        }

        buf
    };

    let bench_text_buffer = || {
        let mut tb = buffer::TextBuffer::new(false).unwrap();
        tb.set_crlf(false);
        tb.write_raw(data.start_content.as_bytes());

        for p in &patches_with_coords {
            tb.cursor_move_to_logical(p.0);
            tb.delete(buffer::CursorMovement::Grapheme, p.1);
            tb.write_raw(p.2.as_bytes());
        }

        tb
    };

    // Sanity check: If this fails, the implementation is incorrect.
    {
        let buf = bench_gap_buffer();
        let mut actual = Vec::new();
        buf.extract_raw(0..usize::MAX, &mut actual, 0);
        assert_eq!(actual, data.end_content.as_bytes());
    }
    {
        let mut tb = bench_text_buffer();
        let mut actual = String::new();
        tb.save_as_string(&mut actual);
        assert_eq!(actual, data.end_content);
    }

    c.benchmark_group("buffer")
        .bench_function(BenchmarkId::new("GapBuffer", "rustcode"), |b| {
            b.iter(bench_gap_buffer);
        })
        .bench_function(BenchmarkId::new("TextBuffer", "rustcode"), |b| {
            b.iter(bench_text_buffer);
        });
}

fn bench_glob(c: &mut Criterion) {
    // Same benchmark as in glob-match
    const PATH: &str = "foo/bar/foo/bar/foo/bar/foo/bar/foo/bar.txt";
    const GLOB: &str = "foo/**/bar.txt";

    c.benchmark_group("glob")
        .bench_function("glob_match", |b| b.iter(|| assert!(glob::glob_match(GLOB, PATH))));
}

fn bench_hash(c: &mut Criterion) {
    c.benchmark_group("hash")
        .throughput(Throughput::Bytes(8))
        .bench_function(BenchmarkId::new("hash", 8), |b| {
            let data = [0u8; 8];
            b.iter(|| hash::hash(0, black_box(&data)))
        })
        .throughput(Throughput::Bytes(16))
        .bench_function(BenchmarkId::new("hash", 16), |b| {
            let data = [0u8; 16];
            b.iter(|| hash::hash(0, black_box(&data)))
        })
        .throughput(Throughput::Bytes(1024))
        .bench_function(BenchmarkId::new("hash", 1024), |b| {
            let data = [0u8; 1024];
            b.iter(|| hash::hash(0, black_box(&data)))
        });
}

fn bench_json(c: &mut Criterion) {
    let str = include_str!("../../../assets/highlighting-tests/json.json");

    c.benchmark_group("json").throughput(Throughput::Bytes(str.len() as u64)).bench_function(
        "parse",
        |b| {
            b.iter(|| {
                let scratch = scratch_arena(None);
                let obj = json::parse(&scratch, black_box(str)).unwrap();
                black_box(obj);
            })
        },
    );
}

fn bench_oklab(c: &mut Criterion) {
    c.benchmark_group("oklab")
        .bench_function("StraightRgba::as_oklab", |b| {
            b.iter(|| black_box(oklab::StraightRgba::from_le(0xff212cbe)).as_oklab())
        })
        .bench_function("StraightRgba::oklab_blend", |b| {
            b.iter(|| {
                black_box(oklab::StraightRgba::from_le(0x7f212cbe))
                    .oklab_blend(black_box(oklab::StraightRgba::from_le(0x7f3aae3f)))
            })
        });
}

fn bench_simd_lines_fwd(c: &mut Criterion) {
    let mut group = c.benchmark_group("simd");
    let buf = vec![b'\n'; 128 * MEBI];

    for &lines in &[1, 8, 128, KIBI, 128 * KIBI, 128 * MEBI] {
        group.throughput(Throughput::Bytes(lines as u64)).bench_with_input(
            BenchmarkId::new("lines_fwd", lines),
            &lines,
            |b, &lines| {
                b.iter(|| simd::lines_fwd(black_box(&buf), 0, 0, lines as CoordType));
            },
        );
    }
}

fn bench_simd_memchr2(c: &mut Criterion) {
    let mut group = c.benchmark_group("simd");
    let mut buf = vec![0u8; 128 * MEBI + KIBI];

    // For small sizes we add a small offset of +8,
    // to ensure we also benchmark the non-SIMD tail handling.
    // For large sizes, its relative impact is negligible.
    for &bytes in &[8usize, 128 + 8, KIBI, 128 * KIBI, 128 * MEBI] {
        group.throughput(Throughput::Bytes(bytes as u64 + 1)).bench_with_input(
            BenchmarkId::new("memchr2", bytes),
            &bytes,
            |b, &size| {
                buf.fill(b'a');
                buf[size] = b'\n';
                b.iter(|| simd::memchr2(b'\n', b'\r', black_box(&buf), 0));
            },
        );
    }
}

fn bench_simd_memset<T: Copy + Default>(c: &mut Criterion) {
    let mut group = c.benchmark_group("simd");
    let name = format!("memset<{}>", std::any::type_name::<T>());
    let size = mem::size_of::<T>();
    let mut buf: Vec<T> = vec![Default::default(); 128 * MEBI / size];

    // For small sizes we add a small offset of +8,
    // to ensure we also benchmark the non-SIMD tail handling.
    // For large sizes, its relative impact is negligible.
    for &bytes in &[8usize, 128 + 8, KIBI, 128 * KIBI, 128 * MEBI] {
        group.throughput(Throughput::Bytes(bytes as u64)).bench_with_input(
            BenchmarkId::new(&name, bytes),
            &bytes,
            |b, &bytes| {
                let slice = unsafe { buf.get_unchecked_mut(..bytes / size) };
                b.iter(|| stdext::simd::memset(black_box(slice), Default::default()));
            },
        );
    }
}

fn bench_unicode(c: &mut Criterion) {
    let reference = concat!(
        "In the quiet twilight, dreams unfold, soft whispers of a story untold.\n",
        "月明かりが静かに照らし出し、夢を見る心の奥で詩が静かに囁かれる\n",
        "Stars collide in the early light of hope, echoing the silent call of the night.\n",
        "夜の静寂、希望と孤独が混ざり合うその中で詩が永遠に続く\n",
    );
    let buffer = reference.repeat(10);
    let bytes = buffer.as_bytes();

    c.benchmark_group("unicode::MeasurementConfig::goto_logical")
        .throughput(Throughput::Bytes(bytes.len() as u64))
        .bench_function("basic", |b| {
            b.iter(|| unicode::MeasurementConfig::new(&bytes).goto_logical(Point::MAX))
        })
        .bench_function("word_wrap", |b| {
            b.iter(|| {
                unicode::MeasurementConfig::new(black_box(&bytes))
                    .with_word_wrap_column(50)
                    .goto_logical(Point::MAX)
            })
        });

    c.benchmark_group("unicode::Utf8Chars")
        .throughput(Throughput::Bytes(bytes.len() as u64))
        .bench_function("next", |b| {
            b.iter(|| Utf8Chars::new(bytes, 0).fold(0u32, |acc, ch| acc.wrapping_add(ch as u32)))
        });
}

fn bench(c: &mut Criterion) {
    arena::init(128 * MEBI).unwrap();

    bench_buffer(c);
    bench_glob(c);
    bench_hash(c);
    bench_json(c);
    bench_oklab(c);
    bench_simd_lines_fwd(c);
    bench_simd_memchr2(c);
    bench_simd_memset::<u32>(c);
    bench_simd_memset::<u8>(c);
    bench_unicode(c);
}

criterion_group!(benches, bench);
criterion_main!(benches);


================================================
FILE: crates/edit/build/helpers.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::env::VarError;

pub fn env_opt(name: &str) -> String {
    match std::env::var(name) {
        Ok(value) => value,
        Err(VarError::NotPresent) => String::new(),
        Err(VarError::NotUnicode(_)) => {
            panic!("Environment variable `{name}` is not valid Unicode")
        }
    }
}


================================================
FILE: crates/edit/build/i18n.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt::Write as _;

use crate::helpers::env_opt;

pub fn generate(definitions: &str) -> String {
    let i18n = toml_span::parse(definitions).expect("Failed to parse i18n file");
    let root = i18n.as_table().unwrap();
    let mut languages = Vec::new();
    let mut aliases = Vec::new();
    let mut translations: BTreeMap<String, HashMap<String, String>> = BTreeMap::new();

    for (k, v) in root.iter() {
        match &k.name[..] {
            "__default__" => {
                const ERROR: &str = "i18n: __default__ must be [str]";
                languages = Vec::from_iter(
                    v.as_array()
                        .expect(ERROR)
                        .iter()
                        .map(|lang| lang.as_str().expect(ERROR).to_string()),
                );
            }
            "__alias__" => {
                const ERROR: &str = "i18n: __alias__ must be str->str";
                aliases.extend(v.as_table().expect(ERROR).iter().map(|(alias, lang)| {
                    (alias.to_string(), lang.as_str().expect(ERROR).to_string())
                }));
            }
            _ => {
                const ERROR: &str = "i18n: LocId must be str->str";
                translations.insert(
                    k.name.to_string(),
                    HashMap::from_iter(
                        v.as_table().expect(ERROR).iter().map(|(k, v)| {
                            (k.name.to_string(), v.as_str().expect(ERROR).to_string())
                        }),
                    ),
                );
            }
        }
    }

    // Use EDIT_CFG_LANGUAGES for the language list if it is set.
    if let cfg_languages = env_opt("EDIT_CFG_LANGUAGES")
        && !cfg_languages.is_empty()
    {
        languages = cfg_languages.split(',').map(|lang| lang.to_string()).collect();
    }

    // Ensure English as the fallback language is always present.
    if !languages.iter().any(|l| l == "en") {
        languages.push("en".to_string());
    }

    // Normalize language tags for use in source code (i.e. no "-").
    for lang in &mut languages {
        if lang.is_empty() {
            panic!("i18n: empty language tag");
        }
        for c in unsafe { lang.as_bytes_mut() } {
            *c = match *c {
                b'A'..=b'Z' | b'a'..=b'z' => c.to_ascii_lowercase(),
                b'-' => b'_',
                b'_' => b'_',
                _ => panic!("i18n: language tag \"{lang}\" must be [a-zA-Z_-]"),
            }
        }
    }

    // * Validate that there are no duplicate language tags.
    // * Validate that all language tags are valid.
    // * Merge the aliases into the languages list.
    let mut languages_with_aliases: Vec<_>;
    {
        let mut specified = HashSet::new();
        for lang in &languages {
            if !specified.insert(lang.as_str()) {
                panic!("i18n: duplicate language tag \"{lang}\"");
            }
        }

        let mut available = HashSet::new();
        for v in translations.values() {
            for lang in v.keys() {
                available.insert(lang.as_str());
            }
        }

        let mut invalid = Vec::new();
        for lang in &languages {
            if !available.contains(lang.as_str()) {
                invalid.push(lang.as_str());
            }
        }
        if !invalid.is_empty() {
            panic!("i18n: invalid language tags {invalid:?}");
        }

        languages_with_aliases = languages.iter().map(|l| (l.clone(), l.clone())).collect();
        for (alias, lang) in aliases {
            if specified.contains(lang.as_str()) && !specified.contains(alias.as_str()) {
                languages_with_aliases.push((alias, lang));
            }
        }
    }

    // Sort languages by:
    // - "en" first, because it'll map to `LangId::en == 0`, which is the default.
    // - then alphabetically
    // - but tags with subtags (e.g. "zh_hans") before those without (e.g. "zh").
    {
        fn sort(a: &String, b: &String) -> std::cmp::Ordering {
            match (a == "en", b == "en") {
                (true, false) => std::cmp::Ordering::Less,
                (false, true) => std::cmp::Ordering::Greater,
                _ => {
                    let (a0, a1) = a.split_once('_').unwrap_or((a, "xxxxxx"));
                    let (b0, b1) = b.split_once('_').unwrap_or((b, "xxxxxx"));
                    match a0.cmp(b0) {
                        std::cmp::Ordering::Equal => a1.cmp(b1),
                        ord => ord,
                    }
                }
            }
        }
        languages.sort_unstable_by(sort);
        languages_with_aliases.sort_unstable_by(|a, b| sort(&a.0, &b.0));
    }

    let mut out = String::new();

    // Generate the source code for the i18n data.
    {
        _ = write!(
            out,
            "\
// This file is generated by build.rs. Do not edit it manually.

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum LocId {{",
        );

        for (k, _) in translations.iter() {
            _ = writeln!(out, "    {k},");
        }

        _ = write!(
            out,
            "\
}}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum LangId {{
",
        );

        for lang in &languages {
            _ = writeln!(out, "    {lang},");
        }

        _ = write!(
            out,
            "\
}}

const LANGUAGES: &[(&str, LangId)] = &[
"
        );

        for (alias, lang) in &languages_with_aliases {
            _ = writeln!(out, "    ({alias:?}, LangId::{lang}),");
        }

        _ = write!(
            out,
            "\
];

const TRANSLATIONS: [[&str; {}]; {}] = [
",
            translations.len(),
            languages.len(),
        );

        for lang in &languages {
            _ = writeln!(out, "    [");
            for (_, v) in translations.iter() {
                const DEFAULT: &String = &String::new();
                let v = v.get(lang).or_else(|| v.get("en")).unwrap_or(DEFAULT);
                _ = writeln!(out, "        {v:?},");
            }
            _ = writeln!(out, "    ],");
        }

        _ = writeln!(out, "];");
    }

    out
}


================================================
FILE: crates/edit/build/main.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#![allow(irrefutable_let_patterns)]

use crate::helpers::env_opt;

mod helpers;
mod i18n;

#[derive(Clone, Copy, PartialEq, Eq)]
enum TargetOs {
    Windows,
    MacOS,
    Unix,
}

fn main() {
    stdext::arena::init(128 * 1024 * 1024).unwrap();

    let target_os = match env_opt("CARGO_CFG_TARGET_OS").as_str() {
        "windows" => TargetOs::Windows,
        "macos" | "ios" => TargetOs::MacOS,
        _ => TargetOs::Unix,
    };

    compile_i18n();
    configure_icu(target_os);
    #[cfg(windows)]
    configure_windows_binary(target_os);
}

fn compile_i18n() {
    let i18n_path = "../../i18n/edit.toml";

    let i18n = std::fs::read_to_string(i18n_path).unwrap();
    let contents = i18n::generate(&i18n);
    let out_dir = env_opt("OUT_DIR");
    let path = format!("{out_dir}/i18n_edit.rs");
    std::fs::write(&path, contents).unwrap();

    println!("cargo::rerun-if-env-changed=EDIT_CFG_LANGUAGES");
    println!("cargo::rerun-if-changed={i18n_path}");
}

fn configure_icu(target_os: TargetOs) {
    let icuuc_soname = env_opt("EDIT_CFG_ICUUC_SONAME");
    let icui18n_soname = env_opt("EDIT_CFG_ICUI18N_SONAME");
    let cpp_exports = env_opt("EDIT_CFG_ICU_CPP_EXPORTS");
    let renaming_version = env_opt("EDIT_CFG_ICU_RENAMING_VERSION");
    let renaming_auto_detect = env_opt("EDIT_CFG_ICU_RENAMING_AUTO_DETECT");

    // If none of the `EDIT_CFG_ICU*` environment variables are set,
    // we default to enabling `EDIT_CFG_ICU_RENAMING_AUTO_DETECT` on UNIX.
    // This slightly improves portability at least in the cases where the SONAMEs match our defaults.
    let renaming_auto_detect = if !renaming_auto_detect.is_empty() {
        renaming_auto_detect.parse::<bool>().unwrap()
    } else {
        target_os == TargetOs::Unix
            && icuuc_soname.is_empty()
            && icui18n_soname.is_empty()
            && cpp_exports.is_empty()
            && renaming_version.is_empty()
    };
    if renaming_auto_detect && !renaming_version.is_empty() {
        // It makes no sense to specify an explicit version and also ask for auto-detection.
        panic!(
            "Either `EDIT_CFG_ICU_RENAMING_AUTO_DETECT` or `EDIT_CFG_ICU_RENAMING_VERSION` must be set, but not both"
        );
    }

    let icuuc_soname = if !icuuc_soname.is_empty() {
        &icuuc_soname
    } else {
        match target_os {
            TargetOs::Windows => "icuuc.dll",
            TargetOs::MacOS => "libicucore.dylib",
            TargetOs::Unix => "libicuuc.so",
        }
    };
    let icui18n_soname = if !icui18n_soname.is_empty() {
        &icui18n_soname
    } else {
        match target_os {
            TargetOs::Windows => "icuin.dll",
            TargetOs::MacOS => "libicucore.dylib",
            TargetOs::Unix => "libicui18n.so",
        }
    };
    let icu_export_prefix =
        if !cpp_exports.is_empty() && cpp_exports.parse::<bool>().unwrap() { "_" } else { "" };
    let icu_export_suffix =
        if !renaming_version.is_empty() { format!("_{renaming_version}") } else { String::new() };

    println!("cargo::rerun-if-env-changed=EDIT_CFG_ICUUC_SONAME");
    println!("cargo::rustc-env=EDIT_CFG_ICUUC_SONAME={icuuc_soname}");
    println!("cargo::rerun-if-env-changed=EDIT_CFG_ICUI18N_SONAME");
    println!("cargo::rustc-env=EDIT_CFG_ICUI18N_SONAME={icui18n_soname}");
    println!("cargo::rerun-if-env-changed=EDIT_CFG_ICU_EXPORT_PREFIX");
    println!("cargo::rustc-env=EDIT_CFG_ICU_EXPORT_PREFIX={icu_export_prefix}");
    println!("cargo::rerun-if-env-changed=EDIT_CFG_ICU_EXPORT_SUFFIX");
    println!("cargo::rustc-env=EDIT_CFG_ICU_EXPORT_SUFFIX={icu_export_suffix}");
    println!("cargo::rerun-if-env-changed=EDIT_CFG_ICU_RENAMING_AUTO_DETECT");
    println!("cargo::rustc-check-cfg=cfg(edit_icu_renaming_auto_detect)");
    if renaming_auto_detect {
        println!("cargo::rustc-cfg=edit_icu_renaming_auto_detect");
    }
}

#[cfg(windows)]
fn configure_windows_binary(target_os: TargetOs) {
    if target_os != TargetOs::Windows {
        return;
    }

    let manifest_path = "src/bin/edit/edit.exe.manifest";
    let icon_path = "../../assets/edit.ico";

    winresource::WindowsResource::new()
        .set_manifest_file(manifest_path)
        .set("FileDescription", "Microsoft Edit")
        .set("LegalCopyright", "© Microsoft Corporation. All rights reserved.")
        .set_icon(icon_path)
        .compile()
        .unwrap();

    println!("cargo::rerun-if-changed={manifest_path}");
}


================================================
FILE: crates/edit/src/base64.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! Base64 facilities.

use stdext::arena::Arena;
use stdext::collections::BString;

const CHARSET: [u8; 64] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/// One aspect of base64 is that the encoded length can be
/// calculated accurately in advance, which is what this returns.
#[inline]
pub fn encode_len(src_len: usize) -> usize {
    src_len.div_ceil(3) * 4
}

/// Encodes the given bytes as base64 and appends them to the destination string.
pub fn encode<'a>(arena: &'a Arena, dst: &mut BString<'a>, src: &[u8]) {
    unsafe {
        let mut inp = src.as_ptr();
        let mut remaining = src.len();
        let dst = dst.as_mut_vec();

        let out_len = encode_len(src.len());
        // ... we can then use this fact to reserve space all at once.
        dst.reserve(arena, out_len);

        // SAFETY: Getting a pointer to the reserved space is only safe
        // *after* calling `reserve()` as it may change the pointer.
        let mut out = dst.as_mut_ptr().add(dst.len());

        if remaining != 0 {
            // Translate chunks of 3 source bytes into 4 base64-encoded bytes.
            while remaining > 3 {
                // SAFETY: Thanks to `remaining > 3`, reading 4 bytes at once is safe.
                // This improves performance massively over a byte-by-byte approach,
                // because it allows us to byte-swap the read and use simple bit-shifts below.
                let val = u32::from_be((inp as *const u32).read_unaligned());
                inp = inp.add(3);
                remaining -= 3;

                *out = CHARSET[(val >> 26) as usize];
                out = out.add(1);
                *out = CHARSET[(val >> 20) as usize & 0x3f];
                out = out.add(1);
                *out = CHARSET[(val >> 14) as usize & 0x3f];
                out = out.add(1);
                *out = CHARSET[(val >> 8) as usize & 0x3f];
                out = out.add(1);
            }

            // Convert the remaining 1-3 bytes.
            let mut in1 = 0;
            let mut in2 = 0;

            // We can simplify the following logic by assuming that there's only 1
            // byte left. If there's >1 byte left, these two '=' will be overwritten.
            *out.add(3) = b'=';
            *out.add(2) = b'=';

            if remaining >= 3 {
                in2 = inp.add(2).read() as usize;
                *out.add(3) = CHARSET[in2 & 0x3f];
            }

            if remaining >= 2 {
                in1 = inp.add(1).read() as usize;
                *out.add(2) = CHARSET[(in1 << 2 | in2 >> 6) & 0x3f];
            }

            let in0 = inp.add(0).read() as usize;
            *out.add(1) = CHARSET[(in0 << 4 | in1 >> 4) & 0x3f];
            *out.add(0) = CHARSET[in0 >> 2];
        }

        dst.set_len(dst.len() + out_len);
    }
}

#[cfg(test)]
mod tests {
    use stdext::arena::scratch_arena;
    use stdext::collections::BString;

    use super::encode;

    #[test]
    fn test_basic() {
        let scratch = scratch_arena(None);
        let enc = |s: &[u8]| {
            let mut dst = BString::empty();
            encode(&scratch, &mut dst, s);
            dst
        };
        assert_eq!(enc(b""), "");
        assert_eq!(enc(b"a"), "YQ==");
        assert_eq!(enc(b"ab"), "YWI=");
        assert_eq!(enc(b"abc"), "YWJj");
        assert_eq!(enc(b"abcd"), "YWJjZA==");
        assert_eq!(enc(b"abcde"), "YWJjZGU=");
        assert_eq!(enc(b"abcdef"), "YWJjZGVm");
        assert_eq!(enc(b"abcdefg"), "YWJjZGVmZw==");
        assert_eq!(enc(b"abcdefgh"), "YWJjZGVmZ2g=");
        assert_eq!(enc(b"abcdefghi"), "YWJjZGVmZ2hp");
        assert_eq!(enc(b"abcdefghij"), "YWJjZGVmZ2hpag==");
        assert_eq!(enc(b"abcdefghijk"), "YWJjZGVmZ2hpams=");
        assert_eq!(enc(b"abcdefghijkl"), "YWJjZGVmZ2hpamts");
        assert_eq!(enc(b"abcdefghijklm"), "YWJjZGVmZ2hpamtsbQ==");
        assert_eq!(enc(b"abcdefghijklmN"), "YWJjZGVmZ2hpamtsbU4=");
        assert_eq!(enc(b"abcdefghijklmNO"), "YWJjZGVmZ2hpamtsbU5P");
        assert_eq!(enc(b"abcdefghijklmNOP"), "YWJjZGVmZ2hpamtsbU5PUA==");
        assert_eq!(enc(b"abcdefghijklmNOPQ"), "YWJjZGVmZ2hpamtsbU5PUFE=");
        assert_eq!(enc(b"abcdefghijklmNOPQR"), "YWJjZGVmZ2hpamtsbU5PUFFS");
        assert_eq!(enc(b"abcdefghijklmNOPQRS"), "YWJjZGVmZ2hpamtsbU5PUFFSUw==");
        assert_eq!(enc(b"abcdefghijklmNOPQRST"), "YWJjZGVmZ2hpamtsbU5PUFFSU1Q=");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTU"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RV");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTUV"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RVVg==");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTUVW"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RVVlc=");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTUVWX"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RVVldY");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTUVWXY"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RVVldYWQ==");
        assert_eq!(enc(b"abcdefghijklmNOPQRSTUVWXYZ"), "YWJjZGVmZ2hpamtsbU5PUFFSU1RVVldYWVo=");
    }
}


================================================
FILE: crates/edit/src/bin/edit/apperr.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::io;

use edit::{buffer, icu};

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Icu(icu::Error),
}

pub type Result<T> = std::result::Result<T, Error>;

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Self::Io(err)
    }
}

impl From<icu::Error> for Error {
    fn from(err: icu::Error) -> Self {
        Self::Icu(err)
    }
}

impl From<buffer::IoError> for Error {
    fn from(err: buffer::IoError) -> Self {
        match err {
            buffer::IoError::Io(e) => Self::Io(e),
            buffer::IoError::Icu(e) => Self::Icu(e),
        }
    }
}


================================================
FILE: crates/edit/src/bin/edit/documents.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::ffi::OsStr;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::{fs, io};

use edit::buffer::{RcTextBuffer, TextBuffer};
use edit::helpers::{CoordType, Point};
use edit::{path, sys};

use crate::apperr;
use crate::state::DisplayablePathBuf;

pub struct Document {
    pub buffer: RcTextBuffer,
    pub path: Option<PathBuf>,
    pub dir: Option<DisplayablePathBuf>,
    pub filename: String,
    pub file_id: Option<sys::FileId>,
    pub new_file_counter: usize,
}

impl Document {
    pub fn save(&mut self, new_path: Option<PathBuf>) -> apperr::Result<()> {
        let path = new_path.as_deref().unwrap_or_else(|| self.path.as_ref().unwrap().as_path());
        let mut file = DocumentManager::open_for_writing(path)?;

        {
            let mut tb = self.buffer.borrow_mut();
            tb.write_file(&mut file)?;
        }

        if let Ok(id) = sys::file_id(None, path) {
            self.file_id = Some(id);
        }

        if let Some(path) = new_path {
            self.set_path(path);
        }

        Ok(())
    }

    pub fn reread(&mut self, encoding: Option<&'static str>) -> apperr::Result<()> {
        let path = self.path.as_ref().unwrap().as_path();
        let mut file = DocumentManager::open_for_reading(path)?;

        {
            let mut tb = self.buffer.borrow_mut();
            tb.read_file(&mut file, encoding)?;
        }

        if let Ok(id) = sys::file_id(None, path) {
            self.file_id = Some(id);
        }

        Ok(())
    }

    fn set_path(&mut self, path: PathBuf) {
        let filename = path.file_name().unwrap_or_default().to_string_lossy().into_owned();
        let dir = path.parent().map(ToOwned::to_owned).unwrap_or_default();
        self.filename = filename;
        self.dir = Some(DisplayablePathBuf::from_path(dir));
        self.path = Some(path);
        self.update_file_mode();
    }

    fn update_file_mode(&mut self) {
        let mut tb = self.buffer.borrow_mut();
        tb.set_ruler(if self.filename == "COMMIT_EDITMSG" { 72 } else { 0 });
    }
}

#[derive(Default)]
pub struct DocumentManager {
    list: Vec<Document>,
}

impl DocumentManager {
    #[inline]
    pub fn len(&self) -> usize {
        self.list.len()
    }

    #[inline]
    pub fn active(&self) -> Option<&Document> {
        self.list.last()
    }

    #[inline]
    pub fn active_mut(&mut self) -> Option<&mut Document> {
        self.list.last_mut()
    }

    pub fn update_active<F: FnMut(&Document) -> bool>(&mut self, mut func: F) -> bool {
        let Some(idx) = self.list.iter().rposition(&mut func) else {
            return false;
        };

        // Already active (= last) document matched? Nothing to do.
        if idx == self.list.len() - 1 {
            return false;
        }

        // Otherwise, move the matched document to the end of the list so it becomes active.
        // Uses unsafe, because `rotate_left()` is horrendously bad with -Copt-level=s
        // (it's really almost comical) and I just don't tolerate that.
        // If I'm dead and you're looking to rewrite this use `list.push(list.remove(idx))`.
        unsafe {
            let beg = self.list.as_mut_ptr();
            let doc = beg.add(idx);
            let last = beg.add(self.list.len() - 1);
            let amount = self.list.len() - idx - 1;
            let mut temp = std::mem::MaybeUninit::<Document>::uninit();

            // Make a backup of the document
            std::ptr::copy_nonoverlapping(doc, temp.as_mut_ptr(), 1);
            // Shift the rest to the front
            std::ptr::copy(doc.add(1), doc, amount);
            // Move the backup to the end
            std::ptr::copy_nonoverlapping(temp.as_ptr(), last, 1);
        }

        true
    }

    pub fn remove_active(&mut self) {
        self.list.pop();
    }

    pub fn add_untitled(&mut self) -> apperr::Result<&mut Document> {
        let buffer = Self::create_buffer()?;
        let mut doc = Document {
            buffer,
            path: None,
            dir: Default::default(),
            filename: Default::default(),
            file_id: None,
            new_file_counter: 0,
        };
        self.gen_untitled_name(&mut doc);

        // In the future this could use push_mut, but it's unstable right now. As usual.
        self.list.push(doc);
        Ok(self.list.last_mut().unwrap())
    }

    pub fn gen_untitled_name(&self, doc: &mut Document) {
        let mut new_file_counter = 0;
        for doc in &self.list {
            new_file_counter = new_file_counter.max(doc.new_file_counter);
        }
        new_file_counter += 1;

        doc.filename = format!("Untitled-{new_file_counter}.txt");
        doc.new_file_counter = new_file_counter;
    }

    pub fn add_file_path(&mut self, path: &Path) -> apperr::Result<&mut Document> {
        let (path, goto) = Self::parse_filename_goto(path);
        let path = path::normalize(path);

        let mut file = match File::open(&path) {
            Ok(file) => Some(file),
            Err(err) if err.kind() == io::ErrorKind::NotFound => None,
            Err(err) => return Err(err.into()),
        };

        let file_id = if file.is_some() { Some(sys::file_id(file.as_ref(), &path)?) } else { None };

        // Check if the file is already open.
        if file_id.is_some() && self.update_active(|doc| doc.file_id == file_id) {
            let doc = self.active_mut().unwrap();
            if let Some(goto) = goto {
                doc.buffer.borrow_mut().cursor_move_to_logical(goto);
            }
            return Ok(doc);
        }

        let buffer = Self::create_buffer()?;
        {
            if let Some(file) = &mut file {
                let mut tb = buffer.borrow_mut();
                tb.read_file(file, None)?;

                if let Some(goto) = goto
                    && goto != Default::default()
                {
                    tb.cursor_move_to_logical(goto);
                }
            }
        }

        let mut doc = Document {
            buffer,
            path: None,
            dir: None,
            filename: Default::default(),
            file_id,
            new_file_counter: 0,
        };
        doc.set_path(path);

        if let Some(active) = self.active()
            && active.path.is_none()
            && active.file_id.is_none()
            && !active.buffer.borrow().is_dirty()
        {
            // If the current document is a pristine Untitled document with no
            // name and no ID, replace it with the new document.
            self.remove_active();
        }

        self.list.push(doc);
        Ok(self.list.last_mut().unwrap())
    }

    pub fn reflow_all(&self) {
        for doc in &self.list {
            let mut tb = doc.buffer.borrow_mut();
            tb.reflow();
        }
    }

    pub fn open_for_reading(path: &Path) -> apperr::Result<File> {
        File::open(path).map_err(apperr::Error::from)
    }

    pub fn open_for_writing(path: &Path) -> apperr::Result<File> {
        // Error handling for directory creation and file writing

        // It is worth doing an existence check because it is significantly
        // faster than calling mkdir() and letting it fail (at least on Windows).
        if let Some(parent) = path.parent()
            && !parent.exists()
        {
            fs::create_dir_all(parent)?;
        }

        File::create(path).map_err(apperr::Error::from)
    }

    fn create_buffer() -> apperr::Result<RcTextBuffer> {
        let buffer = TextBuffer::new_rc(false)?;
        {
            let mut tb = buffer.borrow_mut();
            tb.set_insert_final_newline(!cfg!(windows)); // As mandated by POSIX.
            tb.set_margin_enabled(true);
            tb.set_line_highlight_enabled(true);
        }
        Ok(buffer)
    }

    // Parse a filename in the form of "filename:line:char".
    // Returns the position of the first colon and the line/char coordinates.
    fn parse_filename_goto(path: &Path) -> (&Path, Option<Point>) {
        fn parse(s: &[u8]) -> Option<CoordType> {
            if s.is_empty() {
                return None;
            }

            let mut num: CoordType = 0;
            for &b in s {
                if !b.is_ascii_digit() {
                    return None;
                }
                let digit = (b - b'0') as CoordType;
                num = num.checked_mul(10)?.checked_add(digit)?;
            }
            Some(num)
        }

        fn find_colon_rev(bytes: &[u8], offset: usize) -> Option<usize> {
            (0..offset.min(bytes.len())).rev().find(|&i| bytes[i] == b':')
        }

        let bytes = path.as_os_str().as_encoded_bytes();
        let colend = match find_colon_rev(bytes, bytes.len()) {
            // Reject filenames that would result in an empty filename after stripping off the :line:char suffix.
            // For instance, a filename like ":123:456" will not be processed by this function.
            Some(colend) if colend > 0 => colend,
            _ => return (path, None),
        };

        let last = match parse(&bytes[colend + 1..]) {
            Some(last) => last,
            None => return (path, None),
        };
        let last = (last - 1).max(0);
        let mut len = colend;
        let mut goto = Point { x: 0, y: last };

        if let Some(colbeg) = find_colon_rev(bytes, colend) {
            // Same here: Don't allow empty filenames.
            if colbeg != 0
                && let Some(first) = parse(&bytes[colbeg + 1..colend])
            {
                let first = (first - 1).max(0);
                len = colbeg;
                goto = Point { x: last, y: first };
            }
        }

        // Strip off the :line:char suffix.
        let path = &bytes[..len];
        let path = unsafe { OsStr::from_encoded_bytes_unchecked(path) };
        let path = Path::new(path);
        (path, Some(goto))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_last_numbers() {
        fn parse(s: &str) -> (&str, Option<Point>) {
            let (p, g) = DocumentManager::parse_filename_goto(Path::new(s));
            (p.to_str().unwrap(), g)
        }

        assert_eq!(parse("123"), ("123", None));
        assert_eq!(parse("abc"), ("abc", None));
        assert_eq!(parse(":123"), (":123", None));
        assert_eq!(parse("abc:123"), ("abc", Some(Point { x: 0, y: 122 })));
        assert_eq!(parse("45:123"), ("45", Some(Point { x: 0, y: 122 })));
        assert_eq!(parse(":45:123"), (":45", Some(Point { x: 0, y: 122 })));
        assert_eq!(parse("abc:45:123"), ("abc", Some(Point { x: 122, y: 44 })));
        assert_eq!(parse("abc:def:123"), ("abc:def", Some(Point { x: 0, y: 122 })));
        assert_eq!(parse("1:2:3"), ("1", Some(Point { x: 2, y: 1 })));
        assert_eq!(parse("::3"), (":", Some(Point { x: 0, y: 2 })));
        assert_eq!(parse("1::3"), ("1:", Some(Point { x: 0, y: 2 })));
        assert_eq!(parse(""), ("", None));
        assert_eq!(parse(":"), (":", None));
        assert_eq!(parse("::"), ("::", None));
        assert_eq!(parse("a:1"), ("a", Some(Point { x: 0, y: 0 })));
        assert_eq!(parse("1:a"), ("1:a", None));
        assert_eq!(parse("file.txt:10"), ("file.txt", Some(Point { x: 0, y: 9 })));
        assert_eq!(parse("file.txt:10:5"), ("file.txt", Some(Point { x: 4, y: 9 })));
    }
}


================================================
FILE: crates/edit/src/bin/edit/draw_editor.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::num::ParseIntError;

use edit::framebuffer::IndexedColor;
use edit::helpers::*;
use edit::icu;
use edit::input::{kbmod, vk};
use edit::tui::*;
use stdext::string_from_utf8_lossy_owned;

use crate::localization::*;
use crate::state::*;

pub fn draw_editor(ctx: &mut Context, state: &mut State) {
    if !matches!(state.wants_search.kind, StateSearchKind::Hidden | StateSearchKind::Disabled) {
        draw_search(ctx, state);
    }

    let size = ctx.size();
    // TODO: The layout code should be able to just figure out the height on its own.
    let height_reduction = match state.wants_search.kind {
        StateSearchKind::Search => 4,
        StateSearchKind::Replace => 5,
        _ => 2,
    };

    if let Some(doc) = state.documents.active() {
        ctx.textarea("textarea", doc.buffer.clone());
        ctx.inherit_focus();
    } else {
        ctx.block_begin("empty");
        ctx.block_end();
    }

    ctx.attr_intrinsic_size(Size { width: 0, height: size.height - height_reduction });
}

fn draw_search(ctx: &mut Context, state: &mut State) {
    if let Err(err) = icu::init() {
        error_log_add(ctx, state, err.into());
        state.wants_search.kind = StateSearchKind::Disabled;
        return;
    }

    let Some(doc) = state.documents.active() else {
        state.wants_search.kind = StateSearchKind::Hidden;
        return;
    };

    let mut action = None;
    let mut focus = StateSearchKind::Hidden;

    if state.wants_search.focus {
        state.wants_search.focus = false;
        focus = StateSearchKind::Search;

        // If the selection is empty, focus the search input field.
        // Otherwise, focus the replace input field, if it exists.
        if let Some(selection) = doc.buffer.borrow_mut().extract_user_selection(false) {
            state.search_needle = string_from_utf8_lossy_owned(selection);
            focus = state.wants_search.kind;
        }
    }

    ctx.block_begin("search");
    ctx.attr_focus_well();
    ctx.attr_background_rgba(ctx.indexed(IndexedColor::White));
    ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::Black));
    {
        if ctx.contains_focus() && ctx.consume_shortcut(vk::ESCAPE) {
            state.wants_search.kind = StateSearchKind::Hidden;
        }

        ctx.table_begin("needle");
        ctx.table_set_cell_gap(Size { width: 1, height: 0 });
        {
            {
                ctx.table_next_row();
                ctx.label("label", loc(LocId::SearchNeedleLabel));

                if ctx.editline("needle", &mut state.search_needle) {
                    action = Some(SearchAction::Search);
                }
                if !state.search_success {
                    ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red));
                    ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite));
                }
                ctx.attr_intrinsic_size(Size { width: COORD_TYPE_SAFE_MAX, height: 1 });
                if focus == StateSearchKind::Search {
                    ctx.steal_focus();
                }
                if ctx.is_focused() && ctx.consume_shortcut(vk::RETURN) {
                    action = Some(SearchAction::Search);
                }
            }

            if state.wants_search.kind == StateSearchKind::Replace {
                ctx.table_next_row();
                ctx.label("label", loc(LocId::SearchReplacementLabel));

                ctx.editline("replacement", &mut state.search_replacement);
                ctx.attr_intrinsic_size(Size { width: COORD_TYPE_SAFE_MAX, height: 1 });
                if focus == StateSearchKind::Replace {
                    ctx.steal_focus();
                }
                if ctx.is_focused() {
                    if ctx.consume_shortcut(vk::RETURN) {
                        action = Some(SearchAction::Replace);
                    } else if ctx.consume_shortcut(kbmod::CTRL_ALT | vk::RETURN) {
                        action = Some(SearchAction::ReplaceAll);
                    }
                }
            }
        }
        ctx.table_end();

        ctx.table_begin("options");
        ctx.table_set_cell_gap(Size { width: 2, height: 0 });
        {
            let mut change = false;
            let mut change_action = Some(SearchAction::Search);

            ctx.table_next_row();

            change |= ctx.checkbox(
                "match-case",
                loc(LocId::SearchMatchCase),
                &mut state.search_options.match_case,
            );
            change |= ctx.checkbox(
                "whole-word",
                loc(LocId::SearchWholeWord),
                &mut state.search_options.whole_word,
            );
            change |= ctx.checkbox(
                "use-regex",
                loc(LocId::SearchUseRegex),
                &mut state.search_options.use_regex,
            );
            if state.wants_search.kind == StateSearchKind::Replace
                && ctx.button("replace-all", loc(LocId::SearchReplaceAll), ButtonStyle::default())
            {
                change = true;
                change_action = Some(SearchAction::ReplaceAll);
            }
            if ctx.button("close", loc(LocId::SearchClose), ButtonStyle::default()) {
                state.wants_search.kind = StateSearchKind::Hidden;
            }

            if change {
                action = change_action;
                state.wants_search.focus = true;
                ctx.needs_rerender();
            }
        }
        ctx.table_end();
    }
    ctx.block_end();

    if let Some(action) = action {
        search_execute(ctx, state, action);
    }
}

pub enum SearchAction {
    Search,
    Replace,
    ReplaceAll,
}

pub fn search_execute(ctx: &mut Context, state: &mut State, action: SearchAction) {
    let Some(doc) = state.documents.active_mut() else {
        return;
    };

    state.search_success = match action {
        SearchAction::Search => {
            doc.buffer.borrow_mut().find_and_select(&state.search_needle, state.search_options)
        }
        SearchAction::Replace => doc.buffer.borrow_mut().find_and_replace(
            &state.search_needle,
            state.search_options,
            state.search_replacement.as_bytes(),
        ),
        SearchAction::ReplaceAll => doc.buffer.borrow_mut().find_and_replace_all(
            &state.search_needle,
            state.search_options,
            state.search_replacement.as_bytes(),
        ),
    }
    .is_ok();

    ctx.needs_rerender();
}

pub fn draw_handle_save(ctx: &mut Context, state: &mut State) {
    if let Some(doc) = state.documents.active_mut() {
        if doc.path.is_some() {
            if let Err(err) = doc.save(None) {
                error_log_add(ctx, state, err);
            }
        } else {
            // No path? Show the file picker.
            state.wants_file_picker = StateFilePicker::SaveAs;
            state.wants_save = false;
            ctx.needs_rerender();
        }
    }

    state.wants_save = false;
}

pub fn draw_handle_wants_close(ctx: &mut Context, state: &mut State) {
    let Some(doc) = state.documents.active() else {
        state.wants_close = false;
        return;
    };

    if !doc.buffer.borrow().is_dirty() {
        state.documents.remove_active();
        state.wants_close = false;
        ctx.needs_rerender();
        return;
    }

    enum Action {
        None,
        Save,
        Discard,
        Cancel,
    }
    let mut action = Action::None;

    ctx.modal_begin("unsaved-changes", loc(LocId::UnsavedChangesDialogTitle));
    ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red));
    ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite));
    {
        let contains_focus = ctx.contains_focus();

        ctx.label("description", loc(LocId::UnsavedChangesDialogDescription));
        ctx.attr_padding(Rect::three(1, 2, 1));

        ctx.table_begin("choices");
        ctx.inherit_focus();
        ctx.attr_padding(Rect::three(0, 2, 1));
        ctx.attr_position(Position::Center);
        ctx.table_set_cell_gap(Size { width: 2, height: 0 });
        {
            ctx.table_next_row();
            ctx.inherit_focus();

            if ctx.button(
                "yes",
                loc(LocId::UnsavedChangesDialogYes),
                ButtonStyle::default().accelerator('S'),
            ) {
                action = Action::Save;
            }
            ctx.inherit_focus();
            if ctx.button(
                "no",
                loc(LocId::UnsavedChangesDialogNo),
                ButtonStyle::default().accelerator('N'),
            ) {
                action = Action::Discard;
            }
            if ctx.button("cancel", loc(LocId::Cancel), ButtonStyle::default()) {
                action = Action::Cancel;
            }

            // Handle accelerator shortcuts
            if contains_focus {
                if ctx.consume_shortcut(vk::S) {
                    action = Action::Save;
                } else if ctx.consume_shortcut(vk::N) {
                    action = Action::Discard;
                }
            }
        }
        ctx.table_end();
    }
    if ctx.modal_end() {
        action = Action::Cancel;
    }

    match action {
        Action::None => return,
        Action::Save => {
            state.wants_save = true;
        }
        Action::Discard => {
            state.documents.remove_active();
            state.wants_close = false;
        }
        Action::Cancel => {
            state.wants_exit = false;
            state.wants_close = false;
        }
    }

    ctx.needs_rerender();
}

pub fn draw_goto_menu(ctx: &mut Context, state: &mut State) {
    let mut done = false;

    if let Some(doc) = state.documents.active_mut() {
        ctx.modal_begin("goto", loc(LocId::FileGoto));
        {
            if ctx.editline("goto-line", &mut state.goto_target) {
                state.goto_invalid = false;
            }
            if state.goto_invalid {
                ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red));
                ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite));
            }

            ctx.attr_intrinsic_size(Size { width: 24, height: 1 });
            ctx.steal_focus();

            if ctx.consume_shortcut(vk::RETURN) {
                match validate_goto_point(&state.goto_target) {
                    Ok(point) => {
                        let mut buf = doc.buffer.borrow_mut();
                        buf.cursor_move_to_logical(point);
                        buf.make_cursor_visible();
                        done = true;
                    }
                    Err(_) => state.goto_invalid = true,
                }
                ctx.needs_rerender();
            }
        }
        done |= ctx.modal_end();
    } else {
        done = true;
    }

    if done {
        state.wants_goto = false;
        state.goto_target.clear();
        state.goto_invalid = false;
        ctx.needs_rerender();
    }
}

fn validate_goto_point(line: &str) -> Result<Point, ParseIntError> {
    let mut coords = [0; 2];
    let (y, x) = line.split_once(':').unwrap_or((line, "0"));
    // Using a loop here avoids 2 copies of the str->int code.
    // This makes the binary more compact.
    for (i, s) in [x, y].iter().enumerate() {
        coords[i] = s.parse::<CoordType>()?.saturating_sub(1);
    }
    Ok(Point { x: coords[0], y: coords[1] })
}


================================================
FILE: crates/edit/src/bin/edit/draw_filepicker.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::cmp::Ordering;
use std::fs;
use std::path::{Path, PathBuf};

use edit::framebuffer::IndexedColor;
use edit::helpers::*;
use edit::input::{kbmod, vk};
use edit::tui::*;
use edit::{icu, path};
use stdext::arena::scratch_arena;
use stdext::collections::BVec;

use crate::localization::*;
use crate::state::*;

pub fn draw_file_picker(ctx: &mut Context, state: &mut State) {
    // The save dialog is pre-filled with the current document filename.
    if state.wants_file_picker == StateFilePicker::SaveAs {
        state.wants_file_picker = StateFilePicker::SaveAsShown;

        if state.file_picker_pending_name.as_os_str().is_empty() {
            state.file_picker_pending_name =
                state.documents.active().map_or("Untitled.txt", |doc| doc.filename.as_str()).into();
        }
    }

    let width = (ctx.size().width - 20).max(10);
    let height = (ctx.size().height - 10).max(10);
    let mut doit = None;
    let mut done = false;

    ctx.modal_begin(
        "file-picker",
        if state.wants_file_picker == StateFilePicker::Open {
            loc(LocId::FileOpen)
        } else {
            loc(LocId::FileSaveAs)
        },
    );
    ctx.attr_intrinsic_size(Size { width, height });
    {
        let contains_focus = ctx.contains_focus();
        let mut activated = false;

        ctx.table_begin("path");
        ctx.table_set_columns(&[0, COORD_TYPE_SAFE_MAX]);
        ctx.table_set_cell_gap(Size { width: 1, height: 0 });
        ctx.attr_padding(Rect::two(1, 1));
        ctx.inherit_focus();
        {
            ctx.table_next_row();

            ctx.label("dir-label", loc(LocId::SaveAsDialogPathLabel));
            ctx.label("dir", state.file_picker_pending_dir.as_str());
            ctx.attr_overflow(Overflow::TruncateMiddle);

            ctx.table_next_row();
            ctx.inherit_focus();

            ctx.label("name-label", loc(LocId::SaveAsDialogNameLabel));

            let name_changed = ctx.editline("name", &mut state.file_picker_pending_name);
            ctx.inherit_focus();

            if ctx.contains_focus() {
                if name_changed && ctx.is_focused() {
                    update_autocomplete_suggestions(state);
                }
            } else if !state.file_picker_autocomplete.is_empty() {
                state.file_picker_autocomplete.clear();
            }

            if !state.file_picker_autocomplete.is_empty() {
                let bg = ctx.indexed_alpha(IndexedColor::Background, 3, 4);
                let fg = ctx.contrasted(bg);
                let focus_list_beg = ctx.is_focused() && ctx.consume_shortcut(vk::DOWN);
                let focus_list_end = ctx.is_focused() && ctx.consume_shortcut(vk::UP);
                let mut autocomplete_done = ctx.consume_shortcut(vk::ESCAPE);

                ctx.list_begin("suggestions");
                ctx.attr_float(FloatSpec {
                    anchor: Anchor::Last,
                    gravity_x: 0.0,
                    gravity_y: 0.0,
                    offset_x: 0.0,
                    offset_y: 1.0,
                });
                ctx.attr_border();
                ctx.attr_background_rgba(bg);
                ctx.attr_foreground_rgba(fg);
                {
                    for (idx, suggestion) in state.file_picker_autocomplete.iter().enumerate() {
                        let sel = ctx.list_item(false, suggestion.as_str());
                        if sel != ListSelection::Unchanged {
                            state.file_picker_pending_name = suggestion.as_path().into();
                        }
                        if sel == ListSelection::Activated {
                            autocomplete_done = true;
                        }

                        let is_first = idx == 0;
                        let is_last = idx == state.file_picker_autocomplete.len() - 1;
                        if (is_first && focus_list_beg) || (is_last && focus_list_end) {
                            ctx.list_item_steal_focus();
                        } else if ctx.is_focused()
                            && ((is_first && ctx.consume_shortcut(vk::UP))
                                || (is_last && ctx.consume_shortcut(vk::DOWN)))
                        {
                            ctx.toss_focus_up();
                        }
                    }
                }
                ctx.list_end();

                // If the user typed something, we want to put focus back into the editline.
                // TODO: The input should be processed by the editline and not simply get swallowed.
                if ctx.keyboard_input().is_some() {
                    ctx.set_input_consumed();
                    autocomplete_done = true;
                }

                if autocomplete_done {
                    state.file_picker_autocomplete.clear();
                }
            }

            if ctx.is_focused() && ctx.consume_shortcut(vk::RETURN) {
                activated = true;
            }
        }
        ctx.table_end();

        if state.file_picker_entries.is_none() {
            draw_dialog_saveas_refresh_files(state);
        }

        ctx.scrollarea_begin(
            "directory",
            Size {
                width: 0,
                // -1 for the label (top)
                // -1 for the label (bottom)
                // -1 for the editline (bottom)
                height: height - 3,
            },
        );
        ctx.attr_background_rgba(ctx.indexed_alpha(IndexedColor::Black, 1, 4));
        {
            ctx.next_block_id_mixin(state.file_picker_pending_dir_revision);
            ctx.list_begin("files");
            ctx.inherit_focus();

            for entries in state.file_picker_entries.as_ref().unwrap() {
                for entry in entries {
                    match ctx.list_item(false, entry.as_str()) {
                        ListSelection::Unchanged => {}
                        ListSelection::Selected => {
                            state.file_picker_pending_name = entry.as_path().into()
                        }
                        ListSelection::Activated => activated = true,
                    }
                    ctx.attr_overflow(Overflow::TruncateMiddle);
                }
            }

            ctx.list_end();
        }
        ctx.scrollarea_end();

        if contains_focus
            && (ctx.consume_shortcut(vk::BACK) || ctx.consume_shortcut(kbmod::ALT | vk::UP))
        {
            state.file_picker_pending_name = "..".into();
            activated = true;
        }

        if activated {
            doit = draw_file_picker_update_path(state);

            // Check if the file already exists and show an overwrite warning in that case.
            if state.wants_file_picker != StateFilePicker::Open
                && let Some(path) = doit.as_deref()
                && path.exists()
            {
                state.file_picker_overwrite_warning = doit.take();
            }
        }
    }
    if ctx.modal_end() {
        done = true;
    }

    if state.file_picker_overwrite_warning.is_some() {
        let mut save;

        ctx.modal_begin("overwrite", loc(LocId::FileOverwriteWarning));
        ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red));
        ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite));
        {
            let contains_focus = ctx.contains_focus();

            ctx.label("description", loc(LocId::FileOverwriteWarningDescription));
            ctx.attr_overflow(Overflow::TruncateTail);
            ctx.attr_padding(Rect::three(1, 2, 1));

            ctx.table_begin("choices");
            ctx.inherit_focus();
            ctx.attr_padding(Rect::three(0, 2, 1));
            ctx.attr_position(Position::Center);
            ctx.table_set_cell_gap(Size { width: 2, height: 0 });
            {
                ctx.table_next_row();
                ctx.inherit_focus();

                save = ctx.button("yes", loc(LocId::Yes), ButtonStyle::default());
                ctx.inherit_focus();

                if ctx.button("no", loc(LocId::No), ButtonStyle::default()) {
                    state.file_picker_overwrite_warning = None;
                }
            }
            ctx.table_end();

            if contains_focus {
                save |= ctx.consume_shortcut(vk::Y);
                if ctx.consume_shortcut(vk::N) {
                    state.file_picker_overwrite_warning = None;
                }
            }
        }
        if ctx.modal_end() {
            state.file_picker_overwrite_warning = None;
        }

        if save {
            doit = state.file_picker_overwrite_warning.take();
        }
    }

    if let Some(path) = doit {
        let res = if state.wants_file_picker == StateFilePicker::Open {
            state.documents.add_file_path(&path).map(|_| ())
        } else if let Some(doc) = state.documents.active_mut() {
            doc.save(Some(path))
        } else {
            Ok(())
        };
        match res {
            Ok(..) => {
                ctx.needs_rerender();
                done = true;
            }
            Err(err) => error_log_add(ctx, state, err),
        }
    }

    if done {
        state.wants_file_picker = StateFilePicker::None;
        state.file_picker_pending_name = Default::default();
        state.file_picker_entries = Default::default();
        state.file_picker_overwrite_warning = Default::default();
        state.file_picker_autocomplete = Default::default();
    }
}

// Returns Some(path) if the path refers to a file.
fn draw_file_picker_update_path(state: &mut State) -> Option<PathBuf> {
    let old_path = state.file_picker_pending_dir.as_path();
    let path = old_path.join(&state.file_picker_pending_name);
    let path = path::normalize(&path);

    let (dir, name) = if path.is_dir() {
        // If the current path is C:\ and the user selects "..", we want to
        // navigate to the drive picker. Since `path::normalize` will turn C:\.. into C:\,
        // we can detect this by checking if the length of the path didn't change.
        let dir = if cfg!(windows)
            && state.file_picker_pending_name == Path::new("..")
            // It's unnecessary to check the contents of the paths.
            && old_path.as_os_str().len() == path.as_os_str().len()
        {
            Path::new("")
        } else {
            path.as_path()
        };
        (dir, PathBuf::new())
    } else {
        let dir = path.parent().unwrap_or(&path);
        let name = path.file_name().map_or(Default::default(), |s| s.into());
        (dir, name)
    };
    if dir != state.file_picker_pending_dir.as_path() {
        state.file_picker_pending_dir = DisplayablePathBuf::from_path(dir.to_path_buf());
        state.file_picker_pending_dir_revision =
            state.file_picker_pending_dir_revision.wrapping_add(1);
        state.file_picker_entries = None;
    }

    state.file_picker_pending_name = name;
    if state.file_picker_pending_name.as_os_str().is_empty() { None } else { Some(path) }
}

fn draw_dialog_saveas_refresh_files(state: &mut State) {
    let dir = state.file_picker_pending_dir.as_path();
    // ["..", directories, files]
    let mut dirs_files = [Vec::new(), Vec::new(), Vec::new()];

    #[cfg(windows)]
    if dir.as_os_str().is_empty() {
        // If the path is empty, we are at the drive picker.
        // Add all drives as entries.
        for drive in edit::sys::drives() {
            dirs_files[1].push(DisplayablePathBuf::from_string(format!("{drive}:\\")));
        }

        state.file_picker_entries = Some(dirs_files);
        return;
    }

    if cfg!(windows) || dir.parent().is_some() {
        dirs_files[0].push(DisplayablePathBuf::from(".."));
    }

    if let Ok(iter) = fs::read_dir(dir) {
        for entry in iter.flatten() {
            if let Ok(metadata) = entry.metadata() {
                let mut name = entry.file_name();
                let dir = metadata.is_dir()
                    || (metadata.is_symlink()
                        && fs::metadata(entry.path()).is_ok_and(|m| m.is_dir()));
                let idx = if dir { 1 } else { 2 };

                if dir {
                    name.push("/");
                }

                dirs_files[idx].push(DisplayablePathBuf::from(name));
            }
        }
    }

    for entries in &mut dirs_files[1..] {
        entries.sort_unstable_by(|a, b| {
            let a = a.as_bytes();
            let b = b.as_bytes();
            icu::compare_strings(a, b)
        });
    }

    state.file_picker_entries = Some(dirs_files);
}

#[inline(never)]
fn update_autocomplete_suggestions(state: &mut State) {
    state.file_picker_autocomplete.clear();

    if state.file_picker_pending_name.as_os_str().is_empty() {
        return;
    }

    let scratch = scratch_arena(None);
    let needle = state.file_picker_pending_name.as_os_str().as_encoded_bytes();
    let mut matches = Vec::new();

    // Using binary search below we'll quickly find the lower bound
    // of items that match the needle (= share a common prefix).
    //
    // The problem is finding the upper bound. Here I'm using a trick:
    // By appending U+10FFFF (the highest possible Unicode code point)
    // we create a needle that naturally yields an upper bound.
    let mut needle_upper_bound = BVec::empty();
    needle_upper_bound.reserve(&*scratch, needle.len() + 4);
    needle_upper_bound.extend_from_slice(&*scratch, needle);
    needle_upper_bound.extend_from_slice(&*scratch, b"\xf4\x8f\xbf\xbf");

    if let Some(dirs_files) = &state.file_picker_entries {
        'outer: for entries in &dirs_files[1..] {
            let lower = entries
                .binary_search_by(|entry| icu::compare_strings(entry.as_bytes(), needle))
                .unwrap_or_else(|i| i);

            for entry in &entries[lower..] {
                let haystack = entry.as_bytes();
                match icu::compare_strings(haystack, &needle_upper_bound) {
                    Ordering::Less => {
                        matches.push(entry.clone());
                        if matches.len() >= 5 {
                            break 'outer; // Limit to 5 suggestions
                        }
                    }
                    // We're looking for suggestions, not for matches.
                    Ordering::Equal => {}
                    // No more matches possible.
                    Ordering::Greater => break,
                }
            }
        }
    }

    state.file_picker_autocomplete = matches;
}


================================================
FILE: crates/edit/src/bin/edit/draw_menubar.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use edit::helpers::*;
use edit::input::{kbmod, vk};
use edit::tui::*;
use stdext::arena_format;

use crate::localization::*;
use crate::state::*;

pub fn draw_menubar(ctx: &mut Context, state: &mut State) {
    ctx.menubar_begin();
    ctx.attr_background_rgba(state.menubar_color_bg);
    ctx.attr_foreground_rgba(state.menubar_color_fg);
    {
        let contains_focus = ctx.contains_focus();

        if ctx.menubar_menu_begin(loc(LocId::File), 'F') {
            draw_menu_file(ctx, state);
        }
        if !contains_focus && ctx.consume_shortcut(vk::F10) {
            ctx.steal_focus();
        }
        if state.documents.active().is_some() {
            if ctx.menubar_menu_begin(loc(LocId::Edit), 'E') {
                draw_menu_edit(ctx, state);
            }
            if ctx.menubar_menu_begin(loc(LocId::View), 'V') {
                draw_menu_view(ctx, state);
            }
        }
        if ctx.menubar_menu_begin(loc(LocId::Help), 'H') {
            draw_menu_help(ctx, state);
        }
    }
    ctx.menubar_end();
}

fn draw_menu_file(ctx: &mut Context, state: &mut State) {
    if ctx.menubar_menu_button(loc(LocId::FileNew), 'N', kbmod::CTRL | vk::N) {
        draw_add_untitled_document(ctx, state);
    }
    if ctx.menubar_menu_button(loc(LocId::FileOpen), 'O', kbmod::CTRL | vk::O) {
        state.wants_file_picker = StateFilePicker::Open;
    }
    if state.documents.active().is_some() {
        if ctx.menubar_menu_button(loc(LocId::FileSave), 'S', kbmod::CTRL | vk::S) {
            state.wants_save = true;
        }
        if ctx.menubar_menu_button(loc(LocId::FileSaveAs), 'A', vk::NULL) {
            state.wants_file_picker = StateFilePicker::SaveAs;
        }
        if ctx.menubar_menu_button(loc(LocId::FileClose), 'C', kbmod::CTRL | vk::W) {
            state.wants_close = true;
        }
    }
    if ctx.menubar_menu_button(loc(LocId::FileExit), 'X', kbmod::CTRL | vk::Q) {
        state.wants_exit = true;
    }
    ctx.menubar_menu_end();
}

fn draw_menu_edit(ctx: &mut Context, state: &mut State) {
    let doc = state.documents.active().unwrap();
    let mut tb = doc.buffer.borrow_mut();

    if ctx.menubar_menu_button(loc(LocId::EditUndo), 'U', kbmod::CTRL | vk::Z) {
        tb.undo();
        ctx.needs_rerender();
    }
    if ctx.menubar_menu_button(loc(LocId::EditRedo), 'R', kbmod::CTRL | vk::Y) {
        tb.redo();
        ctx.needs_rerender();
    }
    if ctx.menubar_menu_button(loc(LocId::EditCut), 'T', kbmod::CTRL | vk::X) {
        tb.cut(ctx.clipboard_mut());
        ctx.needs_rerender();
    }
    if ctx.menubar_menu_button(loc(LocId::EditCopy), 'C', kbmod::CTRL | vk::C) {
        tb.copy(ctx.clipboard_mut());
        ctx.needs_rerender();
    }
    if ctx.menubar_menu_button(loc(LocId::EditPaste), 'P', kbmod::CTRL | vk::V) {
        tb.paste(ctx.clipboard_ref());
        ctx.needs_rerender();
    }
    if state.wants_search.kind != StateSearchKind::Disabled {
        if ctx.menubar_menu_button(loc(LocId::EditFind), 'F', kbmod::CTRL | vk::F) {
            state.wants_search.kind = StateSearchKind::Search;
            state.wants_search.focus = true;
        }
        if ctx.menubar_menu_button(loc(LocId::EditReplace), 'L', kbmod::CTRL | vk::R) {
            state.wants_search.kind = StateSearchKind::Replace;
            state.wants_search.focus = true;
        }
    }
    if ctx.menubar_menu_button(loc(LocId::EditSelectAll), 'A', kbmod::CTRL | vk::A) {
        tb.select_all();
        ctx.needs_rerender();
    }
    ctx.menubar_menu_end();
}

fn draw_menu_view(ctx: &mut Context, state: &mut State) {
    if let Some(doc) = state.documents.active() {
        let mut tb = doc.buffer.borrow_mut();
        let word_wrap = tb.is_word_wrap_enabled();

        // All values on the statusbar are currently document specific.
        if ctx.menubar_menu_button(loc(LocId::ViewFocusStatusbar), 'S', vk::NULL) {
            state.wants_statusbar_focus = true;
        }
        if ctx.menubar_menu_button(loc(LocId::ViewGoToFile), 'F', kbmod::CTRL | vk::P) {
            state.wants_go_to_file = true;
        }
        if ctx.menubar_menu_button(loc(LocId::FileGoto), 'G', kbmod::CTRL | vk::G) {
            state.wants_goto = true;
        }
        if ctx.menubar_menu_checkbox(loc(LocId::ViewWordWrap), 'W', kbmod::ALT | vk::Z, word_wrap) {
            tb.set_word_wrap(!word_wrap);
            ctx.needs_rerender();
        }
    }

    ctx.menubar_menu_end();
}

fn draw_menu_help(ctx: &mut Context, state: &mut State) {
    if ctx.menubar_menu_button(loc(LocId::HelpAbout), 'A', vk::NULL) {
        state.wants_about = true;
    }
    ctx.menubar_menu_end();
}

pub fn draw_dialog_about(ctx: &mut Context, state: &mut State) {
    ctx.modal_begin("about", loc(LocId::AboutDialogTitle));
    {
        ctx.block_begin("content");
        ctx.inherit_focus();
        ctx.attr_padding(Rect::three(1, 2, 1));
        {
            ctx.label("description", "Microsoft Edit");
            ctx.attr_overflow(Overflow::TruncateTail);
            ctx.attr_position(Position::Center);

            ctx.label(
                "version",
                &arena_format!(
                    ctx.arena(),
                    "{}{}",
                    loc(LocId::AboutDialogVersion),
                    env!("CARGO_PKG_VERSION")
                ),
            );
            ctx.attr_overflow(Overflow::TruncateHead);
            ctx.attr_position(Position::Center);

            ctx.label("copyright", "Copyright (c) Microsoft Corporation");
            ctx.attr_overflow(Overflow::TruncateTail);
            ctx.attr_position(Position::Center);

            ctx.block_begin("choices");
            ctx.inherit_focus();
            ctx.attr_padding(Rect::three(1, 2, 0));
            ctx.attr_position(Position::Center);
            {
                if ctx.button("ok", loc(LocId::Ok), ButtonStyle::default()) {
                    state.wants_about = false;
                }
                ctx.inherit_focus();
            }
            ctx.block_end();
        }
        ctx.block_end();
    }
    if ctx.modal_end() {
        state.wants_about = false;
    }
}


================================================
FILE: crates/edit/src/bin/edit/draw_statusbar.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use edit::framebuffer::{Attributes, IndexedColor};
use edit::fuzzy::score_fuzzy;
use edit::helpers::*;
use edit::icu;
use edit::input::vk;
use edit::tui::*;
use stdext::arena::scratch_arena;
use stdext::arena_format;
use stdext::collections::BVec;

use crate::localization::*;
use crate::state::*;

pub fn draw_statusbar(ctx: &mut Context, state: &mut State) {
    ctx.table_begin("statusbar");
    ctx.attr_focus_well();
    ctx.attr_background_rgba(state.menubar_color_bg);
    ctx.attr_foreground_rgba(state.menubar_color_fg);
    ctx.table_set_cell_gap(Size { width: 2, height: 0 });
    ctx.attr_intrinsic_size(Size { width: COORD_TYPE_SAFE_MAX, height: 1 });
    ctx.attr_padding(Rect::two(0, 1));

    if let Some(doc) = state.documents.active() {
        let mut tb = doc.buffer.borrow_mut();

        ctx.table_next_row();

        if ctx.button("newline", if tb.is_crlf() { "CRLF" } else { "LF" }, ButtonStyle::default()) {
            let is_crlf = tb.is_crlf();
            tb.normalize_newlines(!is_crlf);
        }
        if state.wants_statusbar_focus {
            state.wants_statusbar_focus = false;
            ctx.steal_focus();
        }

        state.wants_encoding_picker |=
            ctx.button("encoding", tb.encoding(), ButtonStyle::default());
        if state.wants_encoding_picker {
            if doc.path.is_some() {
                ctx.block_begin("frame");
                ctx.attr_float(FloatSpec {
                    anchor: Anchor::Last,
                    gravity_x: 0.0,
                    gravity_y: 1.0,
                    offset_x: 0.0,
                    offset_y: 0.0,
                });
                ctx.attr_padding(Rect::two(0, 1));
                ctx.attr_border();
                {
                    if ctx.button("reopen", loc(LocId::EncodingReopen), ButtonStyle::default()) {
                        state.wants_encoding_change = StateEncodingChange::Reopen;
                    }
                    ctx.focus_on_first_present();
                    if ctx.button("convert", loc(LocId::EncodingConvert), ButtonStyle::default()) {
                        state.wants_encoding_change = StateEncodingChange::Convert;
                    }
                }
                ctx.block_end();
            } else {
                // Can't reopen a file that doesn't exist.
                state.wants_encoding_change = StateEncodingChange::Convert;
            }

            if !ctx.contains_focus() {
                state.wants_encoding_picker = false;
                ctx.needs_rerender();
            }
        }

        state.wants_indentation_picker |= ctx.button(
            "indentation",
            &arena_format!(
                ctx.arena(),
                "{}:{}",
                loc(if tb.indent_with_tabs() {
                    LocId::IndentationTabs
                } else {
                    LocId::IndentationSpaces
                }),
                tb.tab_size(),
            ),
            ButtonStyle::default(),
        );
        if state.wants_indentation_picker {
            ctx.table_begin("indentation-picker");
            ctx.attr_float(FloatSpec {
                anchor: Anchor::Last,
                gravity_x: 0.0,
                gravity_y: 1.0,
                offset_x: 0.0,
                offset_y: 0.0,
            });
            ctx.attr_border();
            ctx.attr_padding(Rect::two(0, 1));
            ctx.table_set_cell_gap(Size { width: 1, height: 0 });
            {
                if ctx.contains_focus() && ctx.consume_shortcut(vk::RETURN) {
                    ctx.toss_focus_up();
                }

                ctx.table_next_row();

                ctx.list_begin("type");
                ctx.focus_on_first_present();
                ctx.attr_padding(Rect::two(0, 1));
                {
                    if ctx.list_item(tb.indent_with_tabs(), loc(LocId::IndentationTabs))
                        != ListSelection::Unchanged
                    {
                        tb.set_indent_with_tabs(true);
                        ctx.needs_rerender();
                    }
                    if ctx.list_item(!tb.indent_with_tabs(), loc(LocId::IndentationSpaces))
                        != ListSelection::Unchanged
                    {
                        tb.set_indent_with_tabs(false);
                        ctx.needs_rerender();
                    }
                }
                ctx.list_end();

                ctx.list_begin("width");
                ctx.attr_padding(Rect::two(0, 2));
                {
                    for width in 1u8..=8 {
                        let ch = [b'0' + width];
                        let label = unsafe { std::str::from_utf8_unchecked(&ch) };

                        if ctx.list_item(tb.tab_size() == width as CoordType, label)
                            != ListSelection::Unchanged
                        {
                            tb.set_tab_size(width as CoordType);
                            ctx.needs_rerender();
                        }
                    }
                }
                ctx.list_end();
            }
            ctx.table_end();

            if !ctx.contains_focus() {
                state.wants_indentation_picker = false;
                ctx.needs_rerender();
            }
        }

        ctx.label(
            "location",
            &arena_format!(
                ctx.arena(),
                "{}:{}",
                tb.cursor_logical_pos().y + 1,
                tb.cursor_logical_pos().x + 1
            ),
        );

        #[cfg(feature = "debug-latency")]
        ctx.label(
            "stats",
            &arena_format!(ctx.arena(), "{}/{}", tb.logical_line_count(), tb.visual_line_count(),),
        );

        if tb.is_overtype() && ctx.button("overtype", "OVR", ButtonStyle::default()) {
            tb.set_overtype(false);
            ctx.needs_rerender();
        }

        if tb.is_dirty() {
            ctx.label("dirty", "*");
        }

        ctx.block_begin("filename-container");
        ctx.attr_intrinsic_size(Size { width: COORD_TYPE_SAFE_MAX, height: 1 });
        {
            let total = state.documents.len();
            let mut filename = doc.filename.as_str();
            let filename_buf;

            if total > 1 {
                filename_buf = arena_format!(ctx.arena(), "{} + {}", filename, total - 1);
                filename = &filename_buf;
            }

            state.wants_go_to_file |= ctx.button("filename", filename, ButtonStyle::default());
            ctx.inherit_focus();
            ctx.attr_overflow(Overflow::TruncateMiddle);
            ctx.attr_position(Position::Right);
        }
        ctx.block_end();
    } else {
        state.wants_statusbar_focus = false;
        state.wants_encoding_picker = false;
        state.wants_indentation_picker = false;
    }

    ctx.table_end();
}

pub fn draw_dialog_encoding_change(ctx: &mut Context, state: &mut State) {
    let encoding = state.documents.active_mut().map_or("", |doc| doc.buffer.borrow().encoding());
    let reopen = state.wants_encoding_change == StateEncodingChange::Reopen;
    let width = (ctx.size().width - 20).max(10);
    let height = (ctx.size().height - 10).max(10);
    let mut change = None;
    let mut done = encoding.is_empty();

    ctx.modal_begin(
        "encode",
        if reopen { loc(LocId::EncodingReopen) } else { loc(LocId::EncodingConvert) },
    );
    {
        ctx.table_begin("encoding-search");
        ctx.table_set_columns(&[0, COORD_TYPE_SAFE_MAX]);
        ctx.table_set_cell_gap(Size { width: 1, height: 0 });
        ctx.inherit_focus();
        {
            ctx.table_next_row();
            ctx.inherit_focus();

            ctx.label("needle-label", loc(LocId::SearchNeedleLabel));

            if ctx.editline("needle", &mut state.encoding_picker_needle) {
                encoding_picker_update_list(state);
            }
            ctx.inherit_focus();
        }
        ctx.table_end();

        ctx.scrollarea_begin("scrollarea", Size { width, height });
        ctx.attr_background_rgba(ctx.indexed_alpha(IndexedColor::Black, 1, 4));
        {
            ctx.list_begin("encodings");
            ctx.inherit_focus();

            for enc in state
                .encoding_picker_results
                .as_deref()
                .unwrap_or_else(|| icu::get_available_encodings().preferred)
            {
                if ctx.list_item(enc.canonical == encoding, enc.label) == ListSelection::Activated {
                    change = Some(enc.canonical);
                    break;
                }
                ctx.attr_overflow(Overflow::TruncateTail);
            }
            ctx.list_end();
        }
        ctx.scrollarea_end();
    }
    done |= ctx.modal_end();
    done |= change.is_some();

    if let Some(encoding) = change
        && let Some(doc) = state.documents.active_mut()
    {
        if reopen && doc.path.is_some() {
            let mut res = Ok(());
            if doc.buffer.borrow().is_dirty() {
                res = doc.save(None);
            }
            if res.is_ok() {
                res = doc.reread(Some(encoding));
            }
            if let Err(err) = res {
                error_log_add(ctx, state, err);
            }
        } else {
            doc.buffer.borrow_mut().set_encoding(encoding);
        }
    }

    if done {
        state.wants_encoding_change = StateEncodingChange::None;
        state.encoding_picker_needle.clear();
        state.encoding_picker_results = None;
        ctx.needs_rerender();
    }
}

fn encoding_picker_update_list(state: &mut State) {
    state.encoding_picker_results = None;

    let needle = state.encoding_picker_needle.trim_ascii();
    if needle.is_empty() {
        return;
    }

    let encodings = icu::get_available_encodings();
    let scratch = scratch_arena(None);
    let mut matches = BVec::empty();

    for enc in encodings.all {
        let local_scratch = scratch_arena(Some(&scratch));
        let (score, _) = score_fuzzy(&local_scratch, enc.label, needle, true);

        if score > 0 {
            matches.push(&*scratch, (score, *enc));
        }
    }

    matches.sort_unstable_by_key(|b| std::cmp::Reverse(b.0));
    state.encoding_picker_results = Some(Vec::from_iter(matches.iter().map(|(_, enc)| *enc)));
}

pub fn draw_go_to_file(ctx: &mut Context, state: &mut State) {
    ctx.modal_begin("go-to-file", loc(LocId::ViewGoToFile));
    {
        let width = (ctx.size().width - 20).max(10);
        let height = (ctx.size().height - 10).max(10);

        ctx.scrollarea_begin("scrollarea", Size { width, height });
        ctx.attr_background_rgba(ctx.indexed_alpha(IndexedColor::Black, 1, 4));
        ctx.inherit_focus();
        {
            ctx.list_begin("documents");
            ctx.inherit_focus();

            if state.documents.update_active(|doc| {
                let tb = doc.buffer.borrow();

                ctx.styled_list_item_begin();
                ctx.attr_overflow(Overflow::TruncateTail);
                ctx.styled_label_add_text(if tb.is_dirty() { "* " } else { "  " });
                ctx.styled_label_add_text(&doc.filename);

                if let Some(path) = &doc.dir {
                    ctx.styled_label_add_text("   ");
                    ctx.styled_label_set_attributes(Attributes::Italic);
                    ctx.styled_label_add_text(path.as_str());
                }

                ctx.styled_list_item_end(false) == ListSelection::Activated
            }) {
                state.wants_go_to_file = false;
                ctx.needs_rerender();
            }

            ctx.list_end();
        }
        ctx.scrollarea_end();
    }
    if ctx.modal_end() {
        state.wants_go_to_file = false;
    }
}


================================================
FILE: crates/edit/src/bin/edit/edit.exe.manifest
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly
    xmlns="urn:schemas-microsoft-com:asm.v1"
    xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
    xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings"
    xmlns:ws3="http://schemas.microsoft.com/SMI/2019/WindowsSettings"
    xmlns:ws4="http://schemas.microsoft.com/SMI/2020/WindowsSettings"
    manifestVersion="1.0">
    <asmv3:application>
        <windowsSettings>
            <ws2:longPathAware>true</ws2:longPathAware>
            <ws3:activeCodePage>UTF-8</ws3:activeCodePage>
            <ws4:heapType>SegmentHeap</ws4:heapType>
        </windowsSettings>
    </asmv3:application>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        </application>
    </compatibility>
</assembly>


================================================
FILE: crates/edit/src/bin/edit/localization.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use edit::sys;
use stdext::AsciiStringHelpers as _;
use stdext::arena::scratch_arena;

include!(concat!(env!("OUT_DIR"), "/i18n_edit.rs"));

static mut S_LANG: LangId = LangId::en;

pub fn init() {
    let scratch = scratch_arena(None);
    let langs = sys::preferred_languages(&scratch);
    let mut lang = LangId::en;

    'outer: for l in langs {
        for (prefix, id) in LANGUAGES {
            if l.starts_with_ignore_ascii_case(prefix) {
                lang = *id;
                break 'outer;
            }
        }
    }

    unsafe {
        S_LANG = lang;
    }
}

pub fn loc(id: LocId) -> &'static str {
    TRANSLATIONS[unsafe { S_LANG as usize }][id as usize]
}


================================================
FILE: crates/edit/src/bin/edit/main.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

mod apperr;
mod documents;
mod draw_editor;
mod draw_filepicker;
mod draw_menubar;
mod draw_statusbar;
mod localization;
mod state;

use std::borrow::Cow;
use std::path::Path;
use std::time::Duration;
use std::{env, process};

use draw_editor::*;
use draw_filepicker::*;
use draw_menubar::*;
use draw_statusbar::*;
use edit::framebuffer::{self, IndexedColor};
use edit::helpers::*;
use edit::input::{self, kbmod, vk};
use edit::oklab::StraightRgba;
use edit::tui::*;
use edit::vt::{self, Token};
use edit::{base64, path, sys, unicode};
use localization::*;
use state::*;
use stdext::arena::{self, Arena, scratch_arena};
use stdext::arena_format;
use stdext::collections::{BString, BVec};

#[cfg(target_pointer_width = "32")]
const SCRATCH_ARENA_CAPACITY: usize = 128 * MEBI;
#[cfg(target_pointer_width = "64")]
const SCRATCH_ARENA_CAPACITY: usize = 512 * MEBI;

// NOTE: Before our main() gets called, Rust initializes its stdlib. This pulls in the entire
// std::io::{stdin, stdout, stderr} machinery, and probably some more, which amounts to about 20KB.
// It can technically be avoided nowadays with `#![no_main]`. Maybe a fun project for later? :)
fn main() -> process::ExitCode {
    if cfg!(debug_assertions) {
        let hook = std::panic::take_hook();
        std::panic::set_hook(Box::new(move |info| {
            drop(RestoreModes);
            drop(sys::Deinit);
            hook(info);
        }));
    }

    match run() {
        Ok(()) => process::ExitCode::SUCCESS,
        Err(err) => {
            sys::write_stdout(&format!("{}\n", FormatApperr::from(err)));
            process::ExitCode::FAILURE
        }
    }
}

fn run() -> apperr::Result<()> {
    // Init `sys` first, as everything else may depend on its functionality (IO, function pointers, etc.).
    let _sys_deinit = sys::init();
    // Next init `arena`, so that `scratch_arena` works. `loc` depends on it.
    arena::init(SCRATCH_ARENA_CAPACITY)?;
    // Init the `loc` module, so that error messages are localized.
    localization::init();

    let mut state = State::new()?;
    if handle_args(&mut state)? {
        return Ok(());
    }

    // This will reopen stdin if it's redirected (which may fail) and switch
    // the terminal to raw mode which prevents the user from pressing Ctrl+C.
    // `handle_args` may want to print a help message (must not fail),
    // and reads files (may hang; should be cancelable with Ctrl+C).
    // As such, we call this after `handle_args`.
    sys::switch_modes()?;

    let mut vt_parser = vt::Parser::new();
    let mut input_parser = input::Parser::new();
    let mut tui = Tui::new()?;

    let _restore = setup_terminal(&mut tui, &mut state, &mut vt_parser);

    state.menubar_color_bg = tui.indexed(IndexedColor::Background).oklab_blend(tui.indexed_alpha(
        IndexedColor::BrightBlue,
        1,
        2,
    ));
    state.menubar_color_fg = tui.contrasted(state.menubar_color_bg);
    let floater_bg = tui
        .indexed_alpha(IndexedColor::Background, 2, 3)
        .oklab_blend(tui.indexed_alpha(IndexedColor::Foreground, 1, 3));
    let floater_fg = tui.contrasted(floater_bg);
    tui.setup_modifier_translations(ModifierTranslations {
        ctrl: loc(LocId::Ctrl),
        alt: loc(LocId::Alt),
        shift: loc(LocId::Shift),
    });
    tui.set_floater_default_bg(floater_bg);
    tui.set_floater_default_fg(floater_fg);
    tui.set_modal_default_bg(floater_bg);
    tui.set_modal_default_fg(floater_fg);

    sys::inject_window_size_into_stdin();

    #[cfg(feature = "debug-latency")]
    let mut last_latency_width = 0;

    loop {
        #[cfg(feature = "debug-latency")]
        let time_beg;
        #[cfg(feature = "debug-latency")]
        let mut passes;

        // Process a batch of input.
        {
            let scratch = scratch_arena(None);
            let read_timeout = vt_parser.read_timeout().min(tui.read_timeout());
            let Some(input) = sys::read_stdin(&scratch, read_timeout) else {
                break;
            };

            #[cfg(feature = "debug-latency")]
            {
                time_beg = std::time::Instant::now();
                passes = 0usize;
            }

            let vt_iter = vt_parser.parse(&input);
            let mut input_iter = input_parser.parse(vt_iter);

            while {
                let input = input_iter.next();
                let more = input.is_some();
                let mut ctx = tui.create_context(input);

                draw(&mut ctx, &mut state);

                #[cfg(feature = "debug-latency")]
                {
                    passes += 1;
                }

                more
            } {}
        }

        // Continue rendering until the layout has settled.
        // This can take >1 frame, if the input focus is tossed between different controls.
        while tui.needs_settling() {
            let mut ctx = tui.create_context(None);

            draw(&mut ctx, &mut state);

            #[cfg(feature = "debug-latency")]
            {
                passes += 1;
            }
        }

        if state.exit {
            break;
        }

        // Render the UI and write it to the terminal.
        {
            let scratch = scratch_arena(None);
            let mut output = tui.render(&scratch);

            write_terminal_title(&scratch, &mut output, &mut state);

            if state.osc_clipboard_sync {
                write_osc_clipboard(&scratch, &mut output, &mut tui, &mut state);
            }

            #[cfg(feature = "debug-latency")]
            {
                use stdext::arena_write_fmt;

                // Print the number of passes and latency in the top right corner.
                let time_end = std::time::Instant::now();
                let status = time_end - time_beg;

                let scratch_alt = scratch_arena(Some(&scratch));
                let status = arena_format!(
                    &*scratch_alt,
                    "{}P {}B {:.3}μs",
                    passes,
                    output.len(),
                    status.as_nanos() as f64 / 1000.0
                );

                // "μs" is 3 bytes and 2 columns.
                let cols = status.len() as edit::helpers::CoordType - 3 + 2;

                // Since the status may shrink and grow, we may have to overwrite the previous one with whitespace.
                let padding = (last_latency_width - cols).max(0);

                // If the `output` is already very large,
                // Rust may double the size during the write below.
                // Let's avoid that by reserving the needed size in advance.
                output.reserve_exact(&*scratch, 128);

                // To avoid moving the cursor, push and pop it onto the VT cursor stack.
                arena_write_fmt!(
                    &*scratch,
                    output,
                    "\x1b7\x1b[0;41;97m\x1b[1;{0}H{1:2$}{3}\x1b8",
                    tui.size().width - cols - padding + 1,
                    "",
                    padding as usize,
                    status
                );

                last_latency_width = cols;
            }

            sys::write_stdout(&output);
        }
    }

    Ok(())
}

// Returns true if the application should exit early.
fn handle_args(state: &mut State) -> apperr::Result<bool> {
    let scratch = scratch_arena(None);
    let mut paths = BVec::empty();
    let cwd = env::current_dir()?;
    let mut dir = None;
    let mut parse_args = true;

    // The best CLI argument parser in the world.
    for arg in env::args_os().skip(1) {
        if parse_args {
            if arg == "--" {
                parse_args = false;
                continue;
            }
            if arg == "-" {
                paths.clear();
                break;
            }
            if arg == "-h" || arg == "--help" || (cfg!(windows) && arg == "/?") {
                print_help();
                return Ok(true);
            }
            if arg == "-v" || arg == "--version" {
                print_version();
                return Ok(true);
            }
        }

        let p = cwd.join(Path::new(&arg));
        let p = path::normalize(&p);
        if p.is_dir() {
            state.wants_file_picker = StateFilePicker::Open;
            dir = Some(p);
        } else {
            paths.push(&*scratch, p);
        }
    }

    for p in &paths {
        state.documents.add_file_path(p)?;
    }

    if let Some(mut file) = sys::open_stdin_if_redirected() {
        let doc = state.documents.add_untitled()?;
        let mut tb = doc.buffer.borrow_mut();
        tb.read_file(&mut file, None)?;
        tb.mark_as_dirty();
    } else if paths.is_empty() {
        // No files were passed, and stdin is not redirected.
        state.documents.add_untitled()?;
    }

    if dir.is_none()
        && let Some(parent) = paths.last().and_then(|p| p.parent())
    {
        dir = Some(parent.to_path_buf());
    }

    state.file_picker_pending_dir = DisplayablePathBuf::from_path(dir.unwrap_or(cwd));
    Ok(false)
}

fn print_help() {
    sys::write_stdout(concat!(
        "Usage: edit [OPTIONS] [FILE[:LINE[:COLUMN]]]\n",
        "Options:\n",
        "    -h, --help       Print this help message\n",
        "    -v, --version    Print the version number\n",
        "\n",
        "Arguments:\n",
        "    FILE[:LINE[:COLUMN]]    The file to open, optionally with line and column (e.g., foo.txt:123:45)\n",
    ));
}

fn print_version() {
    sys::write_stdout(concat!("edit version ", env!("CARGO_PKG_VERSION"), "\n"));
}

fn draw(ctx: &mut Context, state: &mut State) {
    draw_menubar(ctx, state);
    draw_editor(ctx, state);
    draw_statusbar(ctx, state);

    if state.wants_close {
        draw_handle_wants_close(ctx, state);
    }
    if state.wants_exit {
        draw_handle_wants_exit(ctx, state);
    }
    if state.wants_goto {
        draw_goto_menu(ctx, state);
    }
    if state.wants_file_picker != StateFilePicker::None {
        draw_file_picker(ctx, state);
    }
    if state.wants_save {
        draw_handle_save(ctx, state);
    }
    if state.wants_encoding_change != StateEncodingChange::None {
        draw_dialog_encoding_change(ctx, state);
    }
    if state.wants_go_to_file {
        draw_go_to_file(ctx, state);
    }
    if state.wants_about {
        draw_dialog_about(ctx, state);
    }
    if ctx.clipboard_ref().wants_host_sync() {
        draw_handle_clipboard_change(ctx, state);
    }
    if state.error_log_count != 0 {
        draw_error_log(ctx, state);
    }

    if let Some(key) = ctx.keyboard_input() {
        // Shortcuts that are not handled as part of the textarea, etc.

        if key == kbmod::CTRL | vk::N {
            draw_add_untitled_document(ctx, state);
        } else if key == kbmod::CTRL | vk::O {
            state.wants_file_picker = StateFilePicker::Open;
        } else if key == kbmod::CTRL | vk::S {
            state.wants_save = true;
        } else if key == kbmod::CTRL_SHIFT | vk::S {
            state.wants_file_picker = StateFilePicker::SaveAs;
        } else if key == kbmod::CTRL | vk::W {
            state.wants_close = true;
        } else if key == kbmod::CTRL | vk::P {
            state.wants_go_to_file = true;
        } else if key == kbmod::CTRL | vk::Q {
            state.wants_exit = true;
        } else if key == kbmod::CTRL | vk::G {
            state.wants_goto = true;
        } else if key == kbmod::CTRL | vk::F && state.wants_search.kind != StateSearchKind::Disabled
        {
            state.wants_search.kind = StateSearchKind::Search;
            state.wants_search.focus = true;
        } else if key == kbmod::CTRL | vk::R && state.wants_search.kind != StateSearchKind::Disabled
        {
            state.wants_search.kind = StateSearchKind::Replace;
            state.wants_search.focus = true;
        } else if key == vk::F3 {
            search_execute(ctx, state, SearchAction::Search);
        } else {
            return;
        }

        // All of the above shortcuts happen to require a rerender.
        ctx.needs_rerender();
        ctx.set_input_consumed();
    }
}

fn draw_handle_wants_exit(_ctx: &mut Context, state: &mut State) {
    while let Some(doc) = state.documents.active() {
        if doc.buffer.borrow().is_dirty() {
            state.wants_close = true;
            return;
        }
        state.documents.remove_active();
    }

    if state.documents.len() == 0 {
        state.exit = true;
    }
}

fn write_terminal_title<'a>(arena: &'a Arena, output: &mut BString<'a>, state: &mut State) {
    let (filename, dirty) = state
        .documents
        .active()
        .map_or(("", false), |d| (&d.filename, d.buffer.borrow().is_dirty()));

    if filename == state.osc_title_file_status.filename
        && dirty == state.osc_title_file_status.dirty
    {
        return;
    }

    output.push_str(arena, "\x1b]0;");
    if !filename.is_empty() {
        if dirty {
            output.push_str(arena, "● ");
        }
        output.push_str(arena, &sanitize_control_chars(filename));
        output.push_str(arena, " - ");
    }
    output.push_str(arena, "edit\x1b\\");

    state.osc_title_file_status.filename = filename.to_string();
    state.osc_title_file_status.dirty = dirty;
}

const LARGE_CLIPBOARD_THRESHOLD: usize = 128 * KIBI;

fn draw_handle_clipboard_change(ctx: &mut Context, state: &mut State) {
    let data_len = ctx.clipboard_ref().read().len();

    if state.osc_clipboard_always_send || data_len < LARGE_CLIPBOARD_THRESHOLD {
        ctx.clipboard_mut().mark_as_synchronized();
        state.osc_clipboard_sync = true;
        return;
    }

    let over_limit = data_len >= SCRATCH_ARENA_CAPACITY / 4;
    let mut done = None;

    ctx.modal_begin("warning", loc(LocId::WarningDialogTitle));
    {
        ctx.block_begin("description");
        ctx.attr_padding(Rect::three(1, 2, 1));

        if over_limit {
            ctx.label("line1", loc(LocId::LargeClipboardWarningLine1));
            ctx.attr_position(Position::Center);
            ctx.label("line2", loc(LocId::SuperLargeClipboardWarning));
            ctx.attr_position(Position::Center);
        } else {
            let label2 = {
                let template = loc(LocId::LargeClipboardWarningLine2);
                let size = arena_format!(ctx.arena(), "{}", MetricFormatter(data_len));

                let mut label = BString::empty();
                label.reserve(ctx.arena(), template.len() + size.len());
                label.push_str(ctx.arena(), template);
                label.replace_once_in_place(ctx.arena(), "{size}", &size);
                label
            };

            ctx.label("line1", loc(LocId::LargeClipboardWarningLine1));
            ctx.attr_position(Position::Center);
            ctx.label("line2", &label2);
            ctx.attr_position(Position::Center);
            ctx.label("line3", loc(LocId::LargeClipboardWarningLine3));
            ctx.attr_position(Position::Center);
        }
        ctx.block_end();

        ctx.table_begin("choices");
        ctx.inherit_focus();
        ctx.attr_padding(Rect::three(0, 2, 1));
        ctx.attr_position(Position::Center);
        ctx.table_set_cell_gap(Size { width: 2, height: 0 });
        {
            ctx.table_next_row();
            ctx.inherit_focus();

            if over_limit {
                if ctx.button("ok", loc(LocId::Ok), ButtonStyle::default()) {
                    done = Some(true);
                }
                ctx.inherit_focus();
            } else {
                if ctx.button("always", loc(LocId::Always), ButtonStyle::default()) {
                    state.osc_clipboard_always_send = true;
                    done = Some(true);
                }

                if ctx.button("yes", loc(LocId::Yes), ButtonStyle::default()) {
                    done = Some(true);
                }
                if data_len < 10 * LARGE_CLIPBOARD_THRESHOLD {
                    ctx.inherit_focus();
                }

                if ctx.button("no", loc(LocId::No), ButtonStyle::default()) {
                    done = Some(false);
                }
                if data_len >= 10 * LARGE_CLIPBOARD_THRESHOLD {
                    ctx.inherit_focus();
                }
            }
        }
        ctx.table_end();
    }
    if ctx.modal_end() {
        done = Some(false);
    }

    if let Some(sync) = done {
        state.osc_clipboard_sync = sync;
        ctx.clipboard_mut().mark_as_synchronized();
        ctx.needs_rerender();
    }
}

#[cold]
fn write_osc_clipboard<'a>(
    arena: &'a Arena,
    output: &mut BString<'a>,
    tui: &mut Tui,
    state: &mut State,
) {
    let clipboard = tui.clipboard_mut();
    let data = clipboard.read();

    if !data.is_empty() {
        // Rust doubles the size of a string when it needs to grow it.
        // If `data` is *really* large, this may then double
        // the size of the `output` from e.g. 100MB to 200MB. Not good.
        // We can avoid that by reserving the needed size in advance.
        output.reserve_exact(arena, base64::encode_len(data.len()) + 16);
        output.push_str(arena, "\x1b]52;c;");
        base64::encode(arena, output, data);
        output.push_str(arena, "\x1b\\");
    }

    state.osc_clipboard_sync = false;
}

struct RestoreModes;

impl Drop for RestoreModes {
    fn drop(&mut self) {
        // Same as in the beginning but in the reverse order.
        // It also includes DECSCUSR 0 to reset the cursor style and DECTCEM to show the cursor.
        // We specifically don't reset mode 1036, because most applications expect it to be set nowadays.
        sys::write_stdout("\x1b[0 q\x1b[?25h\x1b]0;\x07\x1b[?1002;1006;2004l\x1b[?1049l");
    }
}

fn setup_terminal(tui: &mut Tui, state: &mut State, vt_parser: &mut vt::Parser) -> RestoreModes {
    sys::write_stdout(concat!(
        // 1049: Alternative Screen Buffer
        //   I put the ASB switch in the beginning, just in case the terminal performs
        //   some additional state tracking beyond the modes we enable/disable.
        // 1002: Cell Motion Mouse Tracking
        // 1006: SGR Mouse Mode
        // 2004: Bracketed Paste Mode
        // 1036: Xterm: "meta sends escape" (Alt keypresses should be encoded with ESC + char)
        "\x1b[?1049h\x1b[?1002;1006;2004h\x1b[?1036h",
        // OSC 4 color table requests for indices 0 through 15 (base colors).
        "\x1b]4;0;?;1;?;2;?;3;?;4;?;5;?;6;?;7;?\x07",
        "\x1b]4;8;?;9;?;10;?;11;?;12;?;13;?;14;?;15;?\x07",
        // OSC 10 and 11 queries for the current foreground and background colors.
        "\x1b]10;?\x07\x1b]11;?\x07",
        // Test whether ambiguous width characters are two columns wide.
        // We use "…", because it's the most common ambiguous width character we use,
        // and the old Windows conhost doesn't actually use wcwidth, it measures the
        // actual display width of the character and assigns it columns accordingly.
        // We detect it by writing the character and asking for the cursor position.
        "\r…\x1b[6n",
        // CSI c reports the terminal capabilities.
        // It also helps us to detect the end of the responses, because not all
        // terminals support the OSC queries, but all of them support CSI c.
        "\x1b[c",
    ));

    let mut done = false;
    let mut osc_buffer = String::new();
    let mut indexed_colors = framebuffer::DEFAULT_THEME;
    let mut color_responses = 0;
    let mut ambiguous_width = 1;

    while !done {
        let scratch = scratch_arena(None);

        // We explicitly set a high read timeout, because we're not
        // waiting for user keyboard input. If we encounter a lone ESC,
        // it's unlikely to be from a ESC keypress, but rather from a VT sequence.
        let Some(input) = sys::read_stdin(&scratch, Duration::from_secs(3)) else {
            break;
        };

        let mut vt_stream = vt_parser.parse(&input);
        while let Some(token) = vt_stream.next() {
            match token {
                Token::Csi(csi) => match csi.final_byte {
                    'c' => done = true,
                    // CPR (Cursor Position Report) response.
                    'R' => ambiguous_width = csi.params[1] as CoordType - 1,
                    _ => {}
                },
                Token::Osc { mut data, partial } => {
                    if partial {
                        osc_buffer.push_str(data);
                        continue;
                    }
                    if !osc_buffer.is_empty() {
                        osc_buffer.push_str(data);
                        data = &osc_buffer;
                    }

                    let mut splits = data.split_terminator(';');

                    let color = match splits.next().unwrap_or("") {
                        // The response is `4;<color>;rgb:<r>/<g>/<b>`.
                        "4" => match splits.next().unwrap_or("").parse::<usize>() {
                            Ok(val) if val < 16 => &mut indexed_colors[val],
                            _ => continue,
                        },
                        // The response is `10;rgb:<r>/<g>/<b>`.
                        "10" => &mut indexed_colors[IndexedColor::Foreground as usize],
                        // The response is `11;rgb:<r>/<g>/<b>`.
                        "11" => &mut indexed_colors[IndexedColor::Background as usize],
                        _ => continue,
                    };

                    let color_param = splits.next().unwrap_or("");
                    if !color_param.starts_with("rgb:") {
                        continue;
                    }

                    let mut iter = color_param[4..].split_terminator('/');
                    let rgb_parts = [(); 3].map(|_| iter.next().unwrap_or("0"));
                    let mut rgb = 0;

                    for part in rgb_parts {
                        if part.len() == 2 || part.len() == 4 {
                            let Ok(mut val) = usize::from_str_radix(part, 16) else {
                                continue;
                            };
                            if part.len() == 4 {
                                // Round from 16 bits to 8 bits.
                                val = (val * 0xff + 0x7fff) / 0xffff;
                            }
                            rgb = (rgb >> 8) | ((val as u32) << 16);
                        }
                    }

                    *color = StraightRgba::from_le(rgb | 0xff000000);
                    color_responses += 1;
                    osc_buffer.clear();
                }
                _ => {}
            }
        }
    }

    if ambiguous_width == 2 {
        unicode::setup_ambiguous_width(2);
        state.documents.reflow_all();
    }

    if color_responses == indexed_colors.len() {
        tui.setup_indexed_colors(indexed_colors);
    }

    RestoreModes
}

/// Strips all C0 control characters from the string and replaces them with "_".
///
/// Jury is still out on whether this should also strip C1 control characters.
/// That requires parsing UTF8 codepoints, which is annoying.
fn sanitize_control_chars(text: &str) -> Cow<'_, str> {
    if let Some(off) = text.bytes().position(|b| (..0x20).contains(&b)) {
        let mut sanitized = text.to_string();
        // SAFETY: We only search for ASCII and replace it with ASCII.
        let vec = unsafe { sanitized.as_bytes_mut() };

        for i in &mut vec[off..] {
            *i = if (..0x20).contains(i) { b'_' } else { *i }
        }

        Cow::Owned(sanitized)
    } else {
        Cow::Borrowed(text)
    }
}


================================================
FILE: crates/edit/src/bin/edit/state.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::mem;
use std::path::{Path, PathBuf};

use edit::framebuffer::IndexedColor;
use edit::helpers::*;
use edit::oklab::StraightRgba;
use edit::tui::*;
use edit::{buffer, icu};

use crate::apperr;
use crate::documents::DocumentManager;
use crate::localization::*;

#[repr(transparent)]
pub struct FormatApperr(apperr::Error);

impl From<apperr::Error> for FormatApperr {
    fn from(err: apperr::Error) -> Self {
        Self(err)
    }
}

impl std::fmt::Display for FormatApperr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self.0 {
            apperr::Error::Icu(icu::ICU_MISSING_ERROR) => f.write_str(loc(LocId::ErrorIcuMissing)),
            apperr::Error::Icu(ref err) => err.fmt(f),
            apperr::Error::Io(ref err) => err.fmt(f),
        }
    }
}

pub struct DisplayablePathBuf {
    value: PathBuf,
    str: Cow<'static, str>,
}

impl DisplayablePathBuf {
    #[allow(dead_code, reason = "only used on Windows")]
    pub fn from_string(string: String) -> Self {
        let str = Cow::Borrowed(string.as_str());
        let str = unsafe { mem::transmute::<Cow<'_, str>, Cow<'_, str>>(str) };
        let value = PathBuf::from(string);
        Self { value, str }
    }

    pub fn from_path(value: PathBuf) -> Self {
        let str = value.to_string_lossy();
        let str = unsafe { mem::transmute::<Cow<'_, str>, Cow<'_, str>>(str) };
        Self { value, str }
    }

    pub fn as_path(&self) -> &Path {
        &self.value
    }

    pub fn as_str(&self) -> &str {
        &self.str
    }

    pub fn as_bytes(&self) -> &[u8] {
        self.value.as_os_str().as_encoded_bytes()
    }
}

impl Default for DisplayablePathBuf {
    fn default() -> Self {
        Self { value: Default::default(), str: Cow::Borrowed("") }
    }
}

impl Clone for DisplayablePathBuf {
    fn clone(&self) -> Self {
        Self::from_path(self.value.clone())
    }
}

impl From<OsString> for DisplayablePathBuf {
    fn from(s: OsString) -> Self {
        Self::from_path(PathBuf::from(s))
    }
}

impl<T: ?Sized + AsRef<OsStr>> From<&T> for DisplayablePathBuf {
    fn from(s: &T) -> Self {
        Self::from_path(PathBuf::from(s))
    }
}

pub struct StateSearch {
    pub kind: StateSearchKind,
    pub focus: bool,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum StateSearchKind {
    Hidden,
    Disabled,
    Search,
    Replace,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum StateFilePicker {
    None,
    Open,
    SaveAs,

    SaveAsShown, // Transitioned from SaveAs
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum StateEncodingChange {
    None,
    Convert,
    Reopen,
}

#[derive(Default)]
pub struct OscTitleFileStatus {
    pub filename: String,
    pub dirty: bool,
}

pub struct State {
    pub menubar_color_bg: StraightRgba,
    pub menubar_color_fg: StraightRgba,

    pub documents: DocumentManager,

    // A ring buffer of the last 10 errors.
    pub error_log: [String; 10],
    pub error_log_index: usize,
    pub error_log_count: usize,

    pub wants_file_picker: StateFilePicker,
    pub file_picker_pending_dir: DisplayablePathBuf,
    pub file_picker_pending_dir_revision: u64, // Bumped every time `file_picker_pending_dir` changes.
    pub file_picker_pending_name: PathBuf,
    pub file_picker_entries: Option<[Vec<DisplayablePathBuf>; 3]>, // ["..", directories, files]
    pub file_picker_overwrite_warning: Option<PathBuf>,            // The path the warning is about.
    pub file_picker_autocomplete: Vec<DisplayablePathBuf>,

    pub wants_search: StateSearch,
    pub search_needle: String,
    pub search_replacement: String,
    pub search_options: buffer::SearchOptions,
    pub search_success: bool,

    pub wants_encoding_picker: bool,
    pub wants_encoding_change: StateEncodingChange,
    pub encoding_picker_needle: String,
    pub encoding_picker_results: Option<Vec<icu::Encoding>>,

    pub wants_save: bool,
    pub wants_statusbar_focus: bool,
    pub wants_indentation_picker: bool,
    pub wants_go_to_file: bool,
    pub wants_about: bool,
    pub wants_close: bool,
    pub wants_exit: bool,
    pub wants_goto: bool,
    pub goto_target: String,
    pub goto_invalid: bool,

    pub osc_title_file_status: OscTitleFileStatus,
    pub osc_clipboard_sync: bool,
    pub osc_clipboard_always_send: bool,
    pub exit: bool,
}

impl State {
    pub fn new() -> apperr::Result<Self> {
        Ok(Self {
            menubar_color_bg: StraightRgba::zero(),
            menubar_color_fg: StraightRgba::zero(),

            documents: Default::default(),

            error_log: [const { String::new() }; 10],
            error_log_index: 0,
            error_log_count: 0,

            wants_file_picker: StateFilePicker::None,
            file_picker_pending_dir: Default::default(),
            file_picker_pending_dir_revision: 0,
            file_picker_pending_name: Default::default(),
            file_picker_entries: None,
            file_picker_overwrite_warning: None,
            file_picker_autocomplete: Vec::new(),

            wants_search: StateSearch { kind: StateSearchKind::Hidden, focus: false },
            search_needle: Default::default(),
            search_replacement: Default::default(),
            search_options: Default::default(),
            search_success: true,

            wants_encoding_picker: false,
            encoding_picker_needle: Default::default(),
            encoding_picker_results: Default::default(),

            wants_save: false,
            wants_statusbar_focus: false,
            wants_encoding_change: StateEncodingChange::None,
            wants_indentation_picker: false,
            wants_go_to_file: false,
            wants_about: false,
            wants_close: false,
            wants_exit: false,
            wants_goto: false,
            goto_target: Default::default(),
            goto_invalid: false,

            osc_title_file_status: Default::default(),
            osc_clipboard_sync: false,
            osc_clipboard_always_send: false,
            exit: false,
        })
    }
}

pub fn draw_add_untitled_document(ctx: &mut Context, state: &mut State) {
    if let Err(err) = state.documents.add_untitled() {
        error_log_add(ctx, state, err);
    }
}

pub fn error_log_add(ctx: &mut Context, state: &mut State, err: apperr::Error) {
    let msg = format!("{}", FormatApperr::from(err));
    if !msg.is_empty() {
        state.error_log[state.error_log_index] = msg;
        state.error_log_index = (state.error_log_index + 1) % state.error_log.len();
        state.error_log_count = state.error_log.len().min(state.error_log_count + 1);
        ctx.needs_rerender();
    }
}

pub fn draw_error_log(ctx: &mut Context, state: &mut State) {
    ctx.modal_begin("error", loc(LocId::ErrorDialogTitle));
    ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red));
    ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite));
    {
        ctx.block_begin("content");
        ctx.attr_padding(Rect::three(0, 2, 1));
        {
            let off = state.error_log_index + state.error_log.len() - state.error_log_count;

            for i in 0..state.error_log_count {
                let idx = (off + i) % state.error_log.len();
                let msg = &state.error_log[idx][..];

                if !msg.is_empty() {
                    ctx.next_block_id_mixin(i as u64);
                    ctx.label("error", msg);
                    ctx.attr_overflow(Overflow::TruncateTail);
                }
            }
        }
        ctx.block_end();

        if ctx.button("ok", loc(LocId::Ok), ButtonStyle::default()) {
            state.error_log_count = 0;
        }
        ctx.attr_position(Position::Center);
        ctx.inherit_focus();
    }
    if ctx.modal_end() {
        state.error_log_count = 0;
    }
}


================================================
FILE: crates/edit/src/buffer/gap_buffer.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::ops::Range;
use std::ptr::{self, NonNull};
use std::{io, slice};

use stdext::sys::{virtual_commit, virtual_release, virtual_reserve};
use stdext::{ReplaceRange as _, slice_copy_safe};

use crate::document::{ReadableDocument, WriteableDocument};
use crate::helpers::*;

#[cfg(target_pointer_width = "32")]
const LARGE_CAPACITY: usize = 128 * MEBI;
#[cfg(target_pointer_width = "64")]
const LARGE_CAPACITY: usize = 4 * GIBI;
const LARGE_ALLOC_CHUNK: usize = 64 * KIBI;
const LARGE_GAP_CHUNK: usize = 4 * KIBI;

const SMALL_CAPACITY: usize = 128 * KIBI;
const SMALL_ALLOC_CHUNK: usize = 256;
const SMALL_GAP_CHUNK: usize = 16;

// TODO: Instead of having a specialization for small buffers here,
// tui.rs could also just keep a MRU set of large buffers around.
enum BackingBuffer {
    VirtualMemory(NonNull<u8>, usize),
    Vec(Vec<u8>),
}

impl Drop for BackingBuffer {
    fn drop(&mut self) {
        unsafe {
            if let Self::VirtualMemory(ptr, reserve) = *self {
                virtual_release(ptr, reserve);
            }
        }
    }
}

/// Most people know how `Vec<T>` works: It has some spare capacity at the end,
/// so that pushing into it doesn't reallocate every single time. A gap buffer
/// is the same thing, but the spare capacity can be anywhere in the buffer.
/// This variant is optimized for large buffers and uses virtual memory.
pub struct GapBuffer {
    /// Pointer to the buffer.
    text: NonNull<u8>,
    /// Maximum size of the buffer, including gap.
    reserve: usize,
    /// Size of the buffer, including gap.
    commit: usize,
    /// Length of the stored text, NOT including gap.
    text_length: usize,
    /// Gap offset.
    gap_off: usize,
    /// Gap length.
    gap_len: usize,
    /// Increments every time the buffer is modified.
    generation: u32,
    /// If `Vec(..)`, the buffer is optimized for small amounts of text
    /// and uses the standard heap. Otherwise, it uses virtual memory.
    buffer: BackingBuffer,
}

impl GapBuffer {
    pub fn new(small: bool) -> io::Result<Self> {
        let reserve;
        let buffer;
        let text;

        if small {
            reserve = SMALL_CAPACITY;
            text = NonNull::dangling();
            buffer = BackingBuffer::Vec(Vec::new());
        } else {
            reserve = LARGE_CAPACITY;
            text = unsafe { virtual_reserve(reserve)? };
            buffer = BackingBuffer::VirtualMemory(text, reserve);
        }

        Ok(Self {
            text,
            reserve,
            commit: 0,
            text_length: 0,
            gap_off: 0,
            gap_len: 0,
            generation: 0,
            buffer,
        })
    }

    #[allow(clippy::len_without_is_empty)]
    pub fn len(&self) -> usize {
        self.text_length
    }

    pub fn generation(&self) -> u32 {
        self.generation
    }

    pub fn set_generation(&mut self, generation: u32) {
        self.generation = generation;
    }

    /// WARNING: The returned slice must not necessarily be the same length as `len` (due to OOM).
    pub fn allocate_gap(&mut self, off: usize, len: usize, delete: usize) -> &mut [u8] {
        // Sanitize parameters
        let off = off.min(self.text_length);
        let delete = delete.min(self.text_length - off);

        // Move the existing gap if it exists
        if off != self.gap_off {
            self.move_gap(off);
        }

        // Delete the text
        if delete > 0 {
            self.delete_text(delete);
        }

        // Enlarge the gap if needed
        if len > self.gap_len {
            self.enlarge_gap(len);
        }

        self.generation = self.generation.wrapping_add(1);
        unsafe { slice::from_raw_parts_mut(self.text.add(self.gap_off).as_ptr(), self.gap_len) }
    }

    fn move_gap(&mut self, off: usize) {
        if self.gap_len > 0 {
            //
            //                       v gap_off
            // left:  |ABCDEFGHIJKLMN   OPQRSTUVWXYZ|
            //        |ABCDEFGHI   JKLMNOPQRSTUVWXYZ|
            //                  ^ off
            //        move: JKLMN
            //
            //                       v gap_off
            // !left: |ABCDEFGHIJKLMN   OPQRSTUVWXYZ|
            //        |ABCDEFGHIJKLMNOPQRS   TUVWXYZ|
            //                            ^ off
            //        move: OPQRS
            //
            let left = off < self.gap_off;
            let move_src = if left { off } else { self.gap_off + self.gap_len };
            let move_dst = if left { off + self.gap_len } else { self.gap_off };
            let move_len = if left { self.gap_off - off } else { off - self.gap_off };

            unsafe { self.text.add(move_src).copy_to(self.text.add(move_dst), move_len) };

            if cfg!(debug_assertions) {
                // Fill the moved-out bytes with 0xCD to make debugging easier.
                unsafe { self.text.add(off).write_bytes(0xCD, self.gap_len) };
            }
        }

        self.gap_off = off;
    }

    fn delete_text(&mut self, delete: usize) {
        if cfg!(debug_assertions) {
            // Fill the deleted bytes with 0xCD to make debugging easier.
            unsafe { self.text.add(self.gap_off + self.gap_len).write_bytes(0xCD, delete) };
        }

        self.gap_len += delete;
        self.text_length -= delete;
    }

    fn enlarge_gap(&mut self, len: usize) {
        let gap_chunk;
        let alloc_chunk;

        if matches!(self.buffer, BackingBuffer::VirtualMemory(..)) {
            gap_chunk = LARGE_GAP_CHUNK;
            alloc_chunk = LARGE_ALLOC_CHUNK;
        } else {
            gap_chunk = SMALL_GAP_CHUNK;
            alloc_chunk = SMALL_ALLOC_CHUNK;
        }

        let gap_len_old = self.gap_len;
        let gap_len_new = (len + gap_chunk + gap_chunk - 1) & !(gap_chunk - 1);

        let bytes_old = self.commit;
        let bytes_new = self.text_length + gap_len_new;

        if bytes_new > bytes_old {
            let bytes_new = (bytes_new + alloc_chunk - 1) & !(alloc_chunk - 1);

            if bytes_new > self.reserve {
                return;
            }

            match &mut self.buffer {
                BackingBuffer::VirtualMemory(ptr, _) => unsafe {
                    if virtual_commit(ptr.add(bytes_old), bytes_new - bytes_old).is_err() {
                        return;
                    }
                },
                BackingBuffer::Vec(v) => {
                    v.resize(bytes_new, 0);
                    self.text = unsafe { NonNull::new_unchecked(v.as_mut_ptr()) };
                }
            }

            self.commit = bytes_new;
        }

        let gap_beg = unsafe { self.text.add(self.gap_off) };
        unsafe {
            ptr::copy(
                gap_beg.add(gap_len_old).as_ptr(),
                gap_beg.add(gap_len_new).as_ptr(),
                self.text_length - self.gap_off,
            )
        };

        if cfg!(debug_assertions) {
            // Fill the moved-out bytes with 0xCD to make debugging easier.
            unsafe { gap_beg.add(gap_len_old).write_bytes(0xCD, gap_len_new - gap_len_old) };
        }

        self.gap_len = gap_len_new;
    }

    pub fn commit_gap(&mut self, len: usize) {
        assert!(len <= self.gap_len);
        self.text_length += len;
        self.gap_off += len;
        self.gap_len -= len;
    }

    pub fn replace(&mut self, range: Range<usize>, src: &[u8]) {
        let gap = self.allocate_gap(range.start, src.len(), range.end.saturating_sub(range.start));
        let len = slice_copy_safe(gap, src);
        self.commit_gap(len);
    }

    pub fn clear(&mut self) {
        self.gap_off = 0;
        self.gap_len += self.text_length;
        self.generation = self.generation.wrapping_add(1);
        self.text_length = 0;
    }

    pub fn extract_raw(&self, range: Range<usize>, out: &mut Vec<u8>, mut out_off: usize) {
        let end = range.end.min(self.text_length);
        let mut beg = range.start.min(end);
        out_off = out_off.min(out.len());

        if beg >= end {
            return;
        }

        out.reserve(end - beg);

        while beg < end {
            let chunk = self.read_forward(beg);
            let chunk = &chunk[..chunk.len().min(end - beg)];
            out.replace_range(out_off..out_off, chunk);
            beg += chunk.len();
            out_off += chunk.len();
        }
    }

    /// Replaces the entire buffer contents with the given `text`.
    /// The method is optimized for the case where the given `text` already matches
    /// the existing contents. Returns `true` if the buffer contents were changed.
    pub fn copy_from(&mut self, src: &dyn ReadableDocument) -> bool {
        let mut off = 0;

        // Find the position at which the contents change.
        loop {
            let dst_chunk = self.read_forward(off);
            let src_chunk = src.read_forward(off);

            let dst_len = dst_chunk.len();
            let src_len = src_chunk.len();
            let len = dst_len.min(src_len);
            let mismatch = dst_chunk[..len] != src_chunk[..len];

            if mismatch {
                break; // The contents differ.
            }
            if len == 0 {
                if dst_len == src_len {
                    return false; // Both done simultaneously. -> Done.
                }
                break; // One of the two is shorter.
            }

            off += len;
        }

        // Update the buffer starting at `off`.
        loop {
            let chunk = src.read_forward(off);
            self.replace(off..usize::MAX, chunk);
            off += chunk.len();

            // No more data to copy -> Done. By checking this _after_ the replace()
            // call, we ensure that the initial `off..usize::MAX` range is deleted.
            // This fixes going from some buffer contents to being empty.
            if chunk.is_empty() {
                return true;
            }
        }
    }

    /// Copies the contents of the buffer into a string.
    pub fn copy_into(&self, dst: &mut dyn WriteableDocument) {
        let mut beg = 0;
        let mut off = 0;

        while {
            let chunk = self.read_forward(off);

            // The first write will be 0..usize::MAX and effectively clear() the destination.
            // Every subsequent write will be usize::MAX..usize::MAX and thus effectively append().
            dst.replace(beg..usize::MAX, chunk);
            beg = usize::MAX;

            off += chunk.len();
            off < self.text_length
        } {}
    }
}

impl ReadableDocument for GapBuffer {
    fn read_forward(&self, off: usize) -> &[u8] {
        let off = off.min(self.text_length);
        let beg;
        let len;

        if off < self.gap_off {
            // Cursor is before the gap: We can read until the start of the gap.
            beg = off;
            len = self.gap_off - off;
        } else {
            // Cursor is after the gap: We can read until the end of the buffer.
            beg = off + self.gap_len;
            len = self.text_length - off;
        }

        unsafe { slice::from_raw_parts(self.text.add(beg).as_ptr(), len) }
    }

    fn read_backward(&self, off: usize) -> &[u8] {
        let off = off.min(self.text_length);
        let beg;
        let len;

        if off <= self.gap_off {
            // Cursor is before the gap: We can read until the beginning of the buffer.
            beg = 0;
            len = off;
        } else {
            // Cursor is after the gap: We can read until the end of the gap.
            beg = self.gap_off + self.gap_len;
            // The cursor_off doesn't account of the gap_len.
            // (This allows us to move the gap without recalculating the cursor position.)
            len = off - self.gap_off;
        }

        unsafe { slice::from_raw_parts(self.text.add(beg).as_ptr(), len) }
    }
}


================================================
FILE: crates/edit/src/buffer/line_cache.rs
================================================
use std::ops::Range;

use crate::{document::ReadableDocument, simd::memchr2};

/// Cache a line/offset pair every CACHE_EVERY lines to speed up line/offset calculations
const CACHE_EVERY: usize = 1024 * 64;

#[derive(Clone)]
pub struct CachePoint {
    pub index: usize,
    pub line: usize,
    // pub snapshot: ParserSnapshot
}

pub struct LineCache {
    cache: Vec<CachePoint>,
}

impl LineCache {
    pub fn new() -> Self {
        Self { cache: vec![] }
    }

    pub fn from_document<T: ReadableDocument>(&mut self, document: &T) {
        self.cache.clear();

        let mut offset = 0;
        let mut line = 0;
        loop {
            let text = document.read_forward(offset);
            if text.is_empty() { return; }
            
            let mut off = 0;
            loop {
                off = memchr2(b'\n', b'\n', text, off);
                if off == text.len() { break; }

                if line % CACHE_EVERY == 0 {
                    self.cache.push(CachePoint { index: offset+off, line });
                }
                line += 1;
                off += 1;
            }

            offset += text.len();
        }
    }

    /// Updates the cache after a deletion.
    /// `range` is the deleted byte range, and `text` is the content that was deleted.
    pub fn delete(&mut self, range: Range<usize>, text: &Vec<u8>) {
        let mut newlines = 0;
        for c in text {
            if *c == b'\n' {
                newlines += 1;
            }
        }

        let mut beg_del = None;
        let mut end_del = None;
        for (i, point) in self.cache.iter_mut().enumerate() {
            if point.index >= range.start {
                if point.index < range.end {
                    // cache point is within the deleted range
                    if beg_del.is_none() { beg_del = Some(i); }
                    end_del = Some(i + 1);
                }
                else {
                    point.index -= text.len();
                    point.line -= newlines;
                }
            }
        }

        if let (Some(beg), Some(end)) = (beg_del, end_del) {
            self.cache.drain(beg..end);
        }
    }

    /// Updates the cache after an insertion.
    /// `offset` is where the insertion occurs, and `text` is the inserted content.
    pub fn insert(&mut self, offset: usize, text: &[u8]) {
        // Count how many newlines were inserted
        let mut newlines = 0;
        for c in text {
            if *c == b'\n' {
                newlines += 1;
            }
        }

        let len = text.len();
        for point in &mut self.cache {
            if point.index > offset {
                point.index += len;
                point.line += newlines;
            }
        }

        // TODO: This also needs to insert new cache points
    }

    /// Finds the nearest cached line-offset pair relative to a target line.
    /// If `reverse` is false, it returns the closest *before* the target.
    /// If `reverse` is true, it returns the closest *after or at* the target.
    pub fn nearest_offset(&self, target_count: usize, reverse: bool) -> Option<CachePoint> {
        match self.cache.binary_search_by_key(&target_count, |p| p.line) {
            Ok(i) => Some(self.cache[i].clone()),
            Err(i) => {
                if i == 0 || i == self.cache.len() { None }  // target < lowest cache point || target > highest cache point
                else {
                    Some(self.cache[ if reverse {i} else {i-1} ].clone())
                }
            }
        }
    }
}


================================================
FILE: crates/edit/src/buffer/mod.rs
================================================
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! A text buffer for a text editor.
//!
//! Implements a Unicode-aware, layout-aware text buffer for terminals.
//! It's based on a gap buffer. It has no line cache and instead relies
//! on the performance of the ucd module for fast text navigation.
//!
//! ---
//!
//! If the project ever outgrows a basic gap buffer (e.g. to add time travel)
//! an ideal, alternative architecture would be a piece table with immutable trees.
//! The tree nodes can be allocated on the same arena allocator as the added chunks,
//! making lifetime management fairly easy. The algorithm is described here:
//! * <https://cdacamar.github.io/data%20structures/algorithms/benchmarking/text%20editors/c++/editor-data-structures/>
//! * <https://github.com/cdacamar/fredbuf>
//!
//! The downside is that text navigation & search takes a performance hit due to small chunks.
//! The solution to the former is to keep line caches, which further complicates the architecture.
//! There's no solution for the latter. However, there's a chance that the performance will still be sufficient.

mod gap_buffer;
mod navigation;

use std::borrow::Cow;
use std::cell::UnsafeCell;
use std::collections::VecDeque;
use std::fs::File;
use std::io::{self, Read as _, Write as _};
use std::mem::{self, MaybeUninit};
use std::ops::Range;
use std::rc::Rc;
use std::str;

pub use gap_buffer::GapBuffer;
use stdext::arena::{Arena, scratch_arena};
use stdext::collections::{BString, BVec};
use stdext::unicode::Utf8Chars;
use stdext::{ReplaceRange as _, arena_write_fmt, minmax, slice_as_uninit_mut, slice_copy_safe};

use crate::cell::SemiRefCell;
use crate::clipboard::Clipboard;
use crate::document::{ReadableDocument, WriteableDocument};
use crate::framebuffer::{Framebuffer, IndexedColor};
use crate::helpers::*;
use crate::oklab::StraightRgba;
use crate::simd::memchr2;
use crate::unicode::{self, Cursor, MeasurementConfig};
use crate::{icu, simd};

/// The margin template is used for line numbers.
/// The max. line number we should ever expect is probably 64-bit,
/// and so this template fits 19 digits, followed by " │ ".
const MARGIN_TEMPLATE: &str = "                    │ ";
/// Just a bunch of whitespace you can use for turning tabs into spaces.
/// Happens to reuse MARGIN_TEMPLATE, because it has sufficient whitespace.
const TAB_WHITESPACE: &str = MARGIN_TEMPLATE;
const VISUAL_SPACE: &str = "・";
const VISUAL_SPACE_PREFIX_ADD: usize = '・'.len_utf8() - 1;
const VISUAL_TAB: &str = "→       ";
const VISUAL_TAB_PREFIX_ADD: usize = '→'.len_utf8() - 1;

pub enum IoError {
    Io(io::Error),
    Icu(icu::Error),
}

pub type IoResult<T> = std::result::Result<T, IoError>;

impl From<io::Error> for IoError {
    fn from(err: io::Error) -> Self {
        Self::Io(err)
    }
}

impl From<icu::Error> for IoError {
    fn from(err: icu::Error) -> Self {
        Self::Icu(err)
    }
}

/// Stores statistics about the whole document.
#[derive(Copy, Clone)]
pub struct TextBufferStatistics {
    logical_lines: CoordType,
    visual_lines: CoordType,
}

/// Stores the active text selection anchors.
///
/// The two points are not sorted. Instead, `beg` refers to where the selection
/// started being made and `end` refers to the currently being updated position.
#[derive(Copy, Clone)]
struct TextBufferSelection {
    beg: Point,
    end: Point,
}

/// In order to group actions into a single undo step,
/// we need to know the type of action that was performed.
/// This stores the action type.
#[derive(Copy, Clone, Eq, PartialEq)]
enum HistoryType {
    Other,
    Write,
    Delete,
}

/// An undo/redo entry.
struct HistoryEntry {
    /// [`TextBuffer::cursor`] position before the change was made.
    cursor_before: Point,
    /// [`TextBuffer::selection`] before the change was made.
    selection_before: Option<TextBufferSelection>,
    /// [`TextBuffer::stats`] before the change was made.
    stats_before: TextBufferStatistics,
    /// [`GapBuffer::generation`] before the change was made.
    ///
    /// **NOTE:** Entries with the same generation are grouped together.
    generation_before: u32,
    /// Logical cursor position where the change took place.
    /// The position is at the start of the changed range.
    cursor: Point,
    /// Text that was deleted from the buffer.
    deleted: Vec<u8>,
    /// Text that was added to the buffer.
    added: Vec<u8>,
}

/// Caches an ICU search operation.
struct ActiveSearch {
    /// The search pattern.
    pattern: String,
    /// The search options.
    options: SearchOptions,
    /// The ICU `UText` object.
    text: icu::Text,
    /// The ICU `URegularExpression` object.
    regex: icu::Regex,
    /// [`GapBuffer::generation`] when the search was created.
    /// This is used to detect if we need to refresh the
    /// [`ActiveSearch::regex`] object.
    buffer_generation: u32,
    /// [`TextBuffer::selection_generation`] when the search was
    /// created. When the user manually selects text, we need to
    /// refresh the [`ActiveSearch::pattern`] with it.
    selection_generation: u32,
    /// Stores the text buffer offset in between searches.
    next_search_offset: usize,
    /// If we know there were no hits, we can skip searching.
    no_matches: bool,
}

/// Options for a search operation.
#[derive(Default, Clone, Copy, Eq, PartialEq)]
pub struct SearchOptions {
    /// If true, the search is case-sensitive.
    pub match_case: bool,
    /// If true, the search matches whole words.
    pub whole_word: bool,
    /// If true, the search uses regex.
    pub use_regex: bool,
}

enum RegexReplacement<'a> {
    Group(i32),
    Text(BVec<'a, u8>),
}

/// Caches the start and length of the active edit line for a single edit.
/// This helps us avoid having to remeasure the buffer after an edit.
struct ActiveEditLineInfo {
    /// Points to the start of the currently being edited line.
    safe_start: Cursor,
    /// Number of visual rows of the line that starts
    /// at [`ActiveEditLineInfo::safe_start`].
    line_height_in_rows: CoordType,
    /// Byte distance from the start of the line at
    /// [`ActiveEditLineInfo::safe_start`] to the next line.
    distance_next_line_start: usize,
}

/// Undo/redo grouping works by recording a set of "overrides",
/// which are then applied in [`TextBuffer::edit_begin()`].
/// This allows us to create a group of edits that all share a
/// common `generation_before` and can be undone/redone together.
/// This struct stores those overrides.
struct ActiveEditGroupInfo {
    /// [`TextBuffer::cursor`] position before the change was made.
    cursor_before: Point,
    /// [`TextBuffer::selection`] before the change was made.
    selection_before: Option<TextBufferSelection>,
    /// [`TextBuffer::stats`] before the change was made.
    stats_before: TextBufferStatistics,
    /// [`GapBuffer::generation`] before the change was made.
    ///
    /// **NOTE:** Entries with the same generation are grouped together.
    generation_before: u32,
}

/// Char- or word-wise navigation? Your choice.
pub enum CursorMovement {
    Grapheme,
    Word,
}

/// See [`TextBuffer::move_selected_lines`].
pub enum MoveLineDirection {
    Up,
    Down,
}

/// The result of a call to [`TextBuffer::render()`].
pub struct RenderResult {
    /// The maximum visual X position we encountered during rendering.
    pub visual_pos_x_max: CoordType,
}

/// A [`TextBuffer`] with inner mutability.
pub type TextBufferCell = SemiRefCell<TextBuffer>;

/// A [`TextBuffer`] inside an [`Rc`].
///
/// We need this because the TUI system needs to borrow
/// the given text buffer(s) until after the layout process.
pub type RcTextBuffer = Rc<TextBufferCell>;

/// A text buffer for a text editor.
pub struct TextBuffer {
    buffer: GapBuffer,

    undo_stack: VecDeque<SemiRefCell<HistoryEntry>>,
    redo_stack: VecDeque<SemiRefCell<HistoryEntry>>,
    last_history_type: HistoryType,
    last_save_generation: u32,

    active_edit_group: Option<ActiveEditGroupInfo>,
    active_edit_line_info: Option<ActiveEditLineInfo>,
    active_edit_depth: i32,
    active_edit_off: usize,

    stats: TextBufferStatistics,
    cursor: Cursor,
    // When scrolling significant amounts of text away from the cursor,
    // rendering will naturally slow down proportionally to the distance.
    // To avoid this, we cache the cursor position for rendering.
    // Must be cleared on every edit or reflow.
    cursor_for_rendering: Option<Cursor>,
    selection: Option<TextBufferSelection>,
    selection_generation: u32,
    search: Option<UnsafeCell<ActiveSearch>>,

    width: CoordType,
    margin_width: CoordType,
    margin_enabled: bool,
    word_wrap_column: CoordType,
    word_wrap_enabled: bool,
    tab_size: CoordType,
    indent_with_tabs: bool,
    line_highlight_enabled: bool,
    ruler: CoordType,
    encoding: &'static str,
    newlines_are_crlf: bool,
    insert_final_newline: bool,
    overtype: bool,

    wants_cursor_visibility: bool,
}

impl TextBuffer {
    /// Creates a new text buffer inside an [`Rc`].
    /// See [`TextBuffer::new()`].
    pub fn new_rc(small: bool) -> io::Result<RcTextBuffer> {
        let buffer = Self::new(small)?;
        Ok(Rc::new(SemiRefCell::new(buffer)))
    }

    /// Creates a new text buffer. With `small` you can control
    /// if the buffer is optimized for <1MiB contents.
    pub fn new(small: bool) -> io::Result<Self> {
        Ok(Self {
            buffer: GapBuffer::new(small)?,

            undo_stack: Default::default(),
            redo_stack: Default::default(),
            last_history_type: HistoryType::Other,
            last_save_generation: 0,

            active_edit_group: None,
            active_edit_line_info: None,
            active_edit_depth: 0,
            active_edit_off: 0,

            stats: TextBufferStatistics { logical_lines: 1, visual_lines: 1 },
            cursor: Default::default(),
            cursor_for_rendering: None,
            selection: None,
            selection_generation: 0,
            search: None,

            width: 0,
            margin_width: 0,
            margin_enabled: false,
            word_wrap_column: 0,
            word_wrap_enabled: false,
            tab_size: 4,
            indent_with_tabs: false,
            line_highlight_enabled: false,
            ruler: 0,
            encoding: "UTF-8",
            newlines_are_crlf: cfg!(windows), // Windows users want CRLF
            insert_final_newline: false,
            overtype: false,

            wants_cursor_visibility: false,
        })
    }

    /// Length of the document in bytes.
    pub fn text_length(&self) -> usize {
        self.buffer.len()
    }

    /// Number of logical lines in the document,
    /// that is, lines separated by newlines.
    pub fn logical_line_count(&self) -> CoordType {
        self.stats.logical_lines
    }

    /// Number of visual lines in the document,
    /// that is, the number of lines after layout.
    pub fn visual_line_count(&self) -> CoordType {
        self.stats.visual_lines
    }

    /// Does the buffer need to be saved?
    pub fn is_dirty(&self) -> bool {
        self.last_save_generation != self.buffer.generation()
    }

    /// The buffer generation changes on every edit.
    /// With this you can check if it has changed since
    /// the last time you called this function.
    pub fn generation(&self) -> u32 {
        self.buffer.generation()
    }

    /// Force the buffer to be dirty.
    pub fn mark_as_dirty(&mut self) {
        self.last_save_generation = self.buffer.generation().wrapping_sub(1);
    }

    fn mark_as_clean(&mut self) {
        self.last_save_generation = self.buffer.generation();
    }

    /// The encoding used during reading/writing. "UTF-8" is the default.
    pub fn encoding(&self) -> &'static str {
        self.encoding
    }

    /// Set the encoding used during reading/writing.
    pub fn set_encoding(&mut self, encoding: &'static str) {
        if self.encoding != encoding {
            self.encoding = encoding;
            self.mark_as_dirty();
        }
    }

    /// The newline type used in the document. LF or CRLF.
    pub fn is_crlf(&self) -> bool {
        self.newlines_are_crlf
    }

    /// Changes the newline type without normalizing the document.
    pub fn set_crlf(&mut self, crlf: bool) {
        self.newlines_are_crlf = crlf;
    }

    /// Changes the newline type used in the document.
    ///
    /// NOTE: Cannot be undone.
    pub fn normalize_newlines(&mut self, crlf: bool) {
        let newline: &[u8] = if crlf { b"\r\n" } else { b"\n" };
        let mut off = 0;

        let mut cursor_offset = self.cursor.offset;
        let mut cursor_for_rendering_offset =
            self.cursor_for_rendering.map_or(cursor_offset, |c| c.offset);

        #[cfg(debug_assertions)]
        let mut adjusted_newlines = 0;

        'outer: loop {
            // Seek to the offset of the next line start.
            loop {
                let chunk = self.read_forward(off);
                if chunk.is_empty() {
                    break 'outer;
                }

                let (delta, line) = simd::lines_fwd(chunk, 0, 0, 1);
                off += delta;
                if line == 1 {
                    break;
                }
            }

            // Get the preceding newline.
            let chunk = self.read_backward(off);
            let chunk_newline_len = if chunk.ends_with(b"\r\n") { 2 } else { 1 };
            let chunk_newline = &chunk[chunk.len() - chunk_newline_len..];

            if chunk_newline != newline {
                // If this newline is still before our cursor position, then it still has an effect on its offset.
                // Any newline adjustments past that cursor position are irrelevant.
                let delta = newline.len() as isize - chunk_newline_len as isize;
                if off <= cursor_offset {
                    cursor_offset = cursor_offset.saturating_add_signed(delta);
                    #[cfg(debug_assertions)]
                    {
                        adjusted_newlines += 1;
                    }
                }
                if off <= cursor_for_rendering_offset {
                    cursor_for_rendering_offset =
                        cursor_for_rendering_offset.saturating_add_signed(delta);
                }

                // Replace the newline.
                off -= chunk_newline_len;
                self.buffer.replace(off..off + chunk_newline_len, newline);
                off += newline.len();
            }
        }

        // If this fails, the cursor offset calculation above is wrong.
        #[cfg(debug_assertions)]
        debug_assert_eq!(adjusted_newlines, self.cursor.logical_pos.y);

        self.cursor.offset = cursor_offset;
        if let Some(cursor) = &mut self.cursor_for_rendering {
            cursor.offset = cursor_for_rendering_offset;
        }

        self.newlines_are_crlf = crlf;
    }

    /// If enabled, automatically insert a final newline
    /// when typing at the end of the file.
    pub fn set_insert_final_newline(&mut self, enabled: bool) {
        self.insert_final_newline = enabled;
    }

    /// Whether to insert or overtype text when writing.
    pub fn is_overtype(&self) -> bool {
        self.overtype
    }

    /// Set the overtype mode.
    pub fn set_overtype(&mut self, overtype: bool) {
        self.overtype = overtype;
    }

    /// Gets the logical cursor position, that is,
    /// the position in lines and graphemes per line.
    pub fn cursor_logical_pos(&self) -> Point {
        self.cursor.logical_pos
    }

    /// Gets the visual cursor position, that is,
    /// the position in laid out rows and columns.
    pub fn cursor_visual_pos(&self) -> Point {
        self.cursor.visual_pos
    }

    /// Gets the width of the left margin.
    pub fn margin_width(&self) -> CoordType {
        self.margin_width
    }

    /// Is the left margin enabled?
    pub fn set_margin_enabled(&mut self, enabled: bool) -> bool {
        if self.margin_enabled == enabled {
            false
        } else {
            self.margin_enabled = enabled;
            self.reflow();
            true
        }
    }

    /// Gets the width of the text contents for layout.
    pub fn text_width(&self) -> CoordType {
        self.width - self.margin_width
    }

    /// Ask the TUI system to scroll the buffer and make the cursor visible.
    ///
    /// TODO: This function shows that [`TextBuffer`] is poorly abstracted
    /// away from the TUI system. The only reason this exists is so that
    /// if someone outside the TUI code enables word-wrap, the TUI code
    /// recognizes this and scrolls the cursor into view. But outside of this
    /// scrolling, views, etc., are all UI concerns = this should not be here.
    pub fn make_cursor_visible(&mut self) {
        self.wants_cursor_visibility = true;
    }

    /// For the TUI code to retrieve a prior [`TextBuffer::make_cursor_visible()`] request.
    pub fn take_cursor_visibility_request(&mut self) -> bool {
        mem::take(&mut self.wants_cursor_visibility)
    }

    /// Is word-wrap enabled?
    ///
    /// Technically, this is a misnomer, because it's line-wrapping.
    pub fn is_word_wrap_enabled(&self) -> bool {
        self.word_wrap_enabled
    }

    /// Enable or disable word-wrap.
    ///
    /// NOTE: It's expected that the tui code calls `set_width()` sometime after this.
    /// This will then trigger the actual recalculation of the cursor position.
    pub fn set_word_wrap(&mut self, enabled: bool) {
        if self.word_wrap_enabled != enabled {
            self.word_wrap_enabled = enabled;
            self.width = 0; // Force a reflow.
            self.make_cursor_visible();
        }
    }

    /// Set the width available for layout.
    ///
    /// Ideally this would be a pure UI concern, but the text buffer needs this
    /// so that it can abstract away  visual cursor movement such as "go a line up".
    /// What would that even mean if it didn't know how wide a line is?
    pub fn set_width(&mut self, width: CoordType) -> bool {
        if width <= 0 || width == self.width {
            false
        } else {
            self.width = width;
            self.reflow();
            true
        }
    }

    /// Set the tab width. Could be anything, but is expected to be 1-8.
    pub fn tab_size(&self) -> CoordType {
        self.tab_size
    }

    /// Set the tab size. Clamped to 1-8.
    pub fn set_tab_size(&mut self, width: CoordType) -> bool {
        let width = width.clamp(1, 8);
        if width == self.tab_size {
            false
        } else {
            self.tab_size = width;
            self.reflow();
            true
        }
    }

    /// Calculates the amount of spaces a tab key press would insert at the given column.
    /// This also equals the visual width of an actual tab character.
    ///
    /// This exists because Rust doesn't have range constraints yet, and without
    /// them assembly blows up in size by 7x. It's a recurring issue with Rust.
    #[inline]
    fn tab_size_eval(&self, column: CoordType) -> CoordType {
        // SAFETY: `set_tab_size` clamps `self.tab_size` to 1-8.
        unsafe { std::hint::assert_unchecked(self.tab_size >= 1 && self.tab_size <= 8) };
        self.tab_size - (column % self.tab_size)
    }

    /// If the cursor is at an indentation of `column`, this returns
    /// the column to which a backspace key press would delete to.
    #[inline]
    fn tab_size_prev_column(&self, column: CoordType) -> CoordType {
        // SAFETY: `set_tab_size` clamps `self.tab_size` to 1-8.
        unsafe { std::hint::assert_unchecked(self.tab_size >= 1 && self.tab_size <= 8) };
        (column - 1).max(0) / self.tab_size * self.tab_size
    }

    /// Returns whether tabs are used for indentation.
    pub fn indent_with_tabs(&self) -> bool {
        self.indent_with_tabs
    }

    /// Sets whether tabs or spaces are used for indentation.
    pub fn set_indent_with_tabs(&mut self, indent_with_tabs: bool) {
        self.indent_with_tabs = indent_with_tabs;
    }

    /// Sets whether the line the cursor is on should be highlighted.
    pub fn set_line_highlight_enabled(&mut self, enabled: bool) {
        self.line_highlight_enabled = enabled;
    }

    /// Sets a ruler column, e.g. 80.
    pub fn set_ruler(&mut self, column: CoordType) {
        self.ruler = column;
    }

    pub fn reflow(&mut self) {
        self.reflow_internal(true);
    }

    fn recalc_after_content_changed(&mut self) {
        self.reflow_internal(false);
    }

    fn reflow_internal(&mut self, force: bool) {
        let word_wrap_column_before = self.word_wrap_column;

        {
            // +1 onto logical_lines, because line numbers are 1-based.
            // +1 onto log10, because we want the digit width and not the actual log10.
            // +3 onto log10, because we append " | " to the line numbers to form the margin.
            self.margin_width = if self.margin_enabled {
                self.stats.logical_lines.ilog10() as CoordType + 4
            } else {
                0
            };

            let text_width = self.text_width();
            // 2 columns are required, because otherwise wide glyphs wouldn't ever fit.
            self.word_wrap_column =
                if self.word_wrap_enabled && text_width >= 2 { text_width } else { 0 };
        }

        self.cursor_for_rendering = None;

        if force || self.word_wrap_column != word_wrap_column_before {
            // Recalculate the cursor position.
            self.cursor = self.cursor_move_to_logical_internal(
                if self.word_wrap_column > 0 {
                    Default::default()
                } else {
                    self.goto_line_start(self.cursor, self.cursor.logical_pos.y)
                },
                self.cursor.logical_pos,
            );

            // Recalculate the line statistics.
            if self.word_wrap_column > 0 {
                let end = self.cursor_move_to_logical_internal(self.cursor, Point::MAX);
                self.stats.visual_lines = end.visual_pos.y + 1;
            } else {
                self.stats.visual_lines = self.stats.logical_lines;
            }
        }
    }

    /// Replaces the entire buffer contents with the given `text`.
    /// Assumes that the line count doesn't change.
    pub fn copy_from_str(&mut self, text: &dyn ReadableDocument) {
        if self.buffer.copy_from(text) {
            self.recalc_after_content_swap();
            self.cursor_move_to_logical(Point { x: CoordType::MAX, y: 0 });

            let delete = self.buffer.len() - self.cursor.offset;
            if delete != 0 {
                self.buffer.allocate_gap(self.cursor.offset, 0, delete);
            }
        }
    }

    fn recalc_after_content_swap(&mut self) {
        // If the buffer was changed, nothing we previously saved can be relied upon.
        self.undo_stack.clear();
        self.redo_stack.clear();
        self.last_history_type = HistoryType::Other;
        self.cursor = Default::default();
        self.set_selection(None);
        self.mark_as_clean();
        self.reflow();
    }

    /// Copies the contents of the buffer into a string.
    pub fn save_as_string(&mut self, dst: &mut dyn WriteableDocument) {
        self.buffer.copy_into(dst);
        self.mark_as_clean();
    }

    /// Reads a file from disk into the text buffer, detecting encoding and BOM.
    pub fn read_file(&mut self, file: &mut File, encoding: Option<&'static str>) -> IoResult<()> {
        let scratch = scratch_arena(None);
        let buf = scratch.alloc_uninit_array();
        let mut first_chunk_len = 0;
        let mut read = 0;

        // Read enough bytes to detect the BOM.
        while first_chunk_len < BOM_MAX_LEN {
            read = file_read_uninit(file, &mut buf[first_chunk_len..])?;
            if read == 0 {
                break;
            }
            first_chunk_len += read;
        }

        if let Some(encoding) = encoding {
            self.encoding = encoding;
        } else {
            let bom = detect_bom(unsafe { buf[..first_chunk_len].assume_init_ref() });
            self.encoding = bom.unwrap_or("UTF-8");
        }

        // TODO: Since reading the file can fail, we should ensure that we also reset the cursor here.
        // I don't do it, so that `recalc_after_content_swap()` works.
        self.buffer.clear();

        let done = read == 0;
        if self.encoding == "UTF-8" {
            self.read_file_as_utf8(file, buf, first_chunk_len, done)?;
        } else {
            self.read_file_with_icu(file, buf, first_chunk_len, done)?;
        }

        // Figure out
        // * the logical line count
        // * the newline type (LF or CRLF)
        // * the indentation type (tabs or spaces)
        // * whether there's a final newline
        {
            let chunk = self.read_forward(0);
            let mut offset = 0;
            let mut lines = 0;
            // Number of lines ending in CRLF.
            let mut crlf_count = 0;
            // Number of lines starting with a tab.
            let mut tab_indentations = 0;
            // Number of lines starting with a space.
            let mut space_indentations = 0;
            // Histogram of the indentation depth of lines starting with between 2 and 8 spaces.
            // In other words, `space_indentation_sizes[0]` is the number of lines starting with 2 spaces.
            let mut space_indentation_sizes = [0; 7];

            loop {
                // Check if the line starts with a tab.
                if offset < chunk.len() && chunk[offset] == b'\t' {
                    tab_indentations += 1;
                } else {
                    // Otherwise, check how many spaces the line starts with. Searching for >8 spaces
                    // allows us to reject lines that have more than 1 level of indentation.
                    let space_indentation =
                        chunk[offset..].iter().take(9).take_while(|&&c| c == b' ').count();

                    // We'll also reject lines starting with 1 space, because that's too fickle as a heuristic.
                    if (2..=8).contains(&space_indentation) {
                        space_indentations += 1;

                        // If we encounter an indentation depth of 6, it may either be a 6-space indentation,
                        // two 3-space indentation or 3 2-space indentations. To make this work, we increment
                        // all 3 possible histogram slots.
                        //   2 -> 2
                        //   3 -> 3
                        //   4 -> 4 2
                        //   5 -> 5
                        //   6 -> 6 3 2
                        //   7 -> 7
                        //   8 -> 8 4 2
                        space_indentation_sizes[space_indentation - 2] += 1;
                        if space_indentation & 4 != 0 {
                            space_indentation_sizes[0] += 1;
                        }
                        if space_indentation == 6 || space_indentation == 8 {
                            space_indentation_sizes[space_indentation / 2 - 2] += 1;
                        }
                    }
                }

                (offset, line
Download .txt
gitextract_909sqtf7/

├── .cargo/
│   ├── release-nightly.toml
│   ├── release-windows-ms.toml
│   └── release.toml
├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   └── workflows/
│       ├── ci.yml
│       └── winget.yml
├── .gitignore
├── .pipelines/
│   ├── release.yml
│   └── tsa.json
├── .vscode/
│   ├── launch.json
│   └── tasks.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── README.md
├── SECURITY.md
├── assets/
│   ├── com.microsoft.edit.desktop
│   ├── editing-traces/
│   │   ├── README.md
│   │   └── rustcode.json.zst
│   ├── highlighting-tests/
│   │   └── json.json
│   ├── manpage/
│   │   └── edit.1
│   ├── microsoft.sixel
│   └── snapcraft.yaml
├── crates/
│   ├── edit/
│   │   ├── Cargo.toml
│   │   ├── benches/
│   │   │   └── lib.rs
│   │   ├── build/
│   │   │   ├── helpers.rs
│   │   │   ├── i18n.rs
│   │   │   └── main.rs
│   │   └── src/
│   │       ├── base64.rs
│   │       ├── bin/
│   │       │   └── edit/
│   │       │       ├── apperr.rs
│   │       │       ├── documents.rs
│   │       │       ├── draw_editor.rs
│   │       │       ├── draw_filepicker.rs
│   │       │       ├── draw_menubar.rs
│   │       │       ├── draw_statusbar.rs
│   │       │       ├── edit.exe.manifest
│   │       │       ├── localization.rs
│   │       │       ├── main.rs
│   │       │       └── state.rs
│   │       ├── buffer/
│   │       │   ├── gap_buffer.rs
│   │       │   ├── line_cache.rs
│   │       │   ├── mod.rs
│   │       │   └── navigation.rs
│   │       ├── cell.rs
│   │       ├── clipboard.rs
│   │       ├── document.rs
│   │       ├── framebuffer.rs
│   │       ├── fuzzy.rs
│   │       ├── glob.rs
│   │       ├── hash.rs
│   │       ├── helpers.rs
│   │       ├── icu.rs
│   │       ├── input.rs
│   │       ├── json.rs
│   │       ├── lib.rs
│   │       ├── oklab.rs
│   │       ├── path.rs
│   │       ├── simd/
│   │       │   ├── lines_bwd.rs
│   │       │   ├── lines_fwd.rs
│   │       │   ├── memchr2.rs
│   │       │   └── mod.rs
│   │       ├── sys/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       ├── tui.rs
│   │       ├── unicode/
│   │       │   ├── measurement.rs
│   │       │   ├── mod.rs
│   │       │   └── tables.rs
│   │       └── vt.rs
│   ├── stdext/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── alloc.rs
│   │       ├── arena/
│   │       │   ├── debug.rs
│   │       │   ├── fs.rs
│   │       │   ├── mod.rs
│   │       │   ├── release.rs
│   │       │   └── scratch.rs
│   │       ├── collections/
│   │       │   ├── mod.rs
│   │       │   ├── string.rs
│   │       │   └── vec.rs
│   │       ├── helpers.rs
│   │       ├── lib.rs
│   │       ├── simd/
│   │       │   ├── memset.rs
│   │       │   └── mod.rs
│   │       ├── sys/
│   │       │   ├── mod.rs
│   │       │   ├── unix.rs
│   │       │   └── windows.rs
│   │       └── unicode/
│   │           ├── mod.rs
│   │           └── utf8.rs
│   └── unicode-gen/
│       ├── Cargo.toml
│       ├── README.md
│       └── src/
│           ├── main.rs
│           └── rules.rs
├── i18n/
│   └── edit.toml
├── rust-toolchain.toml
└── rustfmt.toml
Download .txt
SYMBOL INDEX (1363 symbols across 55 files)

FILE: crates/edit/benches/lib.rs
  type EditingTracePatch (line 15) | struct EditingTracePatch<'a>(usize, usize, &'a str);
  type EditingTraceTransaction (line 17) | struct EditingTraceTransaction<'a> {
  type EditingTraceData (line 21) | struct EditingTraceData<'a> {
  function bench_buffer (line 27) | fn bench_buffer(c: &mut Criterion) {
  function bench_glob (line 138) | fn bench_glob(c: &mut Criterion) {
  function bench_hash (line 147) | fn bench_hash(c: &mut Criterion) {
  function bench_json (line 166) | fn bench_json(c: &mut Criterion) {
  function bench_oklab (line 181) | fn bench_oklab(c: &mut Criterion) {
  function bench_simd_lines_fwd (line 194) | fn bench_simd_lines_fwd(c: &mut Criterion) {
  function bench_simd_memchr2 (line 209) | fn bench_simd_memchr2(c: &mut Criterion) {
  function bench_simd_memset (line 229) | fn bench_simd_memset<T: Copy + Default>(c: &mut Criterion) {
  function bench_unicode (line 250) | fn bench_unicode(c: &mut Criterion) {
  function bench (line 280) | fn bench(c: &mut Criterion) {

FILE: crates/edit/build/helpers.rs
  function env_opt (line 6) | pub fn env_opt(name: &str) -> String {

FILE: crates/edit/build/i18n.rs
  function generate (line 9) | pub fn generate(definitions: &str) -> String {

FILE: crates/edit/build/main.rs
  type TargetOs (line 12) | enum TargetOs {
  function main (line 18) | fn main() {
  function compile_i18n (line 33) | fn compile_i18n() {
  function configure_icu (line 46) | fn configure_icu(target_os: TargetOs) {
  function configure_windows_binary (line 111) | fn configure_windows_binary(target_os: TargetOs) {

FILE: crates/edit/src/base64.rs
  constant CHARSET (line 9) | const CHARSET: [u8; 64] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopq...
  function encode_len (line 14) | pub fn encode_len(src_len: usize) -> usize {
  function encode (line 19) | pub fn encode<'a>(arena: &'a Arena, dst: &mut BString<'a>, src: &[u8]) {
  function test_basic (line 89) | fn test_basic() {

FILE: crates/edit/src/bin/edit/apperr.rs
  type Error (line 9) | pub enum Error {
    method from (line 17) | fn from(err: io::Error) -> Self {
    method from (line 23) | fn from(err: icu::Error) -> Self {
    method from (line 29) | fn from(err: buffer::IoError) -> Self {
  type Result (line 14) | pub type Result<T> = std::result::Result<T, Error>;

FILE: crates/edit/src/bin/edit/documents.rs
  type Document (line 16) | pub struct Document {
    method save (line 26) | pub fn save(&mut self, new_path: Option<PathBuf>) -> apperr::Result<()> {
    method reread (line 46) | pub fn reread(&mut self, encoding: Option<&'static str>) -> apperr::Re...
    method set_path (line 62) | fn set_path(&mut self, path: PathBuf) {
    method update_file_mode (line 71) | fn update_file_mode(&mut self) {
  type DocumentManager (line 78) | pub struct DocumentManager {
    method len (line 84) | pub fn len(&self) -> usize {
    method active (line 89) | pub fn active(&self) -> Option<&Document> {
    method active_mut (line 94) | pub fn active_mut(&mut self) -> Option<&mut Document> {
    method update_active (line 98) | pub fn update_active<F: FnMut(&Document) -> bool>(&mut self, mut func:...
    method remove_active (line 130) | pub fn remove_active(&mut self) {
    method add_untitled (line 134) | pub fn add_untitled(&mut self) -> apperr::Result<&mut Document> {
    method gen_untitled_name (line 151) | pub fn gen_untitled_name(&self, doc: &mut Document) {
    method add_file_path (line 162) | pub fn add_file_path(&mut self, path: &Path) -> apperr::Result<&mut Do...
    method reflow_all (line 221) | pub fn reflow_all(&self) {
    method open_for_reading (line 228) | pub fn open_for_reading(path: &Path) -> apperr::Result<File> {
    method open_for_writing (line 232) | pub fn open_for_writing(path: &Path) -> apperr::Result<File> {
    method create_buffer (line 246) | fn create_buffer() -> apperr::Result<RcTextBuffer> {
    method parse_filename_goto (line 259) | fn parse_filename_goto(path: &Path) -> (&Path, Option<Point>) {
  function test_parse_last_numbers (line 320) | fn test_parse_last_numbers() {

FILE: crates/edit/src/bin/edit/draw_editor.rs
  function draw_editor (line 16) | pub fn draw_editor(ctx: &mut Context, state: &mut State) {
  function draw_search (line 40) | fn draw_search(ctx: &mut Context, state: &mut State) {
  type SearchAction (line 167) | pub enum SearchAction {
  function search_execute (line 173) | pub fn search_execute(ctx: &mut Context, state: &mut State, action: Sear...
  function draw_handle_save (line 198) | pub fn draw_handle_save(ctx: &mut Context, state: &mut State) {
  function draw_handle_wants_close (line 215) | pub fn draw_handle_wants_close(ctx: &mut Context, state: &mut State) {
  function draw_goto_menu (line 306) | pub fn draw_goto_menu(ctx: &mut Context, state: &mut State) {
  function validate_goto_point (line 349) | fn validate_goto_point(line: &str) -> Result<Point, ParseIntError> {

FILE: crates/edit/src/bin/edit/draw_filepicker.rs
  function draw_file_picker (line 19) | pub fn draw_file_picker(ctx: &mut Context, state: &mut State) {
  function draw_file_picker_update_path (line 270) | fn draw_file_picker_update_path(state: &mut State) -> Option<PathBuf> {
  function draw_dialog_saveas_refresh_files (line 305) | fn draw_dialog_saveas_refresh_files(state: &mut State) {
  function update_autocomplete_suggestions (line 356) | fn update_autocomplete_suggestions(state: &mut State) {

FILE: crates/edit/src/bin/edit/draw_menubar.rs
  function draw_menubar (line 12) | pub fn draw_menubar(ctx: &mut Context, state: &mut State) {
  function draw_menu_file (line 40) | fn draw_menu_file(ctx: &mut Context, state: &mut State) {
  function draw_menu_edit (line 64) | fn draw_menu_edit(ctx: &mut Context, state: &mut State) {
  function draw_menu_view (line 105) | fn draw_menu_view(ctx: &mut Context, state: &mut State) {
  function draw_menu_help (line 129) | fn draw_menu_help(ctx: &mut Context, state: &mut State) {
  function draw_dialog_about (line 136) | pub fn draw_dialog_about(ctx: &mut Context, state: &mut State) {

FILE: crates/edit/src/bin/edit/draw_statusbar.rs
  function draw_statusbar (line 17) | pub fn draw_statusbar(ctx: &mut Context, state: &mut State) {
  function draw_dialog_encoding_change (line 204) | pub fn draw_dialog_encoding_change(ctx: &mut Context, state: &mut State) {
  function encoding_picker_update_list (line 285) | fn encoding_picker_update_list(state: &mut State) {
  function draw_go_to_file (line 310) | pub fn draw_go_to_file(ctx: &mut Context, state: &mut State) {

FILE: crates/edit/src/bin/edit/localization.rs
  function init (line 12) | pub fn init() {
  function loc (line 31) | pub fn loc(id: LocId) -> &'static str {

FILE: crates/edit/src/bin/edit/main.rs
  constant SCRATCH_ARENA_CAPACITY (line 36) | const SCRATCH_ARENA_CAPACITY: usize = 128 * MEBI;
  constant SCRATCH_ARENA_CAPACITY (line 38) | const SCRATCH_ARENA_CAPACITY: usize = 512 * MEBI;
  function main (line 43) | fn main() -> process::ExitCode {
  function run (line 62) | fn run() -> apperr::Result<()> {
  function handle_args (line 230) | fn handle_args(state: &mut State) -> apperr::Result<bool> {
  function print_help (line 292) | fn print_help() {
  function print_version (line 304) | fn print_version() {
  function draw (line 308) | fn draw(ctx: &mut Context, state: &mut State) {
  function draw_handle_wants_exit (line 383) | fn draw_handle_wants_exit(_ctx: &mut Context, state: &mut State) {
  function write_terminal_title (line 397) | fn write_terminal_title<'a>(arena: &'a Arena, output: &mut BString<'a>, ...
  constant LARGE_CLIPBOARD_THRESHOLD (line 423) | const LARGE_CLIPBOARD_THRESHOLD: usize = 128 * KIBI;
  function draw_handle_clipboard_change (line 425) | fn draw_handle_clipboard_change(ctx: &mut Context, state: &mut State) {
  function write_osc_clipboard (line 517) | fn write_osc_clipboard<'a>(
  type RestoreModes (line 540) | struct RestoreModes;
  method drop (line 543) | fn drop(&mut self) {
  function setup_terminal (line 551) | fn setup_terminal(tui: &mut Tui, state: &mut State, vt_parser: &mut vt::...
  function sanitize_control_chars (line 675) | fn sanitize_control_chars(text: &str) -> Cow<'_, str> {

FILE: crates/edit/src/bin/edit/state.rs
  type FormatApperr (line 20) | pub struct FormatApperr(apperr::Error);
    method from (line 23) | fn from(err: apperr::Error) -> Self {
    method fmt (line 29) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type DisplayablePathBuf (line 38) | pub struct DisplayablePathBuf {
    method from_string (line 45) | pub fn from_string(string: String) -> Self {
    method from_path (line 52) | pub fn from_path(value: PathBuf) -> Self {
    method as_path (line 58) | pub fn as_path(&self) -> &Path {
    method as_str (line 62) | pub fn as_str(&self) -> &str {
    method as_bytes (line 66) | pub fn as_bytes(&self) -> &[u8] {
    method from (line 84) | fn from(s: OsString) -> Self {
    method from (line 90) | fn from(s: &T) -> Self {
  method default (line 72) | fn default() -> Self {
  method clone (line 78) | fn clone(&self) -> Self {
  type StateSearch (line 95) | pub struct StateSearch {
  type StateSearchKind (line 101) | pub enum StateSearchKind {
  type StateFilePicker (line 109) | pub enum StateFilePicker {
  type StateEncodingChange (line 118) | pub enum StateEncodingChange {
  type OscTitleFileStatus (line 125) | pub struct OscTitleFileStatus {
  type State (line 130) | pub struct State {
    method new (line 178) | pub fn new() -> apperr::Result<Self> {
  function draw_add_untitled_document (line 227) | pub fn draw_add_untitled_document(ctx: &mut Context, state: &mut State) {
  function error_log_add (line 233) | pub fn error_log_add(ctx: &mut Context, state: &mut State, err: apperr::...
  function draw_error_log (line 243) | pub fn draw_error_log(ctx: &mut Context, state: &mut State) {

FILE: crates/edit/src/buffer/gap_buffer.rs
  constant LARGE_CAPACITY (line 15) | const LARGE_CAPACITY: usize = 128 * MEBI;
  constant LARGE_CAPACITY (line 17) | const LARGE_CAPACITY: usize = 4 * GIBI;
  constant LARGE_ALLOC_CHUNK (line 18) | const LARGE_ALLOC_CHUNK: usize = 64 * KIBI;
  constant LARGE_GAP_CHUNK (line 19) | const LARGE_GAP_CHUNK: usize = 4 * KIBI;
  constant SMALL_CAPACITY (line 21) | const SMALL_CAPACITY: usize = 128 * KIBI;
  constant SMALL_ALLOC_CHUNK (line 22) | const SMALL_ALLOC_CHUNK: usize = 256;
  constant SMALL_GAP_CHUNK (line 23) | const SMALL_GAP_CHUNK: usize = 16;
  type BackingBuffer (line 27) | enum BackingBuffer {
  method drop (line 33) | fn drop(&mut self) {
  type GapBuffer (line 46) | pub struct GapBuffer {
    method new (line 67) | pub fn new(small: bool) -> io::Result<Self> {
    method len (line 95) | pub fn len(&self) -> usize {
    method generation (line 99) | pub fn generation(&self) -> u32 {
    method set_generation (line 103) | pub fn set_generation(&mut self, generation: u32) {
    method allocate_gap (line 108) | pub fn allocate_gap(&mut self, off: usize, len: usize, delete: usize) ...
    method move_gap (line 132) | fn move_gap(&mut self, off: usize) {
    method delete_text (line 163) | fn delete_text(&mut self, delete: usize) {
    method enlarge_gap (line 173) | fn enlarge_gap(&mut self, len: usize) {
    method commit_gap (line 230) | pub fn commit_gap(&mut self, len: usize) {
    method replace (line 237) | pub fn replace(&mut self, range: Range<usize>, src: &[u8]) {
    method clear (line 243) | pub fn clear(&mut self) {
    method extract_raw (line 250) | pub fn extract_raw(&self, range: Range<usize>, out: &mut Vec<u8>, mut ...
    method copy_from (line 273) | pub fn copy_from(&mut self, src: &dyn ReadableDocument) -> bool {
    method copy_into (line 315) | pub fn copy_into(&self, dst: &mut dyn WriteableDocument) {
  method read_forward (line 334) | fn read_forward(&self, off: usize) -> &[u8] {
  method read_backward (line 352) | fn read_backward(&self, off: usize) -> &[u8] {

FILE: crates/edit/src/buffer/line_cache.rs
  constant CACHE_EVERY (line 6) | const CACHE_EVERY: usize = 1024 * 64;
  type CachePoint (line 9) | pub struct CachePoint {
  type LineCache (line 15) | pub struct LineCache {
    method new (line 20) | pub fn new() -> Self {
    method from_document (line 24) | pub fn from_document<T: ReadableDocument>(&mut self, document: &T) {
    method delete (line 51) | pub fn delete(&mut self, range: Range<usize>, text: &Vec<u8>) {
    method insert (line 82) | pub fn insert(&mut self, offset: usize, text: &[u8]) {
    method nearest_offset (line 105) | pub fn nearest_offset(&self, target_count: usize, reverse: bool) -> Op...

FILE: crates/edit/src/buffer/mod.rs
  constant MARGIN_TEMPLATE (line 55) | const MARGIN_TEMPLATE: &str = "                    │ ";
  constant TAB_WHITESPACE (line 58) | const TAB_WHITESPACE: &str = MARGIN_TEMPLATE;
  constant VISUAL_SPACE (line 59) | const VISUAL_SPACE: &str = "・";
  constant VISUAL_SPACE_PREFIX_ADD (line 60) | const VISUAL_SPACE_PREFIX_ADD: usize = '・'.len_utf8() - 1;
  constant VISUAL_TAB (line 61) | const VISUAL_TAB: &str = "→       ";
  constant VISUAL_TAB_PREFIX_ADD (line 62) | const VISUAL_TAB_PREFIX_ADD: usize = '→'.len_utf8() - 1;
  type IoError (line 64) | pub enum IoError {
    method from (line 72) | fn from(err: io::Error) -> Self {
    method from (line 78) | fn from(err: icu::Error) -> Self {
  type IoResult (line 69) | pub type IoResult<T> = std::result::Result<T, IoError>;
  type TextBufferStatistics (line 85) | pub struct TextBufferStatistics {
  type TextBufferSelection (line 95) | struct TextBufferSelection {
  type HistoryType (line 104) | enum HistoryType {
  type HistoryEntry (line 111) | struct HistoryEntry {
  type ActiveSearch (line 132) | struct ActiveSearch {
  type SearchOptions (line 157) | pub struct SearchOptions {
  type RegexReplacement (line 166) | enum RegexReplacement<'a> {
  type ActiveEditLineInfo (line 173) | struct ActiveEditLineInfo {
  type ActiveEditGroupInfo (line 189) | struct ActiveEditGroupInfo {
  type CursorMovement (line 203) | pub enum CursorMovement {
  type MoveLineDirection (line 209) | pub enum MoveLineDirection {
  type RenderResult (line 215) | pub struct RenderResult {
  type TextBufferCell (line 221) | pub type TextBufferCell = SemiRefCell<TextBuffer>;
  type RcTextBuffer (line 227) | pub type RcTextBuffer = Rc<TextBufferCell>;
  type TextBuffer (line 230) | pub struct TextBuffer {
    method new_rc (line 274) | pub fn new_rc(small: bool) -> io::Result<RcTextBuffer> {
    method new (line 281) | pub fn new(small: bool) -> io::Result<Self> {
    method text_length (line 321) | pub fn text_length(&self) -> usize {
    method logical_line_count (line 327) | pub fn logical_line_count(&self) -> CoordType {
    method visual_line_count (line 333) | pub fn visual_line_count(&self) -> CoordType {
    method is_dirty (line 338) | pub fn is_dirty(&self) -> bool {
    method generation (line 345) | pub fn generation(&self) -> u32 {
    method mark_as_dirty (line 350) | pub fn mark_as_dirty(&mut self) {
    method mark_as_clean (line 354) | fn mark_as_clean(&mut self) {
    method encoding (line 359) | pub fn encoding(&self) -> &'static str {
    method set_encoding (line 364) | pub fn set_encoding(&mut self, encoding: &'static str) {
    method is_crlf (line 372) | pub fn is_crlf(&self) -> bool {
    method set_crlf (line 377) | pub fn set_crlf(&mut self, crlf: bool) {
    method normalize_newlines (line 384) | pub fn normalize_newlines(&mut self, crlf: bool) {
    method set_insert_final_newline (line 452) | pub fn set_insert_final_newline(&mut self, enabled: bool) {
    method is_overtype (line 457) | pub fn is_overtype(&self) -> bool {
    method set_overtype (line 462) | pub fn set_overtype(&mut self, overtype: bool) {
    method cursor_logical_pos (line 468) | pub fn cursor_logical_pos(&self) -> Point {
    method cursor_visual_pos (line 474) | pub fn cursor_visual_pos(&self) -> Point {
    method margin_width (line 479) | pub fn margin_width(&self) -> CoordType {
    method set_margin_enabled (line 484) | pub fn set_margin_enabled(&mut self, enabled: bool) -> bool {
    method text_width (line 495) | pub fn text_width(&self) -> CoordType {
    method make_cursor_visible (line 506) | pub fn make_cursor_visible(&mut self) {
    method take_cursor_visibility_request (line 511) | pub fn take_cursor_visibility_request(&mut self) -> bool {
    method is_word_wrap_enabled (line 518) | pub fn is_word_wrap_enabled(&self) -> bool {
    method set_word_wrap (line 526) | pub fn set_word_wrap(&mut self, enabled: bool) {
    method set_width (line 539) | pub fn set_width(&mut self, width: CoordType) -> bool {
    method tab_size (line 550) | pub fn tab_size(&self) -> CoordType {
    method set_tab_size (line 555) | pub fn set_tab_size(&mut self, width: CoordType) -> bool {
    method tab_size_eval (line 572) | fn tab_size_eval(&self, column: CoordType) -> CoordType {
    method tab_size_prev_column (line 581) | fn tab_size_prev_column(&self, column: CoordType) -> CoordType {
    method indent_with_tabs (line 588) | pub fn indent_with_tabs(&self) -> bool {
    method set_indent_with_tabs (line 593) | pub fn set_indent_with_tabs(&mut self, indent_with_tabs: bool) {
    method set_line_highlight_enabled (line 598) | pub fn set_line_highlight_enabled(&mut self, enabled: bool) {
    method set_ruler (line 603) | pub fn set_ruler(&mut self, column: CoordType) {
    method reflow (line 607) | pub fn reflow(&mut self) {
    method recalc_after_content_changed (line 611) | fn recalc_after_content_changed(&mut self) {
    method reflow_internal (line 615) | fn reflow_internal(&mut self, force: bool) {
    method copy_from_str (line 659) | pub fn copy_from_str(&mut self, text: &dyn ReadableDocument) {
    method recalc_after_content_swap (line 671) | fn recalc_after_content_swap(&mut self) {
    method save_as_string (line 683) | pub fn save_as_string(&mut self, dst: &mut dyn WriteableDocument) {
    method read_file (line 689) | pub fn read_file(&mut self, file: &mut File, encoding: Option<&'static...
    method read_file_as_utf8 (line 832) | fn read_file_as_utf8(
    method read_file_with_icu (line 886) | fn read_file_with_icu(
    method write_file (line 951) | pub fn write_file(&mut self, file: &mut File) -> IoResult<()> {
    method write_file_with_icu (line 974) | fn write_file_with_icu(&mut self, file: &mut File) -> IoResult<()> {
    method has_selection (line 1008) | pub fn has_selection(&self) -> bool {
    method set_selection (line 1012) | fn set_selection(&mut self, selection: Option<TextBufferSelection>) ->...
    method selection_update_offset (line 1019) | pub fn selection_update_offset(&mut self, offset: usize) {
    method selection_update_visual (line 1024) | pub fn selection_update_visual(&mut self, visual_pos: Point) {
    method selection_update_logical (line 1029) | pub fn selection_update_logical(&mut self, logical_pos: Point) {
    method selection_update_delta (line 1036) | pub fn selection_update_delta(&mut self, granularity: CursorMovement, ...
    method select_word (line 1045) | pub fn select_word(&mut self) {
    method select_line (line 1057) | pub fn select_line(&mut self) {
    method select_all (line 1072) | pub fn select_all(&mut self) {
    method start_selection (line 1083) | pub fn start_selection(&mut self) {
    method clear_selection (line 1093) | pub fn clear_selection(&mut self) -> bool {
    method find_and_select (line 1100) | pub fn find_and_select(&mut self, pattern: &str, options: SearchOption...
    method find_and_replace (line 1153) | pub fn find_and_replace(
    method find_and_replace_all (line 1176) | pub fn find_and_replace_all(
    method find_construct_search (line 1202) | fn find_construct_search(
    method find_select_next (line 1262) | fn find_select_next(&mut self, search: &mut ActiveSearch, offset: usiz...
    method find_parse_replacement (line 1303) | fn find_parse_replacement<'a>(
    method find_fill_replacement (line 1404) | fn find_fill_replacement<'a>(
    method measurement_config (line 1430) | fn measurement_config(&self) -> MeasurementConfig<'_> {
    method goto_line_start (line 1436) | fn goto_line_start(&self, cursor: Cursor, y: CoordType) -> Cursor {
    method cursor_move_to_offset_internal (line 1519) | fn cursor_move_to_offset_internal(&self, mut cursor: Cursor, offset: u...
    method cursor_move_to_logical_internal (line 1549) | fn cursor_move_to_logical_internal(&self, mut cursor: Cursor, pos: Poi...
    method cursor_move_to_visual_internal (line 1566) | fn cursor_move_to_visual_internal(&self, mut cursor: Cursor, pos: Poin...
    method cursor_move_delta_internal (line 1593) | fn cursor_move_delta_internal(
    method cursor_move_to_offset (line 1665) | pub fn cursor_move_to_offset(&mut self, offset: usize) {
    method cursor_move_to_logical (line 1670) | pub fn cursor_move_to_logical(&mut self, pos: Point) {
    method cursor_move_to_visual (line 1675) | pub fn cursor_move_to_visual(&mut self, pos: Point) {
    method cursor_move_delta (line 1680) | pub fn cursor_move_delta(&mut self, granularity: CursorMovement, delta...
    method set_cursor (line 1690) | pub unsafe fn set_cursor(&mut self, cursor: Cursor) {
    method set_cursor_for_selection (line 1696) | fn set_cursor_for_selection(&mut self, cursor: Cursor) {
    method set_cursor_internal (line 1709) | fn set_cursor_internal(&mut self, cursor: Cursor) {
    method render (line 1724) | pub fn render(
    method cut (line 2061) | pub fn cut(&mut self, clipboard: &mut Clipboard) {
    method copy (line 2065) | pub fn copy(&mut self, clipboard: &mut Clipboard) {
    method cut_copy (line 2069) | fn cut_copy(&mut self, clipboard: &mut Clipboard, cut: bool) {
    method paste (line 2076) | pub fn paste(&mut self, clipboard: &Clipboard) {
    method write_canon (line 2098) | pub fn write_canon(&mut self, text: &[u8]) {
    method write_raw (line 2104) | pub fn write_raw(&mut self, text: &[u8]) {
    method write (line 2108) | fn write(&mut self, text: &[u8], at: Cursor, raw: bool) {
    method delete (line 2271) | pub fn delete(&mut self, granularity: CursorMovement, delta: CoordType) {
    method indent_end_logical_pos (line 2308) | pub fn indent_end_logical_pos(&self) -> Point {
    method indent_change (line 2315) | pub fn indent_change(&mut self, direction: CoordType) {
    method measure_indent_internal (line 2382) | fn measure_indent_internal(
    method move_selected_lines (line 2422) | pub fn move_selected_lines(&mut self, direction: MoveLineDirection) {
    method extract_selection (line 2491) | fn extract_selection(&mut self, delete: bool) -> Vec<u8> {
    method extract_user_selection (line 2518) | pub fn extract_user_selection(&mut self, delete: bool) -> Option<Vec<u...
    method selection_range (line 2535) | pub fn selection_range(&self) -> Option<(Cursor, Cursor)> {
    method selection_range_internal (line 2544) | fn selection_range_internal(&self, line_fallback: bool) -> Option<(Cur...
    method edit_begin_grouping (line 2560) | fn edit_begin_grouping(&mut self) {
    method edit_end_grouping (line 2569) | fn edit_end_grouping(&mut self) {
    method edit_begin (line 2575) | fn edit_begin(&mut self, history_type: HistoryType, cursor: Cursor) {
    method edit_write (line 2637) | fn edit_write(&mut self, text: &[u8]) {
    method edit_delete (line 2658) | fn edit_delete(&mut self, to: Cursor) {
    method edit_end (line 2687) | fn edit_end(&mut self) {
    method undo (line 2734) | pub fn undo(&mut self) {
    method redo (line 2739) | pub fn redo(&mut self) {
    method undo_redo (line 2743) | fn undo_redo(&mut self, undo: bool) {
    method read_backward (line 2870) | pub(crate) fn read_backward(&self, off: usize) -> &[u8] {
    method read_forward (line 2875) | pub fn read_forward(&self, off: usize) -> &[u8] {
  type Bom (line 2880) | pub enum Bom {
  constant BOM_MAX_LEN (line 2890) | const BOM_MAX_LEN: usize = 4;
  function detect_bom (line 2892) | fn detect_bom(bytes: &[u8]) -> Option<&'static str> {

FILE: crates/edit/src/buffer/navigation.rs
  type CharClass (line 9) | enum CharClass {
  function construct_classifier (line 16) | const fn construct_classifier(separators: &[u8]) -> [CharClass; 256] {
  constant WORD_CLASSIFIER (line 36) | const WORD_CLASSIFIER: [CharClass; 256] =
  function word_forward (line 41) | pub fn word_forward(doc: &dyn ReadableDocument, offset: usize) -> usize {
  function word_backward (line 46) | pub fn word_backward(doc: &dyn ReadableDocument, offset: usize) -> usize {
  function word_navigation (line 51) | fn word_navigation<T: WordNavigation>(mut nav: T) -> usize {
  type WordNavigation (line 81) | trait WordNavigation {
    method read (line 82) | fn read(&mut self);
    method skip_newline (line 83) | fn skip_newline(&mut self);
    method skip_class (line 84) | fn skip_class(&mut self, class: CharClass);
    method peek (line 85) | fn peek(&self, default: CharClass) -> CharClass;
    method next (line 86) | fn next(&mut self);
    method offset (line 87) | fn offset(&self) -> usize;
    method read (line 98) | fn read(&mut self) {
    method skip_newline (line 103) | fn skip_newline(&mut self) {
    method skip_class (line 115) | fn skip_class(&mut self, class: CharClass) {
    method peek (line 130) | fn peek(&self, default: CharClass) -> CharClass {
    method next (line 138) | fn next(&mut self) {
    method offset (line 142) | fn offset(&self) -> usize {
    method read (line 155) | fn read(&mut self) {
    method skip_newline (line 160) | fn skip_newline(&mut self) {
    method skip_class (line 171) | fn skip_class(&mut self, class: CharClass) {
    method peek (line 186) | fn peek(&self, default: CharClass) -> CharClass {
    method next (line 194) | fn next(&mut self) {
    method offset (line 198) | fn offset(&self) -> usize {
  type WordForward (line 90) | struct WordForward<'a> {
  type WordBackward (line 147) | struct WordBackward<'a> {
  function word_select (line 205) | pub fn word_select(doc: &dyn ReadableDocument, offset: usize) -> Range<u...
  function test_word_navigation (line 279) | fn test_word_navigation() {

FILE: crates/edit/src/cell.rs
  type SemiRefCell (line 14) | pub type SemiRefCell<T> = std::cell::RefCell<T>;
  type Ref (line 15) | pub type Ref<'b, T> = std::cell::Ref<'b, T>;
  type RefMut (line 16) | pub type RefMut<'b, T> = std::cell::RefMut<'b, T>;
  type SemiRefCell (line 23) | pub struct SemiRefCell<T>(std::cell::UnsafeCell<T>);
  function new (line 27) | pub const fn new(value: T) -> Self {
  function as_ptr (line 32) | pub const fn as_ptr(&self) -> *mut T {
  function borrow (line 37) | pub const fn borrow(&self) -> Ref<'_, T> {
  function borrow_mut (line 42) | pub const fn borrow_mut(&self) -> RefMut<'_, T> {
  type Ref (line 48) | pub struct Ref<'b, T>(&'b T);
  function clone (line 52) | pub fn clone(orig: &Self) -> Self {
  type Target (line 58) | type Target = T;
  function deref (line 61) | fn deref(&self) -> &Self::Target {
  type RefMut (line 67) | pub struct RefMut<'b, T>(&'b mut T);
  type Target (line 70) | type Target = T;
  function deref (line 73) | fn deref(&self) -> &Self::Target {
  function deref_mut (line 80) | fn deref_mut(&mut self) -> &mut Self::Target {

FILE: crates/edit/src/clipboard.rs
  type Clipboard (line 11) | pub struct Clipboard {
    method wants_host_sync (line 20) | pub fn wants_host_sync(&self) -> bool {
    method mark_as_synchronized (line 25) | pub fn mark_as_synchronized(&mut self) {
    method is_line_copy (line 34) | pub fn is_line_copy(&self) -> bool {
    method read (line 39) | pub fn read(&self) -> &[u8] {
    method write (line 44) | pub fn write(&mut self, data: Vec<u8>) {
    method write_was_line_copy (line 53) | pub fn write_was_line_copy(&mut self, line_copy: bool) {

FILE: crates/edit/src/document.rs
  type ReadableDocument (line 14) | pub trait ReadableDocument {
    method read_forward (line 25) | fn read_forward(&self, off: usize) -> &[u8];
    method read_backward (line 37) | fn read_backward(&self, off: usize) -> &[u8];
    method read_forward (line 52) | fn read_forward(&self, off: usize) -> &[u8] {
    method read_backward (line 57) | fn read_backward(&self, off: usize) -> &[u8] {
    method read_forward (line 64) | fn read_forward(&self, off: usize) -> &[u8] {
    method read_backward (line 69) | fn read_backward(&self, off: usize) -> &[u8] {
    method read_forward (line 85) | fn read_forward(&self, off: usize) -> &[u8] {
    method read_backward (line 90) | fn read_backward(&self, off: usize) -> &[u8] {
  type WriteableDocument (line 41) | pub trait WriteableDocument: ReadableDocument {
    method replace (line 48) | fn replace(&mut self, range: Range<usize>, replacement: &[u8]);
    method replace (line 76) | fn replace(&mut self, range: Range<usize>, replacement: &[u8]) {
    method replace (line 97) | fn replace(&mut self, range: Range<usize>, replacement: &[u8]) {

FILE: crates/edit/src/framebuffer.rs
  constant HASH_MULTIPLIER (line 22) | const HASH_MULTIPLIER: usize = 747796405;
  constant HASH_MULTIPLIER (line 24) | const HASH_MULTIPLIER: usize = 6364136223846793005;
  constant CACHE_TABLE_LOG2_SIZE (line 27) | const CACHE_TABLE_LOG2_SIZE: usize = 8;
  constant CACHE_TABLE_SIZE (line 28) | const CACHE_TABLE_SIZE: usize = 1 << CACHE_TABLE_LOG2_SIZE;
  constant CACHE_TABLE_SHIFT (line 32) | const CACHE_TABLE_SHIFT: usize = usize::BITS as usize - CACHE_TABLE_LOG2...
  type IndexedColor (line 36) | pub enum IndexedColor {
    method from (line 59) | fn from(value: T) -> Self {
  constant INDEXED_COLORS_COUNT (line 65) | pub const INDEXED_COLORS_COUNT: usize = 18;
  constant DEFAULT_THEME (line 68) | pub const DEFAULT_THEME: [StraightRgba; INDEXED_COLORS_COUNT] = [
  type Framebuffer (line 100) | pub struct Framebuffer {
    method new (line 122) | pub fn new() -> Self {
    method set_indexed_colors (line 143) | pub fn set_indexed_colors(&mut self, colors: [StraightRgba; INDEXED_CO...
    method flip (line 168) | pub fn flip(&mut self, size: Size) {
    method replace_text (line 198) | pub fn replace_text(
    method draw_scrollbar (line 221) | pub fn draw_scrollbar(
    method indexed (line 333) | pub fn indexed(&self, index: IndexedColor) -> StraightRgba {
    method indexed_alpha (line 342) | pub fn indexed_alpha(
    method contrasted (line 354) | pub fn contrasted(&self, color: StraightRgba) -> StraightRgba {
    method contrasted_slow (line 361) | fn contrasted_slow(&self, color: StraightRgba) -> StraightRgba {
    method blend_bg (line 373) | pub fn blend_bg(&mut self, target: Rect, bg: StraightRgba) {
    method blend_fg (line 382) | pub fn blend_fg(&mut self, target: Rect, fg: StraightRgba) {
    method reverse (line 388) | pub fn reverse(&mut self, target: Rect) {
    method replace_attr (line 412) | pub fn replace_attr(&mut self, target: Rect, mask: Attributes, attr: A...
    method set_cursor (line 420) | pub fn set_cursor(&mut self, pos: Point, overtype: bool) {
    method render (line 428) | pub fn render<'a>(&mut self, arena: &'a Arena) -> BString<'a> {
    method format_color (line 562) | fn format_color<'a>(
  type Buffer (line 603) | struct Buffer {
  type LineBuffer (line 613) | struct LineBuffer {
    method new (line 619) | fn new(size: Size) -> Self {
    method fill_whitespace (line 623) | fn fill_whitespace(&mut self) {
    method replace_text (line 638) | fn replace_text(
  type Bitmap (line 760) | struct Bitmap {
    method new (line 766) | fn new(size: Size) -> Self {
    method fill (line 770) | fn fill(&mut self, color: StraightRgba) {
    method blend (line 778) | fn blend(&mut self, target: Rect, color: StraightRgba) {
    method iter (line 826) | fn iter(&self) -> ChunksExact<'_, StraightRgba> {
  type Attributes (line 836) | pub struct Attributes(u8);
    constant None (line 840) | pub const None: Self = Self(0);
    constant Italic (line 841) | pub const Italic: Self = Self(0b1);
    constant Underlined (line 842) | pub const Underlined: Self = Self(0b10);
    constant All (line 843) | pub const All: Self = Self(0b11);
    method is (line 845) | pub const fn is(self, attr: Self) -> bool {
  type Output (line 851) | type Output = Self;
  method bitor (line 853) | fn bitor(self, rhs: Self) -> Self::Output {
  type Output (line 859) | type Output = Self;
  method bitxor (line 861) | fn bitxor(self, rhs: Self) -> Self::Output {
  type AttributeBuffer (line 868) | struct AttributeBuffer {
    method new (line 874) | fn new(size: Size) -> Self {
    method reset (line 878) | fn reset(&mut self) {
    method replace (line 882) | fn replace(&mut self, target: Rect, mask: Attributes, attr: Attributes) {
    method iter (line 910) | fn iter(&self) -> ChunksExact<'_, Attributes> {
  type Cursor (line 917) | struct Cursor {
    method new_invalid (line 923) | const fn new_invalid() -> Self {
    method new_disabled (line 927) | const fn new_disabled() -> Self {

FILE: crates/edit/src/fuzzy.rs
  constant NO_MATCH (line 13) | const NO_MATCH: i32 = 0;
  function score_fuzzy (line 15) | pub fn score_fuzzy<'a>(
  function compute_char_score (line 158) | fn compute_char_score(
  function consider_as_equal (line 206) | fn consider_as_equal(a: char, b: char) -> bool {
  function score_separator_at_pos (line 211) | fn score_separator_at_pos(ch: char) -> i32 {
  function map_chars (line 219) | fn map_chars<'a>(arena: &'a Arena, s: &str) -> BVec<'a, char> {

FILE: crates/edit/src/glob.rs
  function glob_match (line 14) | pub fn glob_match<P: AsRef<[u8]>, N: AsRef<[u8]>>(pattern: P, name: N) -...
  function glob (line 18) | fn glob(pattern: &[u8], name: &[u8]) -> bool {
  function fast_path (line 25) | fn fast_path(pattern: &[u8], name: &[u8]) -> Option<bool> {
  function contains_magic (line 57) | fn contains_magic(pattern: &[u8]) -> bool {
  function match_path_suffix (line 61) | fn match_path_suffix(path: &[u8], suffix: &[u8]) -> bool {
  function slow_path (line 84) | fn slow_path(pattern: &[u8], name: &[u8]) -> bool {
  function test_glob_match (line 147) | fn test_glob_match() {

FILE: crates/edit/src/hash.rs
  type WyHash (line 14) | pub struct WyHash(u64);
  method finish (line 17) | fn finish(&self) -> u64 {
  method write (line 21) | fn write(&mut self, bytes: &[u8]) {
  function hash (line 33) | pub fn hash(mut seed: u64, data: &[u8]) -> u64 {
  function wyr3 (line 86) | unsafe fn wyr3(p: *const u8, k: usize) -> u64 {
  function wyr4 (line 93) | unsafe fn wyr4(p: *const u8) -> u64 {
  function wyr8 (line 97) | unsafe fn wyr8(p: *const u8) -> u64 {
  function wymix (line 104) | pub fn wymix(lhs: u64, rhs: u64) -> u64 {
  function hash_str (line 111) | pub fn hash_str(seed: u64, s: &str) -> u64 {

FILE: crates/edit/src/helpers.rs
  constant KILO (line 11) | pub const KILO: usize = 1000;
  constant MEGA (line 12) | pub const MEGA: usize = 1000 * 1000;
  constant GIGA (line 13) | pub const GIGA: usize = 1000 * 1000 * 1000;
  constant KIBI (line 15) | pub const KIBI: usize = 1024;
  constant MEBI (line 16) | pub const MEBI: usize = 1024 * 1024;
  constant GIBI (line 17) | pub const GIBI: usize = 1024 * 1024 * 1024;
  type MetricFormatter (line 19) | pub struct MetricFormatter<T>(pub T);
  function fmt (line 22) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type CoordType (line 40) | pub type CoordType = isize;
  constant COORD_TYPE_SAFE_MAX (line 47) | pub const COORD_TYPE_SAFE_MAX: CoordType = (1 << (CoordType::BITS / 2 - ...
  type Point (line 51) | pub struct Point {
    constant MIN (line 57) | pub const MIN: Self = Self { x: CoordType::MIN, y: CoordType::MIN };
    constant MAX (line 58) | pub const MAX: Self = Self { x: CoordType::MAX, y: CoordType::MAX };
    method partial_cmp (line 62) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  method cmp (line 68) | fn cmp(&self, other: &Self) -> Ordering {
  type Size (line 75) | pub struct Size {
    method as_rect (line 81) | pub fn as_rect(&self) -> Rect {
  type Rect (line 88) | pub struct Rect {
    method one (line 97) | pub fn one(value: CoordType) -> Self {
    method two (line 103) | pub fn two(top_bottom: CoordType, left_right: CoordType) -> Self {
    method three (line 109) | pub fn three(top: CoordType, left_right: CoordType, bottom: CoordType)...
    method is_empty (line 114) | pub fn is_empty(&self) -> bool {
    method width (line 119) | pub fn width(&self) -> CoordType {
    method height (line 124) | pub fn height(&self) -> CoordType {
    method contains (line 129) | pub fn contains(&self, point: Point) -> bool {
    method intersect (line 134) | pub fn intersect(&self, rhs: Self) -> Self {
  function file_read_uninit (line 150) | pub fn file_read_uninit<T: Read>(file: &mut T, buf: &mut [MaybeUninit<u8...

FILE: crates/edit/src/icu.rs
  constant ILLEGAL_ARGUMENT_ERROR (line 21) | pub(crate) const ILLEGAL_ARGUMENT_ERROR: Error = Error(1);
  constant ICU_MISSING_ERROR (line 22) | pub const ICU_MISSING_ERROR: Error = Error(0);
  type Error (line 25) | pub struct Error(u32);
    method fmt (line 28) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Result (line 56) | pub type Result<T> = std::result::Result<T, Error>;
  type Encoding (line 59) | pub struct Encoding {
  type Encodings (line 64) | pub struct Encodings {
  function get_available_encodings (line 72) | pub fn get_available_encodings() -> &'static Encodings {
  type Converter (line 135) | pub struct Converter<'pivot> {
  method drop (line 145) | fn drop(&mut self) {
  function new (line 161) | pub fn new(
  function append_nul (line 191) | fn append_nul<'a>(arena: &'a Arena, input: &str) -> BString<'a> {
  function convert (line 209) | pub fn convert(
  constant CACHE_SIZE (line 261) | const CACHE_SIZE: usize = 64;
  type Cache (line 265) | struct Cache {
  type DoubleCache (line 288) | struct DoubleCache {
  type Text (line 303) | pub struct Text(&'static mut icu_ffi::UText);
    method new (line 319) | pub unsafe fn new(tb: &TextBuffer) -> Result<Self> {
  method drop (line 306) | fn drop(&mut self) {
  function text_buffer_from_utext (line 357) | fn text_buffer_from_utext<'a>(ut: &icu_ffi::UText) -> &'a TextBuffer {
  function double_cache_from_utext (line 361) | fn double_cache_from_utext<'a>(ut: &icu_ffi::UText) -> &'a mut DoubleCac...
  function utext_clone (line 365) | extern "C" fn utext_clone(
  function utext_native_length (line 399) | extern "C" fn utext_native_length(ut: &mut icu_ffi::UText) -> i64 {
  function utext_access (line 404) | extern "C" fn utext_access(ut: &mut icu_ffi::UText, native_index: i64, f...
  function utext_access_impl (line 419) | fn utext_access_impl<'a>(
  function utext_map_offset_to_native (line 586) | extern "C" fn utext_map_offset_to_native(ut: &icu_ffi::UText) -> i64 {
  function utext_map_native_index_to_utf16 (line 596) | extern "C" fn utext_map_native_index_to_utf16(ut: &icu_ffi::UText, nativ...
  type Regex (line 610) | pub struct Regex(&'static mut icu_ffi::URegularExpression);
    constant CASE_INSENSITIVE (line 621) | pub const CASE_INSENSITIVE: i32 = icu_ffi::UREGEX_CASE_INSENSITIVE;
    constant MULTILINE (line 625) | pub const MULTILINE: i32 = icu_ffi::UREGEX_MULTILINE;
    constant LITERAL (line 628) | pub const LITERAL: i32 = icu_ffi::UREGEX_LITERAL;
    method new (line 635) | pub unsafe fn new(pattern: &str, flags: i32, text: &Text) -> Result<Se...
    method set_text (line 671) | pub unsafe fn set_text(&mut self, text: &mut Text, offset: usize) {
    method reset (line 686) | pub fn reset(&mut self, offset: usize) {
    method group_count (line 693) | pub fn group_count(&mut self) -> i32 {
    method group (line 702) | pub fn group(&mut self, group: i32) -> Option<Range<usize>> {
  method drop (line 613) | fn drop(&mut self) {
  type Item (line 719) | type Item = Range<usize>;
  method next (line 721) | fn next(&mut self) -> Option<Self::Item> {
  function compare_strings (line 737) | pub fn compare_strings(a: &[u8], b: &[u8]) -> Ordering {
  function compare_strings_ascii (line 807) | fn compare_strings_ascii(a: &[u8], b: &[u8]) -> Ordering {
  function fold_case (line 848) | pub fn fold_case<'a>(arena: &'a Arena, input: &str) -> BString<'a> {
  type LibraryFunctions (line 930) | struct LibraryFunctions {
  constant LIBICUUC_PROC_NAMES (line 966) | const LIBICUUC_PROC_NAMES: [*const c_char; 10] = [
  constant LIBICUI18N_PROC_NAMES (line 980) | const LIBICUI18N_PROC_NAMES: [*const c_char; 12] = [
  type LibraryFunctionsState (line 995) | enum LibraryFunctionsState {
  function init (line 1003) | pub fn init() -> Result<()> {
  function init_if_needed (line 1009) | fn init_if_needed() -> Result<&'static LibraryFunctions> {
  function assume_loaded (line 1085) | fn assume_loaded() -> &'static LibraryFunctions {
  type UErrorCode (line 1101) | pub struct UErrorCode(c_int);
    method new (line 1104) | pub const fn new(code: u32) -> Self {
    method is_success (line 1108) | pub fn is_success(&self) -> bool {
    method is_failure (line 1112) | pub fn is_failure(&self) -> bool {
    method as_error (line 1116) | pub fn as_error(&self) -> Error {
  constant U_ZERO_ERROR (line 1122) | pub const U_ZERO_ERROR: UErrorCode = UErrorCode(0);
  constant U_BUFFER_OVERFLOW_ERROR (line 1123) | pub const U_BUFFER_OVERFLOW_ERROR: UErrorCode = UErrorCode(15);
  constant U_UNSUPPORTED_ERROR (line 1124) | pub const U_UNSUPPORTED_ERROR: UErrorCode = UErrorCode(16);
  type u_errorName (line 1126) | pub type u_errorName = unsafe extern "C" fn(code: UErrorCode) -> *const ...
  type UConverter (line 1128) | pub struct UConverter;
  type ucnv_getAvailableName (line 1130) | pub type ucnv_getAvailableName = unsafe extern "C" fn(n: i32) -> *const ...
  type ucnv_getStandardName (line 1132) | pub type ucnv_getStandardName = unsafe extern "C" fn(
  type ucnv_open (line 1138) | pub type ucnv_open =
  type ucnv_close (line 1141) | pub type ucnv_close = unsafe extern "C" fn(converter: *mut UConverter);
  type ucnv_convertEx (line 1143) | pub type ucnv_convertEx = unsafe extern "C" fn(
  type UCaseMap (line 1159) | pub struct UCaseMap;
  type ucasemap_open (line 1161) | pub type ucasemap_open = unsafe extern "C" fn(
  type ucasemap_utf8FoldCase (line 1167) | pub type ucasemap_utf8FoldCase = unsafe extern "C" fn(
  type UCollationResult (line 1177) | pub enum UCollationResult {
  type UCollator (line 1184) | pub struct UCollator;
  type ucol_open (line 1186) | pub type ucol_open =
  type ucol_setAttribute (line 1189) | pub type ucol_setAttribute =
  constant UCOL_NORMALIZATION_MODE (line 1192) | pub const UCOL_NORMALIZATION_MODE: i32 = 4;
  constant UCOL_NUMERIC_COLLATION (line 1193) | pub const UCOL_NUMERIC_COLLATION: i32 = 7;
  constant UCOL_ON (line 1194) | pub const UCOL_ON: i32 = 17;
  type ucol_strcollUTF8 (line 1196) | pub type ucol_strcollUTF8 = unsafe extern "C" fn(
  type UTextClone (line 1206) | pub type UTextClone = unsafe extern "C" fn(
  type UTextNativeLength (line 1212) | pub type UTextNativeLength = unsafe extern "C" fn(ut: &mut UText) -> i64;
  type UTextAccess (line 1213) | pub type UTextAccess =
  type UTextExtract (line 1215) | pub type UTextExtract = unsafe extern "C" fn(
  type UTextReplace (line 1223) | pub type UTextReplace = unsafe extern "C" fn(
  type UTextCopy (line 1231) | pub type UTextCopy = unsafe extern "C" fn(
  type UTextMapOffsetToNative (line 1239) | pub type UTextMapOffsetToNative = unsafe extern "C" fn(ut: &UText) -> i64;
  type UTextMapNativeIndexToUTF16 (line 1240) | pub type UTextMapNativeIndexToUTF16 =
  type UTextClose (line 1242) | pub type UTextClose = unsafe extern "C" fn(ut: &mut UText);
  type UTextFuncs (line 1245) | pub struct UTextFuncs {
  type UText (line 1265) | pub struct UText {
  constant UTEXT_MAGIC (line 1292) | pub const UTEXT_MAGIC: u32 = 0x345ad82c;
  constant UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE (line 1293) | pub const UTEXT_PROVIDER_LENGTH_IS_EXPENSIVE: i32 = 1;
  constant UTEXT_PROVIDER_STABLE_CHUNKS (line 1294) | pub const UTEXT_PROVIDER_STABLE_CHUNKS: i32 = 2;
  constant UTEXT_PROVIDER_WRITABLE (line 1295) | pub const UTEXT_PROVIDER_WRITABLE: i32 = 3;
  constant UTEXT_PROVIDER_HAS_META_DATA (line 1296) | pub const UTEXT_PROVIDER_HAS_META_DATA: i32 = 4;
  constant UTEXT_PROVIDER_OWNS_TEXT (line 1297) | pub const UTEXT_PROVIDER_OWNS_TEXT: i32 = 5;
  type utext_setup (line 1299) | pub type utext_setup = unsafe extern "C" fn(
  type utext_close (line 1304) | pub type utext_close = unsafe extern "C" fn(ut: *mut UText) -> *mut UText;
  type UParseError (line 1307) | pub struct UParseError {
  type URegularExpression (line 1315) | pub struct URegularExpression;
  constant UREGEX_UNIX_LINES (line 1317) | pub const UREGEX_UNIX_LINES: i32 = 1;
  constant UREGEX_CASE_INSENSITIVE (line 1318) | pub const UREGEX_CASE_INSENSITIVE: i32 = 2;
  constant UREGEX_COMMENTS (line 1319) | pub const UREGEX_COMMENTS: i32 = 4;
  constant UREGEX_MULTILINE (line 1320) | pub const UREGEX_MULTILINE: i32 = 8;
  constant UREGEX_LITERAL (line 1321) | pub const UREGEX_LITERAL: i32 = 16;
  constant UREGEX_DOTALL (line 1322) | pub const UREGEX_DOTALL: i32 = 32;
  constant UREGEX_UWORD (line 1323) | pub const UREGEX_UWORD: i32 = 256;
  constant UREGEX_ERROR_ON_UNKNOWN_ESCAPES (line 1324) | pub const UREGEX_ERROR_ON_UNKNOWN_ESCAPES: i32 = 512;
  type uregex_open (line 1326) | pub type uregex_open = unsafe extern "C" fn(
  type uregex_close (line 1333) | pub type uregex_close = unsafe extern "C" fn(regexp: *mut URegularExpres...
  type uregex_setTimeLimit (line 1334) | pub type uregex_setTimeLimit =
  type uregex_setUText (line 1336) | pub type uregex_setUText = unsafe extern "C" fn(
  type uregex_reset64 (line 1341) | pub type uregex_reset64 =
  type uregex_findNext (line 1343) | pub type uregex_findNext =
  type uregex_groupCount (line 1345) | pub type uregex_groupCount =
  type uregex_start64 (line 1347) | pub type uregex_start64 = unsafe extern "C" fn(
  type uregex_end64 (line 1352) | pub type uregex_end64 = unsafe extern "C" fn(
  function init (line 1365) | fn init() {
  function test_compare_strings_ascii (line 1370) | fn test_compare_strings_ascii() {

FILE: crates/edit/src/input.rs
  type InputKey (line 22) | pub struct InputKey(u32);
    method new (line 25) | pub(crate) const fn new(v: u32) -> Self {
    method from_ascii (line 29) | pub(crate) const fn from_ascii(ch: char) -> Option<Self> {
    method value (line 41) | pub(crate) const fn value(&self) -> u32 {
    method key (line 45) | pub(crate) const fn key(&self) -> Self {
    method modifiers (line 49) | pub(crate) const fn modifiers(&self) -> InputKeyMod {
    method modifiers_contains (line 53) | pub(crate) const fn modifiers_contains(&self, modifier: InputKeyMod) -...
    method with_modifiers (line 57) | pub(crate) const fn with_modifiers(&self, modifiers: InputKeyMod) -> S...
    type Output (line 78) | type Output = Self;
    method bitor (line 80) | fn bitor(self, rhs: InputKeyMod) -> Self {
  type InputKeyMod (line 65) | pub struct InputKeyMod(u32);
    method new (line 68) | const fn new(v: u32) -> Self {
    method contains (line 72) | pub(crate) const fn contains(&self, modifier: Self) -> bool {
    type Output (line 86) | type Output = InputKey;
    method bitor (line 88) | fn bitor(self, rhs: InputKey) -> InputKey {
    method bitor_assign (line 94) | fn bitor_assign(&mut self, rhs: Self) {
  constant NULL (line 106) | pub const NULL: InputKey = InputKey::new('\0' as u32);
  constant BACK (line 107) | pub const BACK: InputKey = InputKey::new(0x08);
  constant TAB (line 108) | pub const TAB: InputKey = InputKey::new('\t' as u32);
  constant RETURN (line 109) | pub const RETURN: InputKey = InputKey::new('\r' as u32);
  constant ESCAPE (line 110) | pub const ESCAPE: InputKey = InputKey::new(0x1B);
  constant SPACE (line 111) | pub const SPACE: InputKey = InputKey::new(' ' as u32);
  constant PRIOR (line 112) | pub const PRIOR: InputKey = InputKey::new(0x21);
  constant NEXT (line 113) | pub const NEXT: InputKey = InputKey::new(0x22);
  constant END (line 115) | pub const END: InputKey = InputKey::new(0x23);
  constant HOME (line 116) | pub const HOME: InputKey = InputKey::new(0x24);
  constant LEFT (line 118) | pub const LEFT: InputKey = InputKey::new(0x25);
  constant UP (line 119) | pub const UP: InputKey = InputKey::new(0x26);
  constant RIGHT (line 120) | pub const RIGHT: InputKey = InputKey::new(0x27);
  constant DOWN (line 121) | pub const DOWN: InputKey = InputKey::new(0x28);
  constant INSERT (line 123) | pub const INSERT: InputKey = InputKey::new(0x2D);
  constant DELETE (line 124) | pub const DELETE: InputKey = InputKey::new(0x2E);
  constant N0 (line 126) | pub const N0: InputKey = InputKey::new('0' as u32);
  constant N1 (line 127) | pub const N1: InputKey = InputKey::new('1' as u32);
  constant N2 (line 128) | pub const N2: InputKey = InputKey::new('2' as u32);
  constant N3 (line 129) | pub const N3: InputKey = InputKey::new('3' as u32);
  constant N4 (line 130) | pub const N4: InputKey = InputKey::new('4' as u32);
  constant N5 (line 131) | pub const N5: InputKey = InputKey::new('5' as u32);
  constant N6 (line 132) | pub const N6: InputKey = InputKey::new('6' as u32);
  constant N7 (line 133) | pub const N7: InputKey = InputKey::new('7' as u32);
  constant N8 (line 134) | pub const N8: InputKey = InputKey::new('8' as u32);
  constant N9 (line 135) | pub const N9: InputKey = InputKey::new('9' as u32);
  constant A (line 137) | pub const A: InputKey = InputKey::new('A' as u32);
  constant B (line 138) | pub const B: InputKey = InputKey::new('B' as u32);
  constant C (line 139) | pub const C: InputKey = InputKey::new('C' as u32);
  constant D (line 140) | pub const D: InputKey = InputKey::new('D' as u32);
  constant E (line 141) | pub const E: InputKey = InputKey::new('E' as u32);
  constant F (line 142) | pub const F: InputKey = InputKey::new('F' as u32);
  constant G (line 143) | pub const G: InputKey = InputKey::new('G' as u32);
  constant H (line 144) | pub const H: InputKey = InputKey::new('H' as u32);
  constant I (line 145) | pub const I: InputKey = InputKey::new('I' as u32);
  constant J (line 146) | pub const J: InputKey = InputKey::new('J' as u32);
  constant K (line 147) | pub const K: InputKey = InputKey::new('K' as u32);
  constant L (line 148) | pub const L: InputKey = InputKey::new('L' as u32);
  constant M (line 149) | pub const M: InputKey = InputKey::new('M' as u32);
  constant N (line 150) | pub const N: InputKey = InputKey::new('N' as u32);
  constant O (line 151) | pub const O: InputKey = InputKey::new('O' as u32);
  constant P (line 152) | pub const P: InputKey = InputKey::new('P' as u32);
  constant Q (line 153) | pub const Q: InputKey = InputKey::new('Q' as u32);
  constant R (line 154) | pub const R: InputKey = InputKey::new('R' as u32);
  constant S (line 155) | pub const S: InputKey = InputKey::new('S' as u32);
  constant T (line 156) | pub const T: InputKey = InputKey::new('T' as u32);
  constant U (line 157) | pub const U: InputKey = InputKey::new('U' as u32);
  constant V (line 158) | pub const V: InputKey = InputKey::new('V' as u32);
  constant W (line 159) | pub const W: InputKey = InputKey::new('W' as u32);
  constant X (line 160) | pub const X: InputKey = InputKey::new('X' as u32);
  constant Y (line 161) | pub const Y: InputKey = InputKey::new('Y' as u32);
  constant Z (line 162) | pub const Z: InputKey = InputKey::new('Z' as u32);
  constant NUMPAD0 (line 164) | pub const NUMPAD0: InputKey = InputKey::new(0x60);
  constant NUMPAD1 (line 165) | pub const NUMPAD1: InputKey = InputKey::new(0x61);
  constant NUMPAD2 (line 166) | pub const NUMPAD2: InputKey = InputKey::new(0x62);
  constant NUMPAD3 (line 167) | pub const NUMPAD3: InputKey = InputKey::new(0x63);
  constant NUMPAD4 (line 168) | pub const NUMPAD4: InputKey = InputKey::new(0x64);
  constant NUMPAD5 (line 169) | pub const NUMPAD5: InputKey = InputKey::new(0x65);
  constant NUMPAD6 (line 170) | pub const NUMPAD6: InputKey = InputKey::new(0x66);
  constant NUMPAD7 (line 171) | pub const NUMPAD7: InputKey = InputKey::new(0x67);
  constant NUMPAD8 (line 172) | pub const NUMPAD8: InputKey = InputKey::new(0x68);
  constant NUMPAD9 (line 173) | pub const NUMPAD9: InputKey = InputKey::new(0x69);
  constant MULTIPLY (line 174) | pub const MULTIPLY: InputKey = InputKey::new(0x6A);
  constant ADD (line 175) | pub const ADD: InputKey = InputKey::new(0x6B);
  constant SEPARATOR (line 176) | pub const SEPARATOR: InputKey = InputKey::new(0x6C);
  constant SUBTRACT (line 177) | pub const SUBTRACT: InputKey = InputKey::new(0x6D);
  constant DECIMAL (line 178) | pub const DECIMAL: InputKey = InputKey::new(0x6E);
  constant DIVIDE (line 179) | pub const DIVIDE: InputKey = InputKey::new(0x6F);
  constant F1 (line 181) | pub const F1: InputKey = InputKey::new(0x70);
  constant F2 (line 182) | pub const F2: InputKey = InputKey::new(0x71);
  constant F3 (line 183) | pub const F3: InputKey = InputKey::new(0x72);
  constant F4 (line 184) | pub const F4: InputKey = InputKey::new(0x73);
  constant F5 (line 185) | pub const F5: InputKey = InputKey::new(0x74);
  constant F6 (line 186) | pub const F6: InputKey = InputKey::new(0x75);
  constant F7 (line 187) | pub const F7: InputKey = InputKey::new(0x76);
  constant F8 (line 188) | pub const F8: InputKey = InputKey::new(0x77);
  constant F9 (line 189) | pub const F9: InputKey = InputKey::new(0x78);
  constant F10 (line 190) | pub const F10: InputKey = InputKey::new(0x79);
  constant F11 (line 191) | pub const F11: InputKey = InputKey::new(0x7A);
  constant F12 (line 192) | pub const F12: InputKey = InputKey::new(0x7B);
  constant F13 (line 193) | pub const F13: InputKey = InputKey::new(0x7C);
  constant F14 (line 194) | pub const F14: InputKey = InputKey::new(0x7D);
  constant F15 (line 195) | pub const F15: InputKey = InputKey::new(0x7E);
  constant F16 (line 196) | pub const F16: InputKey = InputKey::new(0x7F);
  constant F17 (line 197) | pub const F17: InputKey = InputKey::new(0x80);
  constant F18 (line 198) | pub const F18: InputKey = InputKey::new(0x81);
  constant F19 (line 199) | pub const F19: InputKey = InputKey::new(0x82);
  constant F20 (line 200) | pub const F20: InputKey = InputKey::new(0x83);
  constant F21 (line 201) | pub const F21: InputKey = InputKey::new(0x84);
  constant F22 (line 202) | pub const F22: InputKey = InputKey::new(0x85);
  constant F23 (line 203) | pub const F23: InputKey = InputKey::new(0x86);
  constant F24 (line 204) | pub const F24: InputKey = InputKey::new(0x87);
  constant NONE (line 211) | pub const NONE: InputKeyMod = InputKeyMod::new(0x00000000);
  constant CTRL (line 212) | pub const CTRL: InputKeyMod = InputKeyMod::new(0x01000000);
  constant ALT (line 213) | pub const ALT: InputKeyMod = InputKeyMod::new(0x02000000);
  constant SHIFT (line 214) | pub const SHIFT: InputKeyMod = InputKeyMod::new(0x04000000);
  constant CTRL_ALT (line 216) | pub const CTRL_ALT: InputKeyMod = InputKeyMod::new(0x03000000);
  constant CTRL_SHIFT (line 217) | pub const CTRL_SHIFT: InputKeyMod = InputKeyMod::new(0x05000000);
  constant ALT_SHIFT (line 218) | pub const ALT_SHIFT: InputKeyMod = InputKeyMod::new(0x06000000);
  constant CTRL_ALT_SHIFT (line 219) | pub const CTRL_ALT_SHIFT: InputKeyMod = InputKeyMod::new(0x07000000);
  type InputMouseState (line 224) | pub enum InputMouseState {
  type InputMouse (line 240) | pub struct InputMouse {
  type Input (line 252) | pub enum Input<'input> {
  type Parser (line 267) | pub struct Parser {
    method new (line 279) | pub fn new() -> Self {
    method parse (line 291) | pub fn parse<'parser, 'vt, 'input>(
  type Stream (line 300) | pub struct Stream<'parser, 'vt, 'input> {
  type Item (line 306) | type Item = Input<'input>;
  method next (line 308) | fn next(&mut self) -> Option<Input<'input>> {
  function handle_bracketed_paste (line 501) | fn handle_bracketed_paste(&mut self) -> Option<Input<'input>> {
  function parse_x10_mouse_coordinates (line 537) | fn parse_x10_mouse_coordinates(&mut self) -> Option<Input<'input>> {
  function parse_modifiers (line 580) | fn parse_modifiers(csi: &vt::Csi) -> InputKeyMod {

FILE: crates/edit/src/json.rs
  constant MAX_DEPTH (line 18) | const MAX_DEPTH: usize = 64;
  type ParseErrorKind (line 21) | pub enum ParseErrorKind {
  type ParseError (line 29) | pub struct ParseError {
    method fmt (line 36) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Value (line 48) | pub enum Value<'a> {
  function is_null (line 58) | pub fn is_null(&self) -> bool {
  function as_bool (line 62) | pub fn as_bool(&self) -> Option<bool> {
  function as_number (line 69) | pub fn as_number(&self) -> Option<f64> {
  function as_str (line 76) | pub fn as_str(&self) -> Option<&'a str> {
  function as_array (line 83) | pub fn as_array(&self) -> Option<&'a [Value<'a>]> {
  function as_object (line 90) | pub fn as_object(&self) -> Option<Object<'a>> {
  type Object (line 99) | pub struct Object<'a> {
  function get (line 104) | pub fn get(&self, key: &str) -> Option<&'a Value<'a>> {
  function get_bool (line 108) | pub fn get_bool(&self, key: &str) -> Option<bool> {
  function get_number (line 112) | pub fn get_number(&self, key: &str) -> Option<f64> {
  function get_str (line 116) | pub fn get_str(&self, key: &str) -> Option<&'a str> {
  function get_array (line 120) | pub fn get_array(&self, key: &str) -> Option<&'a [Value<'a>]> {
  function get_object (line 124) | pub fn get_object(&self, key: &str) -> Option<Object<'a>> {
  function iter (line 128) | pub fn iter(&self) -> impl Iterator<Item = &'a (&'a str, Value<'a>)> {
  function len (line 132) | pub fn len(&self) -> usize {
  function is_empty (line 136) | pub fn is_empty(&self) -> bool {
  function parse (line 141) | pub fn parse<'a>(arena: &'a Arena, input: &str) -> Result<Value<'a>, Par...
  type Parser (line 154) | struct Parser<'a, 'i> {
  function new (line 162) | fn new(arena: &'a Arena, input: &'i str) -> Self {
  function parse_value (line 166) | fn parse_value(&mut self, depth: usize) -> Result<Value<'a>, ParseError> {
  function parse_null (line 192) | fn parse_null(&mut self) -> Result<Value<'a>, ParseError> {
  function parse_true (line 197) | fn parse_true(&mut self) -> Result<Value<'a>, ParseError> {
  function parse_false (line 202) | fn parse_false(&mut self) -> Result<Value<'a>, ParseError> {
  function parse_number (line 207) | fn parse_number(&mut self) -> Result<Value<'a>, ParseError> {
  function parse_string (line 225) | fn parse_string(&mut self) -> Result<Value<'a>, ParseError> {
  function parse_escape (line 265) | fn parse_escape(&mut self, result: &mut BString<'a>) -> Result<(), Parse...
  function parse_unicode_escape (line 295) | fn parse_unicode_escape(&mut self, result: &mut BString<'a>) -> Result<(...
  function parse_hex4 (line 320) | fn parse_hex4(&mut self) -> Result<u32, ParseError> {
  function parse_array (line 335) | fn parse_array(&mut self, depth: usize) -> Result<Value<'a>, ParseError> {
  function parse_object (line 374) | fn parse_object(&mut self, depth: usize) -> Result<Value<'a>, ParseError> {
  function skip_bom (line 424) | fn skip_bom(&mut self) {
  function skip_whitespace_and_comments (line 430) | fn skip_whitespace_and_comments(&mut self) -> Result<(), ParseError> {
  function expect (line 469) | fn expect(&mut self, expected: u8) -> Result<(), ParseError> {
  function expect_str (line 478) | fn expect_str(&mut self, expected: &str) -> Result<(), ParseError> {
  function is_str (line 487) | fn is_str(&self, expected: &str) -> bool {
  function peek (line 491) | fn peek(&self) -> Option<char> {
  function advance (line 495) | fn advance(&mut self, num: usize) {
  function fail (line 500) | fn fail(&self, pos: usize, kind: ParseErrorKind) -> ParseError {
  function test_null (line 518) | fn test_null() {
  function test_bool (line 524) | fn test_bool() {
  function test_number (line 531) | fn test_number() {
  function test_string (line 542) | fn test_string() {
  function test_array (line 550) | fn test_array() {
  function test_object (line 561) | fn test_object() {
  function test_comments (line 570) | fn test_comments() {
  function test_trailing_comma (line 585) | fn test_trailing_comma() {
  function test_nested (line 592) | fn test_nested() {
  function test_max_depth (line 609) | fn test_max_depth() {
  function test_invalid_json (line 622) | fn test_invalid_json() {
  function test_control_chars (line 633) | fn test_control_chars() {
  function test_unicode (line 640) | fn test_unicode() {

FILE: crates/edit/src/oklab.rs
  type StraightRgba (line 15) | pub struct StraightRgba(u32);
    method zero (line 19) | pub const fn zero() -> Self {
    method from_le (line 24) | pub const fn from_le(color: u32) -> Self {
    method from_be (line 29) | pub const fn from_be(color: u32) -> Self {
    method to_ne (line 34) | pub const fn to_ne(self) -> u32 {
    method to_le (line 39) | pub const fn to_le(self) -> u32 {
    method to_be (line 44) | pub const fn to_be(self) -> u32 {
    method red (line 49) | pub const fn red(self) -> u32 {
    method green (line 54) | pub const fn green(self) -> u32 {
    method blue (line 59) | pub const fn blue(self) -> u32 {
    method alpha (line 64) | pub const fn alpha(self) -> u32 {
    method oklab_blend (line 68) | pub fn oklab_blend(self, top: StraightRgba) -> StraightRgba {
    method as_oklab (line 75) | pub fn as_oklab(self) -> Oklab {
  method fmt (line 98) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Oklab (line 105) | pub struct Oklab([f32; 4]);
    method lightness (line 109) | pub const fn lightness(self) -> f32 {
    method a (line 114) | pub const fn a(self) -> f32 {
    method b (line 119) | pub const fn b(self) -> f32 {
    method alpha (line 124) | pub const fn alpha(self) -> f32 {
    method as_rgba (line 128) | pub fn as_rgba(&self) -> StraightRgba {
    method blend (line 157) | pub fn blend(&self, top: &Self) -> Self {
  function srgb_to_linear (line 174) | fn srgb_to_linear(c: u32) -> f32 {
  function linear_to_srgb (line 178) | fn linear_to_srgb(c: f32) -> u32 {
  function cbrtf_est (line 187) | fn cbrtf_est(a: f32) -> f32 {
  constant SRGB_TO_RGB_LUT (line 207) | const SRGB_TO_RGB_LUT: [f32; 256] = [
  function test_blending (line 231) | fn test_blending() {

FILE: crates/edit/src/path.rs
  function normalize (line 11) | pub fn normalize(path: &Path) -> PathBuf {
  function norm (line 54) | fn norm(s: &str) -> OsString {
  function test_unix (line 60) | fn test_unix() {
  function test_windows (line 74) | fn test_windows() {

FILE: crates/edit/src/simd/lines_bwd.rs
  function lines_bwd (line 17) | pub fn lines_bwd(
  function lines_bwd_raw (line 31) | unsafe fn lines_bwd_raw(
  function lines_bwd_fallback (line 47) | unsafe fn lines_bwd_fallback(
  function lines_bwd_dispatch (line 77) | unsafe fn lines_bwd_dispatch(
  function lines_bwd_avx2 (line 90) | unsafe fn lines_bwd_avx2(
  function lines_bwd_dispatch (line 166) | unsafe fn lines_bwd_dispatch(
  function lines_bwd_lasx (line 187) | unsafe fn lines_bwd_lasx(
  function lines_bwd_lsx (line 263) | unsafe fn lines_bwd_lsx(
  function lines_bwd_neon (line 336) | unsafe fn lines_bwd_neon(
  function pseudo_fuzz (line 404) | fn pseudo_fuzz() {
  function reference_lines_bwd (line 426) | fn reference_lines_bwd(
  function seeks_to_start (line 446) | fn seeks_to_start() {

FILE: crates/edit/src/simd/lines_fwd.rs
  function lines_fwd (line 14) | pub fn lines_fwd(
  function lines_fwd_raw (line 29) | unsafe fn lines_fwd_raw(
  function lines_fwd_fallback (line 45) | unsafe fn lines_fwd_fallback(
  function lines_fwd_dispatch (line 77) | unsafe fn lines_fwd_dispatch(
  function lines_fwd_avx2 (line 90) | unsafe fn lines_fwd_avx2(
  function lines_fwd_dispatch (line 173) | unsafe fn lines_fwd_dispatch(
  function lines_fwd_lasx (line 194) | unsafe fn lines_fwd_lasx(
  function lines_fwd_lsx (line 268) | unsafe fn lines_fwd_lsx(
  function lines_fwd_neon (line 339) | unsafe fn lines_fwd_neon(
  function pseudo_fuzz (line 407) | fn pseudo_fuzz() {
  function reference_lines_fwd (line 429) | fn reference_lines_fwd(

FILE: crates/edit/src/simd/memchr2.rs
  function memchr2 (line 13) | pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8], offset: usize)...
  function memchr2_raw (line 23) | unsafe fn memchr2_raw(needle1: u8, needle2: u8, beg: *const u8, end: *co...
  function memchr2_fallback (line 34) | unsafe fn memchr2_fallback(
  function memchr2_dispatch (line 65) | unsafe fn memchr2_dispatch(needle1: u8, needle2: u8, beg: *const u8, end...
  function memchr2_avx2 (line 75) | unsafe fn memchr2_avx2(needle1: u8, needle2: u8, mut beg: *const u8, end...
  function memchr2_dispatch (line 106) | unsafe fn memchr2_dispatch(needle1: u8, needle2: u8, beg: *const u8, end...
  function memchr2_lasx (line 122) | unsafe fn memchr2_lasx(needle1: u8, needle2: u8, mut beg: *const u8, end...
  function memchr2_lsx (line 157) | unsafe fn memchr2_lsx(needle1: u8, needle2: u8, mut beg: *const u8, end:...
  function memchr2_neon (line 189) | unsafe fn memchr2_neon(needle1: u8, needle2: u8, mut beg: *const u8, end...
  function test_empty (line 233) | fn test_empty() {
  function test_basic (line 238) | fn test_basic() {
  function test_with_offset (line 250) | fn test_with_offset() {
  function test_page_boundary (line 264) | fn test_page_boundary() {

FILE: crates/edit/src/simd/mod.rs
  function make_rng (line 17) | pub fn make_rng() -> impl FnMut() -> usize {
  function generate_random_text (line 25) | pub fn generate_random_text(len: usize) -> String {
  function count_lines (line 38) | pub fn count_lines(text: &str) -> usize {

FILE: crates/edit/src/sys/unix.rs
  type State (line 23) | struct State {
  function sigwinch_handler (line 44) | extern "C" fn sigwinch_handler(_: libc::c_int) {
  function init (line 50) | pub fn init() -> Deinit {
  function switch_modes (line 54) | pub fn switch_modes() -> io::Result<()> {
  type Deinit (line 126) | pub struct Deinit;
  method drop (line 129) | fn drop(&mut self) {
  function inject_window_size_into_stdin (line 140) | pub fn inject_window_size_into_stdin() {
  function get_window_size (line 146) | fn get_window_size() -> (u16, u16) {
  function read_stdin (line 173) | pub fn read_stdin(arena: &Arena, mut timeout: time::Duration) -> Option<...
  function write_stdout (line 293) | pub fn write_stdout(text: &str) {
  function set_tty_nonblocking (line 326) | fn set_tty_nonblocking(nonblock: bool) {
  function open_stdin_if_redirected (line 336) | pub fn open_stdin_if_redirected() -> Option<File> {
  type FileId (line 348) | pub struct FileId {
  function file_id (line 354) | pub fn file_id(file: Option<&File>, path: &Path) -> io::Result<FileId> {
  function load_library (line 368) | unsafe fn load_library(name: *const c_char) -> io::Result<NonNull<c_void...
  function get_proc_address (line 383) | pub unsafe fn get_proc_address<T>(handle: NonNull<c_void>, name: *const ...
  type LibIcu (line 394) | pub struct LibIcu {
  function load_icu (line 399) | pub fn load_icu() -> io::Result<LibIcu> {
  function icu_detect_renaming_suffix (line 434) | pub fn icu_detect_renaming_suffix(arena: &Arena, handle: NonNull<c_void>...
  function icu_add_renaming_suffix (line 492) | pub fn icu_add_renaming_suffix<'a, 'b, 'r>(
  function preferred_languages (line 518) | pub fn preferred_languages(arena: &Arena) -> BVec<'_, BString<'_>> {
  function errno (line 547) | fn errno() -> c_int {
  function last_os_error (line 559) | fn last_os_error() -> io::Error {
  function from_raw_os_error (line 565) | fn from_raw_os_error(code: c_int) -> io::Error {
  function check_int_return (line 569) | fn check_int_return(ret: libc::c_int) -> io::Result<libc::c_int> {

FILE: crates/edit/src/sys/windows.rs
  type ReadConsoleInputExW (line 51) | type ReadConsoleInputExW = unsafe extern "system" fn(
  function read_console_input_ex_placeholder (line 59) | unsafe extern "system" fn read_console_input_ex_placeholder(
  constant CONSOLE_READ_NOWAIT (line 69) | const CONSOLE_READ_NOWAIT: u16 = 0x0002;
  constant INVALID_CONSOLE_MODE (line 70) | const INVALID_CONSOLE_MODE: u32 = u32::MAX;
  type State (line 72) | struct State {
  function console_ctrl_handler (line 98) | extern "system" fn console_ctrl_handler(_ctrl_type: u32) -> BOOL {
  function init (line 107) | pub fn init() -> Deinit {
  function switch_modes (line 119) | pub fn switch_modes() -> io::Result<()> {
  type Deinit (line 195) | pub struct Deinit;
  method drop (line 198) | fn drop(&mut self) {
  function inject_window_size_into_stdin (line 224) | pub fn inject_window_size_into_stdin() {
  function get_console_size (line 230) | fn get_console_size() -> Option<Size> {
  function read_stdin (line 251) | pub fn read_stdin(arena: &Arena, mut timeout: time::Duration) -> Option<...
  function write_stdout (line 400) | pub fn write_stdout(text: &str) {
  function open_stdin_if_redirected (line 423) | pub fn open_stdin_if_redirected() -> Option<File> {
  function drives (line 431) | pub fn drives() -> impl Iterator<Item = char> {
  type FileId (line 447) | pub enum FileId {
  method eq (line 453) | fn eq(&self, other: &Self) -> bool {
  function file_id (line 471) | pub fn file_id(file: Option<&File>, path: &Path) -> io::Result<FileId> {
  function file_id_from_handle (line 480) | fn file_id_from_handle(file: &File) -> io::Result<FileId> {
  function canonicalize (line 497) | pub fn canonicalize(path: &Path) -> std::io::Result<PathBuf> {
  function get_module (line 512) | unsafe fn get_module(name: *const u16) -> io::Result<NonNull<c_void>> {
  function load_library (line 516) | unsafe fn load_library(name: *const u16) -> io::Result<NonNull<c_void>> {
  function get_proc_address (line 534) | pub unsafe fn get_proc_address<T>(handle: NonNull<c_void>, name: *const ...
  type LibIcu (line 541) | pub struct LibIcu {
  function load_icu (line 546) | pub fn load_icu() -> io::Result<LibIcu> {
  function preferred_languages (line 578) | pub fn preferred_languages<'a>(arena: &'a Arena) -> BVec<'a, &'a str> {
  function last_os_error (line 620) | fn last_os_error() -> io::Error {
  function check_bool_return (line 624) | fn check_bool_return(ret: BOOL) -> io::Result<()> {
  function check_ptr_return (line 628) | fn check_ptr_return<T>(ret: *mut T) -> io::Result<NonNull<T>> {

FILE: crates/edit/src/tui.rs
  constant ROOT_ID (line 165) | const ROOT_ID: u64 = 0x14057B7EF767814F;
  constant SHIFT_TAB (line 166) | const SHIFT_TAB: InputKey = vk::TAB.with_modifiers(kbmod::SHIFT);
  constant KBMOD_FOR_WORD_NAV (line 167) | const KBMOD_FOR_WORD_NAV: InputKeyMod =
  type Input (line 170) | type Input<'input> = input::Input<'input>;
  type InputKey (line 171) | type InputKey = input::InputKey;
  type InputMouseState (line 172) | type InputMouseState = input::InputMouseState;
  type CachedTextBuffer (line 177) | struct CachedTextBuffer {
  type TextBufferPayload (line 185) | enum TextBufferPayload<'a> {
  type ModifierTranslations (line 192) | pub struct ModifierTranslations {
  type Anchor (line 200) | pub enum Anchor {
  type FloatSpec (line 212) | pub struct FloatSpec {
  type ListSelection (line 225) | pub enum ListSelection {
  type Position (line 237) | pub enum Position {
  type Overflow (line 252) | pub enum Overflow {
  type ButtonStyle (line 266) | pub struct ButtonStyle {
    method accelerator (line 276) | pub fn accelerator(self, char: char) -> Self {
    method checked (line 280) | pub fn checked(self, checked: bool) -> Self {
    method bracketed (line 284) | pub fn bracketed(self, bracketed: bool) -> Self {
  method default (line 290) | fn default() -> Self {
  type Tui (line 305) | pub struct Tui {
    method new (line 377) | pub fn new() -> io::Result<Self> {
    method setup_indexed_colors (line 430) | pub fn setup_indexed_colors(&mut self, colors: [StraightRgba; INDEXED_...
    method setup_modifier_translations (line 435) | pub fn setup_modifier_translations(&mut self, translations: ModifierTr...
    method set_floater_default_bg (line 440) | pub fn set_floater_default_bg(&mut self, color: StraightRgba) {
    method set_floater_default_fg (line 445) | pub fn set_floater_default_fg(&mut self, color: StraightRgba) {
    method set_modal_default_bg (line 450) | pub fn set_modal_default_bg(&mut self, color: StraightRgba) {
    method set_modal_default_fg (line 455) | pub fn set_modal_default_fg(&mut self, color: StraightRgba) {
    method read_timeout (line 461) | pub fn read_timeout(&mut self) -> time::Duration {
    method size (line 466) | pub fn size(&self) -> Size {
    method indexed (line 474) | pub fn indexed(&self, index: IndexedColor) -> StraightRgba {
    method indexed_alpha (line 481) | pub fn indexed_alpha(
    method contrasted (line 492) | pub fn contrasted(&self, color: StraightRgba) -> StraightRgba {
    method clipboard_ref (line 497) | pub fn clipboard_ref(&self) -> &Clipboard {
    method clipboard_mut (line 502) | pub fn clipboard_mut(&mut self) -> &mut Clipboard {
    method create_context (line 507) | pub fn create_context<'a, 'input>(
    method report_context_completion (line 718) | fn report_context_completion<'a>(&'a mut self, ctx: &mut Context<'a, '...
    method build_node_path (line 817) | fn build_node_path(node: Option<&NodeCell>, path: &mut Vec<u64>) {
    method clean_node_path (line 834) | fn clean_node_path(path: &mut Vec<u64>) {
    method needs_settling (line 839) | pub fn needs_settling(&mut self) -> bool {
    method needs_more_settling (line 843) | fn needs_more_settling(&mut self) {
    method render (line 852) | pub fn render<'a>(&mut self, arena: &'a Arena) -> BString<'a> {
    method render_node (line 863) | fn render_node(&mut self, node: &mut Node) {
    method render_styled_text (line 1051) | fn render_styled_text(
    method debug_layout (line 1145) | pub fn debug_layout<'a>(&mut self, arena: &'a Arena) -> BString<'a> {
    method was_mouse_down_on_node (line 1254) | fn was_mouse_down_on_node(&self, id: u64) -> bool {
    method was_mouse_down_on_subtree (line 1258) | fn was_mouse_down_on_subtree(&self, node: &Node) -> bool {
    method is_node_focused (line 1262) | fn is_node_focused(&self, id: u64) -> bool {
    method is_subtree_focused (line 1267) | fn is_subtree_focused(&self, node: &Node) -> bool {
    method is_subtree_focused_alt (line 1271) | fn is_subtree_focused_alt(&self, id: u64, depth: usize) -> bool {
    method pop_focusable_node (line 1275) | fn pop_focusable_node(&mut self, pop_minimum: usize) -> bool {
    method scroll_to_focused (line 1317) | fn scroll_to_focused(&mut self) -> bool {
  type Context (line 1352) | pub struct Context<'a, 'input> {
  method drop (line 1376) | fn drop(&mut self) {
  function arena (line 1384) | pub fn arena(&self) -> &'a Arena {
  function size (line 1395) | pub fn size(&self) -> Size {
  function indexed (line 1401) | pub fn indexed(&self, index: IndexedColor) -> StraightRgba {
  function indexed_alpha (line 1408) | pub fn indexed_alpha(
  function contrasted (line 1419) | pub fn contrasted(&self, color: StraightRgba) -> StraightRgba {
  function clipboard_ref (line 1424) | pub fn clipboard_ref(&self) -> &Clipboard {
  function clipboard_mut (line 1429) | pub fn clipboard_mut(&mut self) -> &mut Clipboard {
  function needs_rerender (line 1434) | pub fn needs_rerender(&mut self) {
  function block_begin (line 1441) | pub fn block_begin(&mut self, classname: &'static str) {
  function block_end (line 1469) | pub fn block_end(&mut self) {
  function block_end_move_focus (line 1474) | fn block_end_move_focus(&mut self) {
  function next_block_id_mixin (line 1554) | pub fn next_block_id_mixin(&mut self, id: u64) {
  function attr_focusable (line 1558) | fn attr_focusable(&mut self) {
  function focus_on_first_present (line 1565) | pub fn focus_on_first_present(&mut self) {
  function steal_focus (line 1577) | pub fn steal_focus(&mut self) {
  function steal_focus_for (line 1581) | fn steal_focus_for(&mut self, node: &NodeCell<'a>) {
  function toss_focus_up (line 1589) | pub fn toss_focus_up(&mut self) {
  function inherit_focus (line 1596) | pub fn inherit_focus(&mut self) {
  function attr_focus_well (line 1618) | pub fn attr_focus_well(&mut self) {
  function attr_intrinsic_size (line 1625) | pub fn attr_intrinsic_size(&mut self, size: Size) {
  function attr_float (line 1633) | pub fn attr_float(&mut self, spec: FloatSpec) {
  function attr_border (line 1662) | pub fn attr_border(&mut self) {
  function attr_position (line 1668) | pub fn attr_position(&mut self, align: Position) {
  function attr_padding (line 1674) | pub fn attr_padding(&mut self, padding: Rect) {
  function normalize_rect (line 1679) | fn normalize_rect(rect: Rect) -> Rect {
  function attr_background_rgba (line 1689) | pub fn attr_background_rgba(&mut self, bg: StraightRgba) {
  function attr_foreground_rgba (line 1695) | pub fn attr_foreground_rgba(&mut self, fg: StraightRgba) {
  function attr_reverse (line 1702) | pub fn attr_reverse(&mut self) {
  function consume_shortcut (line 1709) | pub fn consume_shortcut(&mut self, shortcut: InputKey) -> bool {
  function keyboard_input (line 1720) | pub fn keyboard_input(&self) -> Option<InputKey> {
  function set_input_consumed (line 1725) | pub fn set_input_consumed(&mut self) {
  function set_input_consumed_unchecked (line 1731) | fn set_input_consumed_unchecked(&mut self) {
  function was_mouse_down (line 1736) | pub fn was_mouse_down(&mut self) -> bool {
  function contains_mouse_down (line 1742) | pub fn contains_mouse_down(&mut self) -> bool {
  function is_focused (line 1748) | pub fn is_focused(&mut self) -> bool {
  function contains_focus (line 1754) | pub fn contains_focus(&mut self) -> bool {
  function modal_begin (line 1760) | pub fn modal_begin(&mut self, classname: &'static str, title: &str) {
  function modal_end (line 1787) | pub fn modal_end(&mut self) -> bool {
  function table_begin (line 1804) | pub fn table_begin(&mut self, classname: &'static str) {
  function table_set_columns (line 1816) | pub fn table_set_columns(&mut self, columns: &[CoordType]) {
  function table_set_cell_gap (line 1827) | pub fn table_set_cell_gap(&mut self, cell_gap: Size) {
  function table_next_row (line 1837) | pub fn table_next_row(&mut self) {
  function table_end_row (line 1863) | fn table_end_row(&mut self) {
  function table_end (line 1868) | pub fn table_end(&mut self) {
  function table_move_focus (line 1882) | fn table_move_focus(&mut self, prev_key: InputKey, next_key: InputKey) {
  function label (line 1942) | pub fn label(&mut self, classname: &'static str, text: &str) {
  function styled_label_begin (line 1964) | pub fn styled_label_begin(&mut self, classname: &'static str) {
  function styled_label_set_foreground (line 1974) | pub fn styled_label_set_foreground(&mut self, fg: StraightRgba) {
  function styled_label_set_attributes (line 1990) | pub fn styled_label_set_attributes(&mut self, attr: Attributes) {
  function styled_label_add_text (line 2006) | pub fn styled_label_add_text(&mut self, text: &str) {
  function styled_label_end (line 2016) | pub fn styled_label_end(&mut self) {
  function attr_overflow (line 2034) | pub fn attr_overflow(&mut self, overflow: Overflow) {
  function button (line 2045) | pub fn button(&mut self, classname: &'static str, text: &str, style: But...
  function checkbox (line 2056) | pub fn checkbox(&mut self, classname: &'static str, text: &str, checked:...
  function button_activated (line 2074) | fn button_activated(&mut self) -> bool {
  function editline (line 2090) | pub fn editline(&mut self, classname: &'static str, text: &mut dyn Write...
  function textarea (line 2095) | pub fn textarea(&mut self, classname: &'static str, tb: RcTextBuffer) {
  function textarea_internal (line 2099) | fn textarea_internal(&mut self, classname: &'static str, payload: TextBu...
  function textarea_handle_input (line 2220) | fn textarea_handle_input(
  function textarea_make_cursor_visible (line 2756) | fn textarea_make_cursor_visible(&self, tc: &mut TextareaContent, node_pr...
  function textarea_adjust_scroll_offset (line 2777) | fn textarea_adjust_scroll_offset(&self, tc: &mut TextareaContent) {
  function scrollarea_begin (line 2795) | pub fn scrollarea_begin(&mut self, classname: &'static str, intrinsic_si...
  function scrollarea_scroll_to (line 2822) | pub fn scrollarea_scroll_to(&mut self, pos: Point) {
  function scrollarea_end (line 2832) | pub fn scrollarea_end(&mut self) {
  function list_begin (line 2918) | pub fn list_begin(&mut self, classname: &'static str) {
  function list_item (line 2940) | pub fn list_item(&mut self, select: bool, text: &str) -> ListSelection {
  function styled_list_item_begin (line 2948) | pub fn styled_list_item_begin(&mut self) {
  function styled_list_item_end (line 2959) | pub fn styled_list_item_end(&mut self, select: bool) -> ListSelection {
  function list_item_steal_focus (line 3019) | pub fn list_item_steal_focus(&mut self) {
  function list_end (line 3032) | pub fn list_end(&mut self) {
  function menubar_begin (line 3140) | pub fn menubar_begin(&mut self) {
  function menubar_menu_begin (line 3149) | pub fn menubar_menu_begin(&mut self, text: &str, accelerator: char) -> b...
  function menubar_menu_button (line 3200) | pub fn menubar_menu_button(
  function menubar_menu_checkbox (line 3211) | pub fn menubar_menu_checkbox(
  function menubar_menu_end (line 3251) | pub fn menubar_menu_end(&mut self) {
  function menubar_end (line 3279) | pub fn menubar_end(&mut self) {
  function button_label (line 3285) | fn button_label(&mut self, classname: &'static str, text: &str, style: B...
  function menubar_shortcut (line 3343) | fn menubar_shortcut(&mut self, shortcut: InputKey) {
  type VisitControl (line 3372) | enum VisitControl {
  type Tree (line 3379) | struct Tree<'a> {
  function new (line 3393) | fn new(arena: &'a Arena) -> Self {
  function alloc_node (line 3413) | fn alloc_node(arena: &'a Arena) -> &'a NodeCell<'a> {
  function push_child (line 3418) | fn push_child(&mut self, node: &'a NodeCell<'a>) {
  function move_node_to_root (line 3455) | fn move_node_to_root(&mut self, node: &'a NodeCell<'a>, anchor: Option<&...
  function pop_stack (line 3491) | fn pop_stack(&mut self) {
  function iterate_siblings (line 3499) | fn iterate_siblings(
  function iterate_siblings_rev (line 3509) | fn iterate_siblings_rev(
  function iterate_roots (line 3519) | fn iterate_roots(&self) -> impl Iterator<Item = &'a NodeCell<'a>> + use<...
  function iterate_roots_rev (line 3523) | fn iterate_roots_rev(&self) -> impl Iterator<Item = &'a NodeCell<'a>> + ...
  function visit_all (line 3531) | fn visit_all<T: FnMut(&'a NodeCell<'a>) -> VisitControl>(
  type NodeMap (line 3585) | struct NodeMap<'a> {
  method default (line 3592) | fn default() -> Self {
  function new (line 3599) | fn new(arena: &'a Arena, tree: &Tree<'a>) -> Self {
  function get (line 3632) | fn get(&self, id: u64) -> Option<&'a NodeCell<'a>> {
  type FloatAttributes (line 3647) | struct FloatAttributes {
  type NodeAttributes (line 3658) | struct NodeAttributes {
  type ListContent (line 3672) | struct ListContent<'a> {
  type TableContent (line 3679) | struct TableContent<'a> {
  type StyledTextChunk (line 3685) | struct StyledTextChunk {
  constant INVALID_STYLED_TEXT_CHUNK (line 3691) | const INVALID_STYLED_TEXT_CHUNK: StyledTextChunk =
  type TextContent (line 3695) | struct TextContent<'a> {
  type TextareaContent (line 3702) | struct TextareaContent<'a> {
  type ScrollareaContent (line 3718) | struct ScrollareaContent {
  type NodeContent (line 3726) | enum NodeContent<'a> {
  type NodeSiblings (line 3739) | struct NodeSiblings<'a> {
  constant PREV (line 3745) | const PREV: usize = 0;
  constant NEXT (line 3746) | const NEXT: usize = 1;
  function get (line 3748) | fn get(&self, off: usize) -> Option<&'a NodeCell<'a>> {
  type NodeChildren (line 3759) | struct NodeChildren<'a> {
  constant FIRST (line 3765) | const FIRST: usize = 0;
  constant LAST (line 3766) | const LAST: usize = 1;
  function get (line 3768) | fn get(&self, off: usize) -> Option<&'a NodeCell<'a>> {
  type NodeCell (line 3777) | type NodeCell<'a> = SemiRefCell<Node<'a>>;
  type Node (line 3783) | struct Node<'a> {
  function outer_to_inner (line 3810) | fn outer_to_inner(&self, mut outer: Rect) -> Rect {
  function intrinsic_to_outer (line 3825) | fn intrinsic_to_outer(&self) -> Size {
  function compute_intrinsic_size (line 3844) | fn compute_intrinsic_size(&mut self, arena: &'a Arena) {
  function layout_children (line 3932) | fn layout_children(&mut self, clip: Rect) {

FILE: crates/edit/src/unicode/measurement.rs
  function setup_ambiguous_width (line 19) | pub fn setup_ambiguous_width(ambiguous_width: CoordType) {
  function ambiguous_width (line 24) | fn ambiguous_width() -> usize {
  type Cursor (line 35) | pub struct Cursor {
  type MeasurementConfig (line 60) | pub struct MeasurementConfig<'doc> {
  function new (line 69) | pub fn new(buffer: &'doc dyn ReadableDocument) -> Self {
  function with_cursor (line 77) | pub fn with_cursor(mut self, cursor: Cursor) -> Self {
  function with_tab_size (line 85) | pub fn with_tab_size(mut self, tab_size: CoordType) -> Self {
  function with_word_wrap_column (line 93) | pub fn with_word_wrap_column(mut self, word_wrap_column: CoordType) -> S...
  function goto_offset (line 103) | pub fn goto_offset(&mut self, offset: usize) -> Cursor {
  function goto_logical (line 114) | pub fn goto_logical(&mut self, logical_target: Point) -> Cursor {
  function goto_visual (line 125) | pub fn goto_visual(&mut self, visual_target: Point) -> Cursor {
  function cursor (line 130) | pub fn cursor(&self) -> Cursor {
  function measure_forward (line 142) | fn measure_forward(
  function calc_target_x (line 471) | fn calc_target_x(target: Point, pos_y: CoordType) -> CoordType {
  function skip_newline (line 484) | pub fn skip_newline(text: &[u8], mut offset: usize) -> usize {
  function strip_newline (line 501) | pub fn strip_newline(mut text: &[u8]) -> &[u8] {
  type ChunkedDoc (line 516) | struct ChunkedDoc<'a>(&'a [&'a [u8]]);
  method read_forward (line 519) | fn read_forward(&self, mut off: usize) -> &[u8] {
  method read_backward (line 529) | fn read_backward(&self, mut off: usize) -> &[u8] {
  function test_measure_forward_newline_start (line 541) | fn test_measure_forward_newline_start() {
  function test_measure_forward_clipped_wide_char (line 557) | fn test_measure_forward_clipped_wide_char() {
  function test_measure_forward_word_wrap (line 572) | fn test_measure_forward_word_wrap() {
  function test_measure_forward_tabs (line 676) | fn test_measure_forward_tabs() {
  function test_measure_forward_chunk_boundaries (line 693) | fn test_measure_forward_chunk_boundaries() {
  function test_exact_wrap (line 706) | fn test_exact_wrap() {
  function test_force_wrap (line 777) | fn test_force_wrap() {
  function test_force_wrap_wide (line 855) | fn test_force_wrap_wide() {
  function test_force_wrap_column (line 877) | fn test_force_wrap_column() {
  function test_any_wrap (line 923) | fn test_any_wrap() {
  function test_any_wrap_wide (line 956) | fn test_any_wrap_wide() {
  function test_wrap_tab (line 975) | fn test_wrap_tab() {
  function test_crlf (line 1021) | fn test_crlf() {
  function test_wrapped_cursor_can_seek_backward (line 1037) | fn test_wrapped_cursor_can_seek_backward() {
  function test_strip_newline (line 1057) | fn test_strip_newline() {

FILE: crates/edit/src/unicode/tables.rs
  constant STAGE0 (line 6) | const STAGE0: [u16; 544] = [
  constant STAGE1 (line 43) | const STAGE1: [u16; 2355] = [
  constant STAGE2 (line 83) | const STAGE2: [u16; 4079] = [
  constant STAGE3 (line 596) | const STAGE3: [u16; 1752] = [
  constant GRAPHEME_JOIN_RULES (line 1037) | const GRAPHEME_JOIN_RULES: [[u32; 16]; 2] = [
  constant LINE_BREAK_JOIN_RULES (line 1076) | const LINE_BREAK_JOIN_RULES: [u32; 25] = [
  function ucd_grapheme_cluster_lookup (line 1104) | pub fn ucd_grapheme_cluster_lookup(cp: char) -> usize {
  function ucd_grapheme_cluster_joins (line 1117) | pub fn ucd_grapheme_cluster_joins(state: u32, lead: usize, trail: usize)...
  function ucd_grapheme_cluster_joins_done (line 1126) | pub fn ucd_grapheme_cluster_joins_done(state: u32) -> bool {
  function ucd_grapheme_cluster_character_width (line 1130) | pub fn ucd_grapheme_cluster_character_width(val: usize, ambiguous_width:...
  function ucd_line_break_joins (line 1139) | pub fn ucd_line_break_joins(lead: usize, trail: usize) -> bool {
  function ucd_start_of_text_properties (line 1148) | pub fn ucd_start_of_text_properties() -> usize {
  function ucd_tab_properties (line 1152) | pub fn ucd_tab_properties() -> usize {
  function ucd_linefeed_properties (line 1156) | pub fn ucd_linefeed_properties() -> usize {
  function cold_path (line 1161) | fn cold_path() {}

FILE: crates/edit/src/vt.rs
  type Token (line 13) | pub enum Token<'parser, 'input> {
  type State (line 40) | enum State {
  type Csi (line 52) | pub struct Csi {
  type Parser (line 68) | pub struct Parser {
    method new (line 76) | pub fn new() -> Self {
    method read_timeout (line 88) | pub fn read_timeout(&mut self) -> std::time::Duration {
    method parse (line 104) | pub fn parse<'parser, 'input>(
  type Stream (line 115) | pub struct Stream<'parser, 'input> {
  function input (line 123) | pub fn input(&self) -> &'input str {
  function offset (line 128) | pub fn offset(&self) -> usize {
  function done (line 133) | pub fn done(&self) -> bool {
  function next_char (line 138) | pub fn next_char(&mut self) -> char {
  function next (line 150) | pub fn next(&mut self) -> Option<Token<'_, 'input>> {

FILE: crates/stdext/src/alloc.rs
  type Allocator (line 7) | pub trait Allocator {
    method realloc (line 12) | unsafe fn realloc(
    method dealloc (line 23) | unsafe fn dealloc(&self, ptr: NonNull<u8>, size: usize, align: usize);
    method realloc (line 29) | unsafe fn realloc(
    method dealloc (line 52) | unsafe fn dealloc(&self, ptr: NonNull<u8>, size: usize, align: usize) {
  type GlobalAllocator (line 26) | pub struct GlobalAllocator;

FILE: crates/stdext/src/arena/debug.rs
  type Arena (line 38) | pub enum Arena {
    method empty (line 62) | pub const fn empty() -> Self {
    method new (line 66) | pub fn new(capacity: usize) -> io::Result<Self> {
    method delegated (line 70) | pub(super) fn delegated(delegate: &release::Arena) -> Self {
    method delegate_target (line 77) | pub(super) fn delegate_target(&self) -> &release::Arena {
    method delegate_target_unchecked (line 91) | pub(super) fn delegate_target_unchecked(&self) -> &release::Arena {
  method drop (line 46) | fn drop(&mut self) {
  method default (line 56) | fn default() -> Self {
  type Target (line 100) | type Target = release::Arena;
  method deref (line 103) | fn deref(&self) -> &Self::Target {
  method realloc (line 109) | unsafe fn realloc(
  method dealloc (line 119) | unsafe fn dealloc(&self, _ptr: NonNull<u8>, _size: usize, _align: usize) {}

FILE: crates/stdext/src/arena/fs.rs
  function read_to_vec (line 13) | pub fn read_to_vec<P: AsRef<Path>>(arena: &'_ Arena, path: P) -> io::Res...
  function read_to_string (line 43) | pub fn read_to_string<P: AsRef<Path>>(arena: &Arena, path: P) -> io::Res...
  function file_read_uninit (line 53) | fn file_read_uninit<T: Read>(file: &mut T, buf: &mut [MaybeUninit<u8>]) ...

FILE: crates/stdext/src/arena/release.rs
  constant ALLOC_CHUNK_SIZE (line 15) | const ALLOC_CHUNK_SIZE: usize = 32 * 1024;
  constant ALLOC_CHUNK_SIZE (line 17) | const ALLOC_CHUNK_SIZE: usize = 64 * 1024;
  type Arena (line 44) | pub struct Arena {
    method empty (line 56) | pub const fn empty() -> Self {
    method new (line 68) | pub fn new(capacity: usize) -> io::Result<Self> {
    method is_empty (line 83) | pub fn is_empty(&self) -> bool {
    method offset (line 87) | pub fn offset(&self) -> usize {
    method reset (line 97) | pub unsafe fn reset(&self, to: usize) {
    method alloc_raw (line 109) | pub(super) fn alloc_raw(&self, bytes: usize, alignment: usize) -> NonN...
    method alloc_raw_bump (line 132) | fn alloc_raw_bump(&self, beg: usize, end: usize) -> NonNull<[u8]> {
    method alloc_uninit (line 161) | pub fn alloc_uninit<T>(&self) -> &mut MaybeUninit<T> {
    method alloc_uninit_array (line 170) | pub fn alloc_uninit_array<const N: usize, T>(&self) -> &mut [MaybeUnin...
    method alloc_uninit_slice (line 179) | pub fn alloc_uninit_slice<T>(&self, count: usize) -> &mut [MaybeUninit...
    method alloc_slice (line 189) | pub fn alloc_slice<T: Copy>(&self, count: usize, value: T) -> &mut [T] {
  method drop (line 197) | fn drop(&mut self) {
  method default (line 205) | fn default() -> Self {
  method realloc (line 211) | unsafe fn realloc(
  method dealloc (line 240) | unsafe fn dealloc(&self, _ptr: NonNull<u8>, _size: usize, _align: usize) {}

FILE: crates/stdext/src/arena/scratch.rs
  type ScratchArena (line 18) | pub struct ScratchArena<'a> {
  type ScratchArena (line 25) | pub struct ScratchArena<'a> {
  function new (line 32) | fn new(arena: &'a release::Arena) -> Self {
  function new (line 40) | fn new(arena: &'a release::Arena) -> Self {
  method drop (line 47) | fn drop(&mut self) {
  type Target (line 54) | type Target = debug::Arena;
  method deref (line 56) | fn deref(&self) -> &Self::Target {
  type Target (line 63) | type Target = Arena;
  method deref (line 65) | fn deref(&self) -> &Self::Target {
  function init (line 79) | pub fn init(capacity: usize) -> io::Result<()> {
  function scratch_arena (line 110) | pub fn scratch_arena(conflict: Option<&Arena>) -> ScratchArena<'static> {
  function init (line 137) | pub fn init(capacity: usize) -> io::Result<()> {
  function scratch_arena (line 146) | pub fn scratch_arena(conflict: Option<&Arena>) -> ScratchArena<'static> {

FILE: crates/stdext/src/collections/string.rs
  type BString (line 14) | pub struct BString<'a> {
  function empty (line 21) | pub const fn empty() -> Self {
  function from_std_string (line 26) | pub fn from_std_string(str: String) -> Self {
  function into_std_string (line 31) | pub fn into_std_string(self) -> String {
  function from_utf8 (line 36) | pub fn from_utf8(vec: BVec<'a, u8>) -> Result<Self, Utf8Error> {
  function from_utf8_lossy (line 42) | pub fn from_utf8_lossy(alloc: &'a dyn Allocator, vec: BVec<'a, u8>) -> S...
  function from_utf8_unchecked (line 79) | pub unsafe fn from_utf8_unchecked(vec: BVec<'a, u8>) -> Self {
  function from_str (line 84) | pub fn from_str(alloc: &'a dyn Allocator, s: &str) -> Self {
  function from_utf16_lossy (line 91) | pub fn from_utf16_lossy(alloc: &'a dyn Allocator, string: &[u16]) -> Self {
  function len (line 99) | pub fn len(&self) -> usize {
  function capacity (line 105) | pub fn capacity(&self) -> usize {
  function is_empty (line 111) | pub fn is_empty(&self) -> bool {
  function as_bytes (line 117) | pub fn as_bytes(&self) -> &[u8] {
  function as_str (line 123) | pub fn as_str(&self) -> &str {
  function as_mut_str (line 129) | pub fn as_mut_str(&mut self) -> &mut str {
  function as_mut_vec (line 137) | pub unsafe fn as_mut_vec(&mut self) -> &mut BVec<'a, u8> {
  function leak (line 143) | pub fn leak(self) -> &'a mut str {
  function reserve (line 149) | pub fn reserve(&mut self, alloc: &'a dyn Allocator, additional: usize) {
  function reserve_exact (line 155) | pub fn reserve_exact(&mut self, arena: &'a dyn Allocator, additional: us...
  function push (line 160) | pub fn push(&mut self, alloc: &'a dyn Allocator, ch: char) {
  function clear (line 171) | pub fn clear(&mut self) {
  function formatter (line 177) | pub fn formatter<A>(&mut self, alloc: &'a A) -> BStringFormatter<'_, 'a, A>
  function push_str (line 185) | pub fn push_str(&mut self, alloc: &'a dyn Allocator, string: &str) {
  function push_utf16_lossy (line 190) | pub fn push_utf16_lossy(&mut self, alloc: &'a dyn Allocator, string: &[u...
  function push_repeat (line 200) | pub fn push_repeat(&mut self, alloc: &'a dyn Allocator, ch: char, total_...
  function extend (line 229) | pub fn extend<I>(&mut self, alloc: &'a dyn Allocator, iter: I)
  function replace_range (line 240) | pub fn replace_range<R: RangeBounds<usize>>(
  function replace_once_in_place (line 261) | pub fn replace_once_in_place(&mut self, alloc: &'a dyn Allocator, old: &...
  method default (line 269) | fn default() -> Self {
  type Target (line 275) | type Target = str;
  method deref (line 278) | fn deref(&self) -> &str {
  method deref_mut (line 285) | fn deref_mut(&mut self) -> &mut str {
  function eq (line 292) | fn eq(&self, other: &BString) -> bool {
  function eq (line 301) | fn eq(&self, other: &&str) -> bool {
  method partial_cmp (line 308) | fn partial_cmp(&self, other: &BString) -> Option<std::cmp::Ordering> {
  method cmp (line 315) | fn cmp(&self, other: &BString) -> std::cmp::Ordering {
  function fmt (line 321) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function fmt (line 327) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type BStringFormatter (line 336) | pub struct BStringFormatter<'s, 'a, A> {
  function write_str (line 346) | fn write_str(&mut self, s: &str) -> fmt::Result {
  function write_char (line 352) | fn write_char(&mut self, c: char) -> fmt::Result {

FILE: crates/stdext/src/collections/vec.rs
  type BVec (line 24) | pub struct BVec<'a, T> {
  function empty (line 39) | pub const fn empty() -> Self {
  function from_slice (line 50) | pub fn from_slice(slice: &'a mut [T]) -> Self {
  function from_std_vec (line 63) | pub fn from_std_vec(vec: Vec<T>) -> Self {
  function into_std_vec (line 85) | pub fn into_std_vec(self) -> Vec<T> {
  function len (line 97) | pub fn len(&self) -> usize {
  function capacity (line 103) | pub fn capacity(&self) -> usize {
  function is_empty (line 109) | pub fn is_empty(&self) -> bool {
  function set_len (line 120) | pub unsafe fn set_len(&mut self, new_len: usize) {
  function truncate (line 126) | pub fn truncate(&mut self, len: usize) {
  function as_ptr (line 140) | pub fn as_ptr(&self) -> *const T {
  function as_mut_ptr (line 146) | pub fn as_mut_ptr(&mut self) -> *mut T {
  function spare_mut_ptr (line 151) | fn spare_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
  function as_slice (line 157) | pub fn as_slice(&self) -> &[T] {
  function as_mut_slice (line 163) | pub fn as_mut_slice(&mut self) -> &mut [T] {
  function leak (line 169) | pub fn leak(self) -> &'a mut [T] {
  function clear (line 175) | pub fn clear(&mut self) {
  function reserve (line 183) | pub fn reserve(&mut self, alloc: &'a dyn Allocator, additional: usize) {
  function reserve_exact (line 204) | pub fn reserve_exact(&mut self, alloc: &'a dyn Allocator, additional: us...
  function reserve_one (line 218) | fn reserve_one(&mut self, alloc: &'a dyn Allocator) {
  function grow (line 232) | fn grow(&mut self, alloc: &'a dyn Allocator, cap: usize, add: usize) {
  function spare_capacity_mut (line 255) | pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] {
  function push (line 260) | pub fn push(&mut self, alloc: &'a dyn Allocator, value: T) -> &mut T {
  function pop (line 270) | pub fn pop(&mut self) -> Option<T> {
  function extend (line 290) | pub fn extend<I>(&mut self, alloc: &'a dyn Allocator, iter: I)
  function extend_sloppy (line 309) | pub fn extend_sloppy<I>(&mut self, alloc: &'a dyn Allocator, iter: I)
  function push_repeat (line 322) | pub fn push_repeat(&mut self, alloc: &'a dyn Allocator, value: T, total_...
  function extend_from_slice (line 338) | pub fn extend_from_slice(&mut self, alloc: &'a dyn Allocator, other: &[T...
  function extend_from_within (line 351) | pub fn extend_from_within<R>(&mut self, alloc: &'a dyn Allocator, src: R)
  function extend_from_within_impl (line 368) | fn extend_from_within_impl(&mut self, alloc: &'a dyn Allocator, src: Ran...
  function replace_range (line 385) | pub fn replace_range<R>(&mut self, alloc: &'a dyn Allocator, range: R, s...
  function replace_range_impl (line 404) | fn replace_range_impl(&mut self, alloc: &'a dyn Allocator, range: Range<...
  function MultiByteToWideChar (line 441) | fn MultiByteToWideChar(
  function push_encode_utf16 (line 452) | pub fn push_encode_utf16(&mut self, alloc: &'a dyn Allocator, utf8: &[u8...
  method default (line 493) | fn default() -> Self {
  type Target (line 499) | type Target = [T];
  method deref (line 502) | fn deref(&self) -> &[T] {
  method deref_mut (line 509) | fn deref_mut(&mut self) -> &mut [T] {
  function eq (line 519) | fn eq(&self, other: &BVec<T>) -> bool {
  function eq (line 531) | fn eq(&self, other: &[T]) -> bool {
  method partial_cmp (line 541) | fn partial_cmp(&self, other: &BVec<T>) -> Option<std::cmp::Ordering> {
  method cmp (line 551) | fn cmp(&self, other: &BVec<T>) -> std::cmp::Ordering {
  function fmt (line 560) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type Item (line 566) | type Item = T;
  type IntoIter (line 567) | type IntoIter = IntoIter<'a, T>;
  method into_iter (line 570) | fn into_iter(self) -> Self::IntoIter {
  type Item (line 580) | type Item = &'a T;
  type IntoIter (line 581) | type IntoIter = slice::Iter<'a, T>;
  method into_iter (line 584) | fn into_iter(self) -> Self::IntoIter {
  type Item (line 590) | type Item = &'a mut T;
  type IntoIter (line 591) | type IntoIter = slice::IterMut<'a, T>;
  method into_iter (line 594) | fn into_iter(self) -> Self::IntoIter {
  type IntoIter (line 600) | pub struct IntoIter<'a, T> {
  type Item (line 607) | type Item = T;
  method next (line 610) | fn next(&mut self) -> Option<T> {
  method size_hint (line 620) | fn size_hint(&self) -> (usize, Option<usize>) {
  method count (line 626) | fn count(self) -> usize {
  method last (line 631) | fn last(mut self) -> Option<T> {
  method nth (line 636) | fn nth(&mut self, n: usize) -> Option<Self::Item> {
  method fold (line 646) | fn fold<B, F>(mut self, mut accum: B, mut f: F) -> B
  method next_back (line 661) | fn next_back(&mut self) -> Option<T> {
  method len (line 674) | fn len(&self) -> usize {

FILE: crates/stdext/src/helpers.rs
  constant KILO (line 11) | pub const KILO: usize = 1000;
  constant MEGA (line 12) | pub const MEGA: usize = 1000 * 1000;
  constant GIGA (line 13) | pub const GIGA: usize = 1000 * 1000 * 1000;
  constant KIBI (line 15) | pub const KIBI: usize = 1024;
  constant MEBI (line 16) | pub const MEBI: usize = 1024 * 1024;
  constant GIBI (line 17) | pub const GIBI: usize = 1024 * 1024 * 1024;
  type MetricFormatter (line 19) | pub struct MetricFormatter<T>(pub T);
  function fmt (line 22) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function cold_path (line 41) | pub const fn cold_path() {}
  function minmax (line 44) | pub fn minmax<T>(v1: T, v2: T) -> [T; 2]
  function opt_ptr (line 53) | pub fn opt_ptr<T>(a: Option<&T>) -> *const T {
  function opt_ptr_eq (line 61) | pub fn opt_ptr_eq<T>(a: Option<&T>, b: Option<&T>) -> bool {
  function str_from_raw_parts (line 74) | pub const unsafe fn str_from_raw_parts<'a>(ptr: *const u8, len: usize) -...
  function slice_copy_safe (line 80) | pub fn slice_copy_safe<T: Copy>(dst: &mut [T], src: &[T]) -> usize {
  type ReplaceRange (line 88) | pub trait ReplaceRange<T: Copy> {
    method replace_range (line 89) | fn replace_range<R: RangeBounds<usize>>(&mut self, range: R, src: &[T]);
  function replace_range (line 93) | fn replace_range<R: RangeBounds<usize>>(&mut self, range: R, src: &[T]) {
  function vec_replace_impl (line 108) | fn vec_replace_impl<T: Copy>(dst: &mut Vec<T>, range: Range<usize>, src:...
  function slice_as_uninit_ref (line 144) | pub const fn slice_as_uninit_ref<T>(slice: &[T]) -> &[MaybeUninit<T>] {
  function slice_as_uninit_mut (line 150) | pub const fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUnini...
  function string_from_utf8_lossy_owned (line 155) | pub fn string_from_utf8_lossy_owned(v: Vec<u8>) -> String {
  type AsciiStringHelpers (line 164) | pub trait AsciiStringHelpers {
    method starts_with_ignore_ascii_case (line 169) | fn starts_with_ignore_ascii_case(&self, prefix: &str) -> bool;
    method starts_with_ignore_ascii_case (line 173) | fn starts_with_ignore_ascii_case(&self, prefix: &str) -> bool {

FILE: crates/stdext/src/simd/memset.rs
  function memset (line 20) | pub fn memset<T: Copy>(dst: &mut [T], val: T) {
  function memset_raw (line 54) | fn memset_raw(beg: *mut u8, end: *mut u8, val: u64) {
  function memset_fallback (line 66) | unsafe fn memset_fallback(mut beg: *mut u8, end: *mut u8, val: u64) {
  function memset_dispatch (line 95) | fn memset_dispatch(beg: *mut u8, end: *mut u8, val: u64) {
  function memset_sse2 (line 103) | unsafe fn memset_sse2(mut beg: *mut u8, end: *mut u8, val: u64) {
  function memset_avx2 (line 152) | fn memset_avx2(mut beg: *mut u8, end: *mut u8, val: u64) {
  function memset_dispatch (line 219) | fn memset_dispatch(beg: *mut u8, end: *mut u8, val: u64) {
  function memset_lasx (line 235) | fn memset_lasx(mut beg: *mut u8, end: *mut u8, val: u64) {
  function memset_lsx (line 295) | unsafe fn memset_lsx(mut beg: *mut u8, end: *mut u8, val: u64) {
  function memset_neon (line 341) | unsafe fn memset_neon(mut beg: *mut u8, end: *mut u8, val: u64) {
  function check_memset (line 393) | fn check_memset<T>(val: T, len: usize)
  function test_memset_empty (line 403) | fn test_memset_empty() {
  function test_memset_single (line 411) | fn test_memset_single() {
  function test_memset_small (line 420) | fn test_memset_small() {
  function test_memset_large (line 430) | fn test_memset_large() {
  function test_memset_various_values (line 439) | fn test_memset_various_values() {
  function test_memset_signed_types (line 448) | fn test_memset_signed_types() {
  function test_memset_usize_isize (line 457) | fn test_memset_usize_isize() {
  function test_memset_alignment (line 465) | fn test_memset_alignment() {

FILE: crates/stdext/src/sys/unix.rs
  function virtual_reserve (line 16) | pub unsafe fn virtual_reserve(size: usize) -> io::Result<NonNull<u8>> {
  function desired_mprotect (line 35) | const fn desired_mprotect(flags: c_int) -> c_int {
  function desired_mprotect (line 45) | const fn desired_mprotect(_: c_int) -> c_int {
  function virtual_release (line 55) | pub unsafe fn virtual_release(base: NonNull<u8>, size: usize) {
  function virtual_commit (line 68) | pub unsafe fn virtual_commit(base: NonNull<u8>, size: usize) -> io::Resu...

FILE: crates/stdext/src/sys/windows.rs
  constant MEM_COMMIT (line 7) | const MEM_COMMIT: u32 = 0x00001000;
  constant MEM_RELEASE (line 8) | const MEM_RELEASE: u32 = 0x00008000;
  constant MEM_RESERVE (line 9) | const MEM_RESERVE: u32 = 0x00002000;
  constant PAGE_READWRITE (line 10) | const PAGE_READWRITE: u32 = 0x04;
  function VirtualAlloc (line 13) | fn VirtualAlloc(
  function VirtualFree (line 19) | fn VirtualFree(lpAddress: *mut u8, dwSize: usize, dwFreeType: u32) -> i32;
  function virtual_reserve (line 30) | pub unsafe fn virtual_reserve(size: usize) -> io::Result<NonNull<u8>> {
  function virtual_release (line 47) | pub unsafe fn virtual_release(base: NonNull<u8>, _size: usize) {
  function virtual_commit (line 62) | pub unsafe fn virtual_commit(base: NonNull<u8>, size: usize) -> io::Resu...

FILE: crates/stdext/src/unicode/utf8.rs
  type Utf8Chars (line 16) | pub struct Utf8Chars<'a> {
  function new (line 23) | pub fn new(source: &'a [u8], offset: usize) -> Self {
  function source (line 28) | pub fn source(&self) -> &'a [u8] {
  function is_empty (line 33) | pub fn is_empty(&self) -> bool {
  function len (line 38) | pub fn len(&self) -> usize {
  function offset (line 45) | pub fn offset(&self) -> usize {
  function seek (line 50) | pub fn seek(&mut self, offset: usize) {
  function has_next (line 55) | pub fn has_next(&self) -> bool {
  function next_slow (line 62) | fn next_slow(&mut self, c: u8) -> char {
  function fffd (line 213) | fn fffd() -> char {
  type Item (line 219) | type Item = char;
  method next (line 222) | fn next(&mut self) -> Option<Self::Item> {
  method size_hint (line 243) | fn size_hint(&self) -> (usize, Option<usize>) {
  function test_broken_utf8 (line 258) | fn test_broken_utf8() {

FILE: crates/unicode-gen/src/main.rs
  type CharacterWidth (line 20) | enum CharacterWidth {
  type ClusterBreak (line 31) | enum ClusterBreak {
  type ClusterBreakExt (line 54) | enum ClusterBreakExt {
  type LineBreak (line 62) | enum LineBreak {
  type TrieType (line 103) | struct TrieType(u32);
    method new (line 106) | fn new(packing: &BitPacking, cb: ClusterBreak, lb: LineBreak, cw: Char...
    method change_cluster_break_ext (line 120) | fn change_cluster_break_ext(&mut self, packing: &BitPacking, cbe: Clus...
    method change_width (line 130) | fn change_width(&mut self, packing: &BitPacking, cw: CharacterWidth) {
    method value (line 140) | fn value(&self) -> u32 {
  type BitPacking (line 146) | struct BitPacking {
    method new (line 159) | fn new(line_breaks: bool, extended: bool) -> Self {
  type Ucd (line 180) | struct Ucd {
  type Stage (line 187) | struct Stage {
  type Trie (line 196) | struct Trie {
  type Language (line 202) | enum Language {
  type Output (line 209) | struct Output {
    method args (line 223) | fn args(&self) -> String {
  constant HELP (line 242) | const HELP: &str = "\
  function main (line 255) | fn main() -> anyhow::Result<()> {
  function generate_c (line 337) | fn generate_c(out: Output) -> String {
  function generate_rust (line 531) | fn generate_rust(out: Output) -> String {
  function extract_values_from_ucd (line 752) | fn extract_values_from_ucd(doc: &roxmltree::Document, out: &Output) -> a...
  type UcdAttributes (line 966) | struct UcdAttributes<'a> {
  function extract_attributes (line 975) | fn extract_attributes<'a>(
  function extract_range (line 989) | fn extract_range(node: &roxmltree::Node) -> RangeInclusive<usize> {
  function build_best_trie (line 1003) | fn build_best_trie(
  function build_trie (line 1031) | fn build_trie(uncompressed: Vec<TrieType>, shifts: &[usize]) -> Trie {
  function find_existing (line 1104) | fn find_existing(haystack: &[u32], needle: &[u32]) -> Option<usize> {
  function measure_overlap (line 1108) | fn measure_overlap(prev: &[u32], next: &[u32]) -> usize {
  function prepare_rules_row (line 1115) | fn prepare_rules_row(row: &[i32], bit_width: usize, non_joiner_value: i3...

FILE: crates/unicode-gen/src/rules.rs
  constant X (line 7) | const X: i32 = -1;
  constant JOIN_RULES_GRAPHEME_CLUSTER (line 57) | pub const JOIN_RULES_GRAPHEME_CLUSTER: [[[i32; 16]; 16]; 2] = [
  constant JOIN_RULES_LINE_BREAK (line 260) | pub const JOIN_RULES_LINE_BREAK: [[i32; 24]; 25] = [
Condensed preview — 96 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,064K chars).
[
  {
    "path": ".cargo/release-nightly.toml",
    "chars": 413,
    "preview": "[profile.release]\npanic = \"immediate-abort\"\n\n[target.'cfg(all(target_os = \"windows\", target_env = \"msvc\"))']\nrustflags ="
  },
  {
    "path": ".cargo/release-windows-ms.toml",
    "chars": 1376,
    "preview": "# vvv The following parts are identical to release.toml vvv\n\n# Avoid linking with vcruntime140.dll by statically linking"
  },
  {
    "path": ".cargo/release.toml",
    "chars": 1061,
    "preview": "# The following is not used by default via .cargo/config.toml,\n# because `build-std-features` cannot be keyed by profile"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 254,
    "preview": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.co"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 1370,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\nenv:\n  CARGO_TERM_COLOR: al"
  },
  {
    "path": ".github/workflows/winget.yml",
    "chars": 1424,
    "preview": "name: Submit release to the WinGet community repository\n\non:\n  release:\n    types: [published]\n\njobs:\n  publish-winget:\n"
  },
  {
    "path": ".gitignore",
    "chars": 37,
    "preview": ".idea\n.vs\n*.profraw\nlcov.info\ntarget\n"
  },
  {
    "path": ".pipelines/release.yml",
    "chars": 8954,
    "preview": "# Documentation:  https://aka.ms/obpipelines\n\ntrigger: none\n\nparameters:\n  - name: debug\n    displayName: Enable debug o"
  },
  {
    "path": ".pipelines/tsa.json",
    "chars": 339,
    "preview": "{\n    \"instanceUrl\": \"https://microsoft.visualstudio.com\",\n    \"projectName\": \"OS\",\n    \"areaPath\": \"OS\\\\Windows Client "
  },
  {
    "path": ".vscode/launch.json",
    "chars": 2041,
    "preview": "{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"name\": \"Launch edit (Windows)\",\n            \"pr"
  },
  {
    "path": ".vscode/tasks.json",
    "chars": 527,
    "preview": "{\n    \"version\": \"2.0.0\",\n    \"tasks\": [\n        {\n            \"label\": \"rust: cargo build\",\n            \"type\": \"proces"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 558,
    "preview": "# Microsoft Open Source Code of Conduct\n\nThis project has adopted the [Microsoft Open Source Code of Conduct](https://op"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3180,
    "preview": "# Contributing\n\n## Translation improvements\n\nYou can find our translations in [`i18n/edit.toml`](./i18n/edit.toml).\nPlea"
  },
  {
    "path": "Cargo.toml",
    "chars": 1412,
    "preview": "[workspace]\ndefault-members = [\"crates/edit\"]\nmembers = [\"crates/*\"]\nresolver = \"2\"\n\n[workspace.package]\nedition = \"2024"
  },
  {
    "path": "LICENSE",
    "chars": 1095,
    "preview": "MIT License\n\nCopyright (c) Microsoft Corporation. All rights reserved.\n\nPermission is hereby granted, free of charge, to"
  },
  {
    "path": "README.md",
    "chars": 3592,
    "preview": "# ![Application Icon for Edit](./assets/edit.svg) Edit\n\nA simple editor for simple needs.\n\nThis editor pays homage to th"
  },
  {
    "path": "SECURITY.md",
    "chars": 2655,
    "preview": "<!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->\n\n## Security\n\nMicrosoft takes the security of our software products an"
  },
  {
    "path": "assets/com.microsoft.edit.desktop",
    "chars": 414,
    "preview": "[Desktop Entry]\nType=Application\nName=Microsoft Edit\nGenericName=Text Editor\nComment=A simple editor for simple needs\nIc"
  },
  {
    "path": "assets/editing-traces/README.md",
    "chars": 242,
    "preview": "# editing-traces\n\nThis directory contains Seph Gentle's ASCII-only `rustcode` editing traces from: https://github.com/jo"
  },
  {
    "path": "assets/highlighting-tests/json.json",
    "chars": 851,
    "preview": "{\n    // Object with various value types\n    \"string\": \"Hello, world!\", // string literal\n    \"numberInt\": 42, // intege"
  },
  {
    "path": "assets/manpage/edit.1",
    "chars": 690,
    "preview": ".TH EDIT 1 \"version 1.2.1\" \"December 2025\"\n.SH NAME\nedit \\- a simple text editor\n.SH SYNOPSIS\n\\fBedit\\fP [\\fIOPTIONS\\fP]"
  },
  {
    "path": "assets/microsoft.sixel",
    "chars": 1058,
    "preview": "\u001bP;1q\"1;1;300;60#0;2;100;100;100#0!42?_ow{}!12?_ow{}!6?_ow{}}!5?_ow{{}}}!17~^NFbpw{}!8~!4}{wwo_!12?_oow{{{!4}!6~!4}{{wwo"
  },
  {
    "path": "assets/snapcraft.yaml",
    "chars": 653,
    "preview": "name: msedit\nbase: core24\nversion: '1.2.1'\nsummary: Edit is an MS-DOS inspired text editor from Microsoft\ndescription: |"
  },
  {
    "path": "crates/edit/Cargo.toml",
    "chars": 1206,
    "preview": "[package]\nname = \"edit\"\nversion = \"1.2.1\"\n\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = true"
  },
  {
    "path": "crates/edit/benches/lib.rs",
    "chars": 9928,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::hint::black_box;\nuse std::io::Curso"
  },
  {
    "path": "crates/edit/build/helpers.rs",
    "chars": 385,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::env::VarError;\n\npub fn env_opt(name"
  },
  {
    "path": "crates/edit/build/i18n.rs",
    "chars": 6300,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::collections::{BTreeMap, HashMap, Ha"
  },
  {
    "path": "crates/edit/build/main.rs",
    "chars": 4534,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n#![allow(irrefutable_let_patterns)]\n\nuse cra"
  },
  {
    "path": "crates/edit/src/base64.rs",
    "chars": 5046,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Base64 facilities.\n\nuse stdext::arena::A"
  },
  {
    "path": "crates/edit/src/bin/edit/apperr.rs",
    "chars": 678,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::io;\n\nuse edit::{buffer, icu};\n\n#[de"
  },
  {
    "path": "crates/edit/src/bin/edit/documents.rs",
    "chars": 11451,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ffi::OsStr;\nuse std::fs::File;\nuse "
  },
  {
    "path": "crates/edit/src/bin/edit/draw_editor.rs",
    "chars": 11512,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::num::ParseIntError;\n\nuse edit::fram"
  },
  {
    "path": "crates/edit/src/bin/edit/draw_filepicker.rs",
    "chars": 14645,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::cmp::Ordering;\nuse std::fs;\nuse std"
  },
  {
    "path": "crates/edit/src/bin/edit/draw_menubar.rs",
    "chars": 6236,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse edit::helpers::*;\nuse edit::input::{kbmo"
  },
  {
    "path": "crates/edit/src/bin/edit/draw_statusbar.rs",
    "chars": 11873,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse edit::framebuffer::{Attributes, IndexedC"
  },
  {
    "path": "crates/edit/src/bin/edit/edit.exe.manifest",
    "chars": 889,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly\n    xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n    xmlns"
  },
  {
    "path": "crates/edit/src/bin/edit/localization.rs",
    "chars": 757,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse edit::sys;\nuse stdext::AsciiStringHelper"
  },
  {
    "path": "crates/edit/src/bin/edit/main.rs",
    "chars": 23780,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nmod apperr;\nmod documents;\nmod draw_editor;\n"
  },
  {
    "path": "crates/edit/src/bin/edit/state.rs",
    "chars": 7956,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::borrow::Cow;\nuse std::ffi::{OsStr, "
  },
  {
    "path": "crates/edit/src/buffer/gap_buffer.rs",
    "chars": 11977,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ops::Range;\nuse std::ptr::{self, No"
  },
  {
    "path": "crates/edit/src/buffer/line_cache.rs",
    "chars": 3572,
    "preview": "use std::ops::Range;\n\nuse crate::{document::ReadableDocument, simd::memchr2};\n\n/// Cache a line/offset pair every CACHE_"
  },
  {
    "path": "crates/edit/src/buffer/mod.rs",
    "chars": 110450,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! A text buffer for a text editor.\n//!\n//!"
  },
  {
    "path": "crates/edit/src/buffer/navigation.rs",
    "chars": 8756,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ops::Range;\n\nuse crate::document::R"
  },
  {
    "path": "crates/edit/src/cell.rs",
    "chars": 1966,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! [`std::cell::RefCell`], but without runt"
  },
  {
    "path": "crates/edit/src/clipboard.rs",
    "chars": 1717,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Clipboard facilities for the editor.\n\n//"
  },
  {
    "path": "crates/edit/src/document.rs",
    "chars": 3365,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Abstractions over reading/writing arbitr"
  },
  {
    "path": "crates/edit/src/framebuffer.rs",
    "chars": 35187,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! A shoddy framebuffer for terminal applic"
  },
  {
    "path": "crates/edit/src/fuzzy.rs",
    "chars": 7998,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Fuzzy search algorithm based on the one "
  },
  {
    "path": "crates/edit/src/glob.rs",
    "chars": 9100,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Simple glob matching.\n//!\n//! Supported "
  },
  {
    "path": "crates/edit/src/hash.rs",
    "chars": 3541,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Provides fast, non-cryptographic hash fu"
  },
  {
    "path": "crates/edit/src/helpers.rs",
    "chars": 4702,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Random assortment of helpers I didn't kn"
  },
  {
    "path": "crates/edit/src/icu.rs",
    "chars": 48055,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Bindings to the ICU library.\n\nuse std::c"
  },
  {
    "path": "crates/edit/src/input.rs",
    "chars": 22735,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Parses VT sequences into input events.\n/"
  },
  {
    "path": "crates/edit/src/json.rs",
    "chars": 19543,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! A simple JSONC parser with trailing comm"
  },
  {
    "path": "crates/edit/src/lib.rs",
    "chars": 657,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n#![cfg_attr(\n    target_arch = \"loongarch64\""
  },
  {
    "path": "crates/edit/src/oklab.rs",
    "chars": 10071,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Oklab colorspace conversions.\n//!\n//! Im"
  },
  {
    "path": "crates/edit/src/path.rs",
    "chars": 3047,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Path related helpers.\n\nuse std::ffi::{Os"
  },
  {
    "path": "crates/edit/src/simd/lines_bwd.rs",
    "chars": 13973,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ptr;\n\nuse crate::helpers::CoordType"
  },
  {
    "path": "crates/edit/src/simd/lines_fwd.rs",
    "chars": 14514,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ptr;\n\nuse crate::helpers::CoordType"
  },
  {
    "path": "crates/edit/src/simd/memchr2.rs",
    "chars": 9400,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! `memchr`, but with two needles.\n\nuse std"
  },
  {
    "path": "crates/edit/src/simd/mod.rs",
    "chars": 941,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Provides various high-throughput utiliti"
  },
  {
    "path": "crates/edit/src/sys/mod.rs",
    "chars": 276,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Platform abstractions.\n\n#[cfg(unix)]\nmod"
  },
  {
    "path": "crates/edit/src/sys/unix.rs",
    "chars": 18868,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Unix-specific platform code.\n//!\n//! Rea"
  },
  {
    "path": "crates/edit/src/sys/windows.rs",
    "chars": 21744,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ffi::{OsString, c_char, c_void};\nus"
  },
  {
    "path": "crates/edit/src/tui.rs",
    "chars": 156039,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! An immediate mode UI framework for termi"
  },
  {
    "path": "crates/edit/src/unicode/measurement.rs",
    "chars": 39215,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse stdext::cold_path;\nuse stdext::unicode::"
  },
  {
    "path": "crates/edit/src/unicode/mod.rs",
    "chars": 177,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Everything related to Unicode lives here"
  },
  {
    "path": "crates/edit/src/unicode/tables.rs",
    "chars": 78493,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n// BEGIN: Generated by grapheme-table-gen on"
  },
  {
    "path": "crates/edit/src/vt.rs",
    "chars": 13614,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Our VT parser.\n\nuse std::time;\n\nuse stde"
  },
  {
    "path": "crates/stdext/Cargo.toml",
    "chars": 234,
    "preview": "[package]\nname = \"stdext\"\nversion = \"0.0.0\"\n\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace = tr"
  },
  {
    "path": "crates/stdext/src/alloc.rs",
    "chars": 1722,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::alloc::{Layout, alloc, dealloc, han"
  },
  {
    "path": "crates/stdext/src/arena/debug.rs",
    "chars": 3657,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n#![allow(clippy::missing_safety_doc, clippy:"
  },
  {
    "path": "crates/stdext/src/arena/fs.rs",
    "chars": 1924,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::fs::File;\nuse std::io::{self, Read}"
  },
  {
    "path": "crates/stdext/src/arena/mod.rs",
    "chars": 864,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Arena allocators. Small and fast.\n\n#[cfg"
  },
  {
    "path": "crates/stdext/src/arena/release.rs",
    "chars": 8425,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n#![allow(clippy::mut_from_ref)]\n\nuse std::ce"
  },
  {
    "path": "crates/stdext/src/arena/scratch.rs",
    "chars": 5125,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::io;\n#[cfg(debug_assertions)]\nuse st"
  },
  {
    "path": "crates/stdext/src/collections/mod.rs",
    "chars": 162,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nmod string;\nmod vec;\n\npub use string::{BStri"
  },
  {
    "path": "crates/stdext/src/collections/string.rs",
    "chars": 10504,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::fmt::{self};\nuse std::ops::{Bound, "
  },
  {
    "path": "crates/stdext/src/collections/vec.rs",
    "chars": 20321,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::hint::assert_unchecked;\nuse std::it"
  },
  {
    "path": "crates/stdext/src/helpers.rs",
    "chars": 5771,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Random assortment of helpers I didn't kn"
  },
  {
    "path": "crates/stdext/src/lib.rs",
    "chars": 244,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Arena allocators. Small and fast.\n\npub m"
  },
  {
    "path": "crates/stdext/src/simd/memset.rs",
    "chars": 15624,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! `memchr` for arbitrary sizes (1/2/4/8 by"
  },
  {
    "path": "crates/stdext/src/simd/mod.rs",
    "chars": 108,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nmod memset;\n\npub use memset::*;\n"
  },
  {
    "path": "crates/stdext/src/sys/mod.rs",
    "chars": 276,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Platform abstractions.\n\n#[cfg(unix)]\nmod"
  },
  {
    "path": "crates/stdext/src/sys/unix.rs",
    "chars": 2330,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::ffi::c_int;\nuse std::io;\nuse std::p"
  },
  {
    "path": "crates/stdext/src/sys/windows.rs",
    "chars": 2188,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::io;\nuse std::ptr::{NonNull, null_mu"
  },
  {
    "path": "crates/stdext/src/unicode/mod.rs",
    "chars": 151,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//! Everything related to Unicode lives here"
  },
  {
    "path": "crates/stdext/src/unicode/utf8.rs",
    "chars": 9044,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nuse std::{hint, iter};\n\n/// An iterator over"
  },
  {
    "path": "crates/unicode-gen/Cargo.toml",
    "chars": 373,
    "preview": "[package]\nname = \"unicode-gen\"\nversion = \"0.0.0\"\n\nedition.workspace = true\nlicense.workspace = true\nrepository.workspace"
  },
  {
    "path": "crates/unicode-gen/README.md",
    "chars": 607,
    "preview": "# Grapheme Table Generator\n\nThis tool processes Unicode Character Database (UCD) XML files to generate efficient, multi-"
  },
  {
    "path": "crates/unicode-gen/src/main.rs",
    "chars": 36989,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nmod rules;\n\nuse std::collections::HashMap;\nu"
  },
  {
    "path": "crates/unicode-gen/src/rules.rs",
    "chars": 30707,
    "preview": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n// Used as an indicator in our rules for ÷ ("
  },
  {
    "path": "i18n/edit.toml",
    "chars": 40550,
    "preview": "__default__ = [\n    \"en\",\n    # --------\n    \"de\",\n    \"es\",\n    \"fr\",\n    \"it\",\n    \"ja\",\n    \"ko\",\n    \"pt_br\",\n    \"r"
  },
  {
    "path": "rust-toolchain.toml",
    "chars": 32,
    "preview": "[toolchain]\nchannel = \"nightly\"\n"
  },
  {
    "path": "rustfmt.toml",
    "chars": 208,
    "preview": "style_edition = \"2024\"\nuse_small_heuristics = \"Max\"\ngroup_imports = \"StdExternalCrate\"\nimports_granularity = \"Module\"\nfo"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the microsoft/edit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 96 files (999.2 KB), approximately 293.9k tokens, and a symbol index with 1363 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!