aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig4
-rw-r--r--.github/workflows/release.yml3
-rw-r--r--CHANGELOG.md16
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--Cargo.lock34
-rw-r--r--INSTALL.md2
-rw-r--r--Makefile6
-rw-r--r--README.md17
-rw-r--r--alacritty.yml911
-rw-r--r--alacritty/Cargo.toml1
-rw-r--r--alacritty/src/cli.rs116
-rw-r--r--alacritty/src/config/bindings.rs38
-rw-r--r--alacritty/src/config/color.rs7
-rw-r--r--alacritty/src/config/mod.rs202
-rw-r--r--alacritty/src/config/mouse.rs28
-rw-r--r--alacritty/src/config/serde_utils.rs66
-rw-r--r--alacritty/src/config/ui_config.rs109
-rw-r--r--alacritty/src/config/window.rs4
-rw-r--r--alacritty/src/display/content.rs4
-rw-r--r--alacritty/src/main.rs15
-rw-r--r--alacritty/src/migrate.rs249
-rw-r--r--alacritty/src/window_context.rs6
-rw-r--r--alacritty_config/Cargo.toml2
-rw-r--r--alacritty_config/src/lib.rs2
-rw-r--r--alacritty_config_derive/Cargo.toml6
-rw-r--r--alacritty_config_derive/src/config_deserialize/de_struct.rs26
-rw-r--r--alacritty_config_derive/src/serde_replace.rs4
-rw-r--r--alacritty_config_derive/tests/config.rs37
-rw-r--r--alacritty_terminal/Cargo.toml1
-rw-r--r--alacritty_terminal/src/ansi.rs6
-rw-r--r--docs/features.md6
l---------extra/alacritty.yml1
-rw-r--r--extra/completions/_alacritty33
-rw-r--r--extra/completions/alacritty.bash46
-rw-r--r--extra/completions/alacritty.fish14
-rw-r--r--extra/man/alacritty-bindings.5.scd478
-rw-r--r--extra/man/alacritty.1.scd10
-rw-r--r--extra/man/alacritty.5.scd823
38 files changed, 2103 insertions, 1233 deletions
diff --git a/.editorconfig b/.editorconfig
index d68a9a4d..065542cc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,10 +10,6 @@ insert_final_newline = true
indent_style = space
indent_size = 4
-[*.yml]
-indent_style = space
-indent_size = 2
-
[Makefile]
indent_style = tab
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3eedddce..98903798 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -76,6 +76,8 @@ jobs:
run: |
scdoc < extra/man/alacritty.1.scd | gzip -c > "./alacritty.1.gz"
scdoc < extra/man/alacritty-msg.1.scd | gzip -c > "./alacritty-msg.1.gz"
+ scdoc < extra/man/alacritty.5.scd | gzip -c > "./alacritty.5.gz"
+ scdoc < extra/man/alacritty-bindings.5.scd | gzip -c > "./alacritty-bindings.5.gz"
- name: Upload Assets
run: |
mv ./extra/logo/alacritty-term.svg ./Alacritty.svg
@@ -87,4 +89,3 @@ jobs:
./.github/workflows/upload_asset.sh ./extra/completions/_alacritty $GITHUB_TOKEN
./.github/workflows/upload_asset.sh ./extra/linux/Alacritty.desktop $GITHUB_TOKEN
./.github/workflows/upload_asset.sh ./extra/alacritty.info $GITHUB_TOKEN
- ./.github/workflows/upload_asset.sh ./alacritty.yml $GITHUB_TOKEN
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cda212ed..4ca925ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,16 +12,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Minimum Rust version has been bumped to 1.65.0
- Manpages are now generated using `scdoc` (see `INSTALL.md`)
+### Added
+
+- Warnings for unused configuration file options
+
### Changed
- Mode-specific bindings can now be bound in any mode for easier macros
- `--help` output is more compact now and uses more neutral palette
+- Configuration file now uses TOML instead of YAML
+ Run `alacritty migrate` to automatically convert all configuration files
+- Deprecated config option `draw_bold_text_with_bright_colors`, use
+ `colors.draw_bold_text_with_bright_colors`
+- Deprecated config option `key_bindings`, use `keyboard.bindings`
+- Deprecated config option `mouse_bindings`, use `mouse.bindings`
### Fixed
- Hyperlink preview not being shown when the terminal has exactly 2 lines
- Crash on Windows when changing display scale factor
+### Removed
+
+- Config option `background_opacity`, use `window.background_opacity`
+- Config option `colors.search.bar`, use `colors.footer_bar` instead
+- Config option `mouse.url`, use the `hints` config section
+
## 0.12.1
### Fixed
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e41b85f3..a40a81db 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -86,8 +86,7 @@ Latency is another important factor for Alacritty. On X11, Windows, and macOS th
Code should be documented where appropriate. The existing code can be used as a guidance here and
the general `rustfmt` rules can be followed for formatting.
-If any change has been made to the `config.rs` file, these changes should also be documented in the
-example configuration file `alacritty.yml`.
+If any change has been made to the `config.rs` file, it should also be documented in the man pages.
Changes compared to the latest Alacritty release which have a direct effect on the user (opposed to
things like code refactorings or documentation/tests) additionally need to be documented in the
diff --git a/Cargo.lock b/Cargo.lock
index 7ee44996..b84ee05d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -38,6 +38,7 @@ dependencies = [
"serde",
"serde_json",
"serde_yaml",
+ "toml 0.7.4",
"unicode-width",
"wayland-client",
"windows-sys 0.48.0",
@@ -52,7 +53,7 @@ version = "0.1.2-dev"
dependencies = [
"log",
"serde",
- "serde_yaml",
+ "toml 0.7.4",
"winit",
]
@@ -65,8 +66,8 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "serde_yaml",
"syn 2.0.18",
+ "toml 0.7.4",
]
[[package]]
@@ -92,6 +93,7 @@ dependencies = [
"serde_yaml",
"signal-hook",
"signal-hook-mio",
+ "toml 0.7.4",
"unicode-width",
"vte",
"windows-sys 0.48.0",
@@ -585,7 +587,7 @@ checksum = "e62abb876c07e4754fae5c14cafa77937841f01740637e17d78dc04352f32a5e"
dependencies = [
"cc",
"rustc_version",
- "toml",
+ "toml 0.5.11",
"vswhom",
"winreg",
]
@@ -1664,6 +1666,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "serde_yaml"
version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1887,10 +1898,25 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
name = "toml_datetime"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
+dependencies = [
+ "serde",
+]
[[package]]
name = "toml_edit"
@@ -1899,6 +1925,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
+ "serde",
+ "serde_spanned",
"toml_datetime",
"winnow",
]
diff --git a/INSTALL.md b/INSTALL.md
index debe3f81..643f8dcc 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -333,6 +333,8 @@ Installing the manual page requires the additional dependencies `gzip` and `scdo
sudo mkdir -p /usr/local/share/man/man1
scdoc < extra/man/alacritty.1.scd | gzip -c | sudo tee /usr/local/share/man/man1/alacritty.1.gz > /dev/null
scdoc < extra/man/alacritty-msg.1.scd | gzip -c | sudo tee /usr/local/share/man/man1/alacritty-msg.1.gz > /dev/null
+scdoc < extra/man/alacritty.5.scd | gzip -c | sudo tee /usr/local/share/man/man5/alacritty.5.gz > /dev/null
+scdoc < extra/man/alacritty-bindings.5.scd | gzip -c | sudo tee /usr/local/share/man/man5/alacritty-bindings.5.gz > /dev/null
```
### Shell completions
diff --git a/Makefile b/Makefile
index e8a86e34..289bbe7c 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,8 @@ ASSETS_DIR = extra
RELEASE_DIR = target/release
MANPAGE = $(ASSETS_DIR)/man/alacritty.1.scd
MANPAGE-MSG = $(ASSETS_DIR)/man/alacritty-msg.1.scd
-CONFIGFILE = alacritty.yml
+MANPAGE-CONFIG = $(ASSETS_DIR)/man/alacritty.5.scd
+MANPAGE-CONFIG-BINDINGS = $(ASSETS_DIR)/man/alacritty-bindings.5.scd
TERMINFO = $(ASSETS_DIR)/alacritty.info
COMPLETIONS_DIR = $(ASSETS_DIR)/completions
COMPLETIONS = $(COMPLETIONS_DIR)/_alacritty \
@@ -48,10 +49,11 @@ $(APP_NAME)-%: $(TARGET)-%
@mkdir -p $(APP_COMPLETIONS_DIR)
@scdoc < $(MANPAGE) | gzip -c > $(APP_EXTRAS_DIR)/alacritty.1.gz
@scdoc < $(MANPAGE-MSG) | gzip -c > $(APP_EXTRAS_DIR)/alacritty-msg.1.gz
+ @scdoc < $(MANPAGE-CONFIG) | gzip -c > $(APP_EXTRAS_DIR)/alacritty.5.gz
+ @scdoc < $(MANPAGE-CONFIG-BINDINGS) | gzip -c > $(APP_EXTRAS_DIR)/alacritty-bindings.5.gz
@tic -xe alacritty,alacritty-direct -o $(APP_EXTRAS_DIR) $(TERMINFO)
@cp -fRp $(APP_TEMPLATE) $(APP_DIR)
@cp -fp $(APP_BINARY) $(APP_BINARY_DIR)
- @cp -fp $(CONFIGFILE) $(APP_EXTRAS_DIR)/
@cp -fp $(COMPLETIONS) $(APP_COMPLETIONS_DIR)
@touch -r "$(APP_BINARY)" "$(APP_DIR)/$(APP_NAME)"
@codesign --remove-signature "$(APP_DIR)/$(APP_NAME)"
diff --git a/README.md b/README.md
index 9a8546ba..87a514b1 100644
--- a/README.md
+++ b/README.md
@@ -52,22 +52,25 @@ For everyone else, the detailed instructions to install Alacritty can be found
## Configuration
-You can find the default configuration file with documentation for all available
-fields on the [GitHub releases page](https://github.com/alacritty/alacritty/releases) for each release.
+You can find the documentation for Alacritty's configuration in `man 5
+alacritty`, or by looking at [the scdoc file] if you do not have the manpages
+installed.
+
+[the scdoc file]: ./extra/man/alacritty.5.scd
Alacritty doesn't create the config file for you, but it looks for one in the
following locations:
-1. `$XDG_CONFIG_HOME/alacritty/alacritty.yml`
-2. `$XDG_CONFIG_HOME/alacritty.yml`
-3. `$HOME/.config/alacritty/alacritty.yml`
-4. `$HOME/.alacritty.yml`
+1. `$XDG_CONFIG_HOME/alacritty/alacritty.toml`
+2. `$XDG_CONFIG_HOME/alacritty.toml`
+3. `$HOME/.config/alacritty/alacritty.toml`
+4. `$HOME/.alacritty.toml`
### Windows
On Windows, the config file should be located at:
-`%APPDATA%\alacritty\alacritty.yml`
+`%APPDATA%\alacritty\alacritty.toml`
## Contributing
diff --git a/alacritty.yml b/alacritty.yml
deleted file mode 100644
index 76047d2a..00000000
--- a/alacritty.yml
+++ /dev/null
@@ -1,911 +0,0 @@
-# Configuration for Alacritty, the GPU enhanced terminal emulator.
-
-# Import additional configuration files
-#
-# Imports are loaded in order, skipping all missing files, with the importing
-# file being loaded last. If a field is already present in a previous import, it
-# will be replaced.
-#
-# All imports must either be absolute paths starting with `/`, or paths relative
-# to the user's home directory starting with `~/`.
-#import:
-# - /path/to/alacritty.yml
-
-# Any items in the `env` entry below will be added as
-# environment variables. Some entries may override variables
-# set by alacritty itself.
-#env:
- # TERM variable
- #
- # This value is used to set the `$TERM` environment variable for
- # each instance of Alacritty. If it is not present, alacritty will
- # check the local terminfo database and use `alacritty` if it is
- # available, otherwise `xterm-256color` is used.
- #TERM: alacritty
-
-#window:
- # Window dimensions (changes require restart)
- #
- # Number of lines/columns (not pixels) in the terminal. Both lines and columns
- # must be non-zero for this to take effect. The number of columns must be at
- # least `2`, while using a value of `0` for columns and lines will fall back
- # to the window manager's recommended size
- #dimensions:
- # columns: 0
- # lines: 0
-
- # Window position (changes require restart)
- #
- # Specified in number of pixels.
- # If the position is not set, the window manager will handle the placement.
- #position:
- # x: 0
- # y: 0
-
- # Window padding (changes require restart)
- #
- # Blank space added around the window in pixels. This padding is scaled
- # by DPI and the specified value is always added at both opposing sides.
- #padding:
- # x: 0
- # y: 0
-
- # Spread additional padding evenly around the terminal content.
- #dynamic_padding: false
-
- # Window decorations
- #
- # Values for `decorations`:
- # - full: Borders and title bar
- # - none: Neither borders nor title bar
- #
- # Values for `decorations` (macOS only):
- # - transparent: Title bar, transparent background and title bar buttons
- # - buttonless: Title bar, transparent background and no title bar buttons
- #decorations: full
-
- # Background opacity
- #
- # Window opacity as a floating point number from `0.0` to `1.0`.
- # The value `0.0` is completely transparent and `1.0` is opaque.
- #opacity: 1.0
-
- # Startup Mode (changes require restart)
- #
- # Values for `startup_mode`:
- # - Windowed
- # - Maximized
- # - Fullscreen
- #
- # Values for `startup_mode` (macOS only):
- # - SimpleFullscreen
- #startup_mode: Windowed
-
- # Window title
- #title: Alacritty
-
- # Allow terminal applications to change Alacritty's window title.
- #dynamic_title: true
-
- # Window class (Linux/BSD only):
- #class:
- # Application instance name
- #instance: Alacritty
- # General application class
- #general: Alacritty
-
- # Decorations theme variant
- #
- # Override the variant of the System theme/GTK theme/Wayland client side
- # decorations. Commonly supported values are `Dark`, `Light`, and `None` for
- # auto pick-up. Set this to `None` to use the default theme variant.
- #decorations_theme_variant: None
-
- # Resize increments
- #
- # Prefer resizing window by discrete steps equal to cell dimensions.
- #resize_increments: false
-
- # Make `Option` key behave as `Alt` (macOS only):
- # - OnlyLeft
- # - OnlyRight
- # - Both
- # - None (default)
- #option_as_alt: None
-
-#scrolling:
- # Maximum number of lines in the scrollback buffer.
- # Specifying '0' will disable scrolling.
- #history: 10000
-
- # Scrolling distance multiplier.
- #multiplier: 3
-
-# Font configuration
-#font:
- # Normal (roman) font face
- #normal:
- # Font family
- #
- # Default:
- # - (macOS) Menlo
- # - (Linux/BSD) monospace
- # - (Windows) Consolas
- #family: monospace
-
- # The `style` can be specified to pick a specific face.
- #style: Regular
-
- # Bold font face
- #bold:
- # Font family
- #
- # If the bold family is not specified, it will fall back to the
- # value specified for the normal font.
- #family: monospace
-
- # The `style` can be specified to pick a specific face.
- #style: Bold
-
- # Italic font face
- #italic:
- # Font family
- #
- # If the italic family is not specified, it will fall back to the
- # value specified for the normal font.
- #family: monospace
-
- # The `style` can be specified to pick a specific face.
- #style: Italic
-
- # Bold italic font face
- #bold_italic:
- # Font family
- #
- # If the bold italic family is not specified, it will fall back to the
- # value specified for the normal font.
- #family: monospace
-
- # The `style` can be specified to pick a specific face.
- #style: Bold Italic
-
- # Point size
- #size: 11.0
-
- # Offset is the extra space around each character. `offset.y` can be thought
- # of as modifying the line spacing, and `offset.x` as modifying the letter
- # spacing.
- #offset:
- # x: 0
- # y: 0
-
- # Glyph offset determines the locations of the glyphs within their cells with
- # the default being at the bottom. Increasing `x` moves the glyph to the
- # right, increasing `y` moves the glyph upward.
- #glyph_offset:
- # x: 0
- # y: 0
-
- # Use built-in font for box drawing characters.
- #
- # If `true`, Alacritty will use a custom built-in font for box drawing
- # characters (Unicode points 2500 - 259f).
- #
- #builtin_box_drawing: true
-
-# If `true`, bold text is drawn using the bright color variants.
-#draw_bold_text_with_bright_colors: false
-
-# Colors (Tomorrow Night)
-#colors:
- # Default colors
- #primary:
- # background: '#1d1f21'
- # foreground: '#c5c8c6'
-
- # Bright and dim foreground colors
- #
- # The dimmed foreground color is calculated automatically if it is not
- # present. If the bright foreground color is not set, or
- # `draw_bold_text_with_bright_colors` is `false`, the normal foreground
- # color will be used.
- #dim_foreground: '#828482'
- #bright_foreground: '#eaeaea'
-
- # Cursor colors
- #
- # Colors which should be used to draw the terminal cursor.
- #
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #cursor:
- # text: CellBackground
- # cursor: CellForeground
-
- # Vi mode cursor colors
- #
- # Colors for the cursor when the vi mode is active.
- #
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #vi_mode_cursor:
- # text: CellBackground
- # cursor: CellForeground
-
- # Search colors
- #
- # Colors used for the search bar and match highlighting.
- #search:
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #matches:
- # foreground: '#000000'
- # background: '#ffffff'
- #focused_match:
- # foreground: '#ffffff'
- # background: '#000000'
-
- # Keyboard hints
- #hints:
- # First character in the hint label
- #
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #start:
- # foreground: '#1d1f21'
- # background: '#e9ff5e'
-
- # All characters after the first one in the hint label
- #
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #end:
- # foreground: '#e9ff5e'
- # background: '#1d1f21'
-
- # Line indicator
- #
- # Color used for the indicator displaying the position in history during
- # search and vi mode.
- #
- # By default, these will use the opposing primary color.
- #line_indicator:
- # foreground: None
- # background: None
-
- # Footer bar
- #
- # Color used for the footer bar on the bottom, used by search regex input,
- # hyperlink URI preview, etc.
- #
- #footer_bar:
- # background: '#c5c8c6'
- # foreground: '#1d1f21'
-
- # Selection colors
- #
- # Colors which should be used to draw the selection area.
- #
- # Allowed values are CellForeground/CellBackground, which reference the
- # affected cell, or hexadecimal colors like #ff00ff.
- #selection:
- # text: CellBackground
- # background: CellForeground
-
- # Normal colors
- #normal:
- # black: '#1d1f21'
- # red: '#cc6666'
- # green: '#b5bd68'
- # yellow: '#f0c674'
- # blue: '#81a2be'
- # magenta: '#b294bb'
- # cyan: '#8abeb7'
- # white: '#c5c8c6'
-
- # Bright colors
- #bright:
- # black: '#666666'
- # red: '#d54e53'
- # green: '#b9ca4a'
- # yellow: '#e7c547'
- # blue: '#7aa6da'
- # magenta: '#c397d8'
- # cyan: '#70c0b1'
- # white: '#eaeaea'
-
- # Dim colors
- #
- # If the dim colors are not set, they will be calculated automatically based
- # on the `normal` colors.
- #dim:
- # black: '#131415'
- # red: '#864343'
- # green: '#777c44'
- # yellow: '#9e824c'
- # blue: '#556a7d'
- # magenta: '#75617b'
- # cyan: '#5b7d78'
- # white: '#828482'
-
- # Indexed Colors
- #
- # The indexed colors include all colors from 16 to 256.
- # When these are not set, they're filled with sensible defaults.
- #
- # Example:
- # `- { index: 16, color: '#ff00ff' }`
- #
- #indexed_colors: []
-
- # Transparent cell backgrounds
- #
- # Whether or not `window.opacity` applies to all cell backgrounds or only to
- # the default background. When set to `true` all cells will be transparent
- # regardless of their background color.
- #transparent_background_colors: false
-
-# Bell
-#
-# The bell is rung every time the BEL control character is received.
-#bell:
- # Visual Bell Animation
- #
- # Animation effect for flashing the screen when the visual bell is rung.
- #
- # Values for `animation`:
- # - Ease
- # - EaseOut
- # - EaseOutSine
- # - EaseOutQuad
- # - EaseOutCubic
- # - EaseOutQuart
- # - EaseOutQuint
- # - EaseOutExpo
- # - EaseOutCirc
- # - Linear
- #animation: EaseOutExpo
-
- # Duration of the visual bell flash in milliseconds. A `duration` of `0` will
- # disable the visual bell animation.
- #duration: 0
-
- # Visual bell animation color.
- #color: '#ffffff'
-
- # Bell Command
- #
- # This program is executed whenever the bell is rung.
- #
- # When set to `command: None`, no command will be executed.
- #
- # Example:
- # command:
- # program: notify-send
- # args: ["Hello, World!"]
- #
- #command: None
-
-#selection:
- # This string contains all characters that are used as separators for
- # "semantic words" in Alacritty.
- #semantic_escape_chars: ",│`|:\"' ()[]{}<>\t"
-
- # When set to `true`, selected text will be copied to the primary clipboard.
- #save_to_clipboard: false
-
-#cursor:
- # Cursor style
- #style:
- # Cursor shape
- #
- # Values for `shape`:
- # - ▇ Block
- # - _ Underline
- # - | Beam
- #shape: Block
-
- # Cursor blinking state
- #
- # Values for `blinking`:
- # - Never: Prevent the cursor from ever blinking
- # - Off: Disable blinking by default
- # - On: Enable blinking by default
- # - Always: Force the cursor to always blink
- #blinking: Off
-
- # Vi mode cursor style
- #
- # If the vi mode cursor style is `None` or not specified, it will fall back to
- # the style of the active value of the normal cursor.
- #
- # See `cursor.style` for available options.
- #vi_mode_style: None
-
- # Cursor blinking interval in milliseconds.
- #blink_interval: 750
-
- # Time after which cursor stops blinking, in seconds.
- #
- # Specifying '0' will disable timeout for blinking.
- #blink_timeout: 5
-
- # If this is `true`, the cursor will be rendered as a hollow box when the
- # window is not focused.
- #unfocused_hollow: true
-
- # Thickness of the cursor relative to the cell width as floating point number
- # from `0.0` to `1.0`.
- #thickness: 0.15
-
-# Live config reload (changes require restart)
-#live_config_reload: true
-
-# Shell
-#
-# You can set `shell.program` to the path of your favorite shell, e.g.
-# `/bin/fish`. Entries in `shell.args` are passed unmodified as arguments to the
-# shell.
-#
-# Default:
-# - (Linux/BSD/macOS) `$SHELL` or the user's login shell, if `$SHELL` is unset
-# - (Windows) powershell
-#shell:
-# program: /bin/bash
-# args:
-# - --login
-
-# Startup directory
-#
-# Directory the shell is started in. If this is unset, or `None`, the working
-# directory of the parent process will be used.
-#working_directory: None
-
-# Offer IPC using `alacritty msg` (unix only)
-#ipc_socket: true
-
-#mouse:
- # Click settings
- #
- # The `double_click` and `triple_click` settings control the time
- # alacritty should wait for accepting multiple clicks as one double
- # or triple click.
- #double_click: { threshold: 300 }
- #triple_click: { threshold: 300 }
-
- # If this is `true`, the cursor is temporarily hidden when typing.
- #hide_when_typing: false
-
-# Hints
-#
-# Terminal hints can be used to find text or hyperlink in the visible part of
-# the terminal and pipe it to other applications.
-#hints:
- # Keys used for the hint labels.
- #alphabet: "jfkdls;ahgurieowpq"
-
- # List with all available hints
- #
- # Each hint must have any of `regex` or `hyperlinks` field and either an
- # `action` or a `command` field. The fields `mouse`, `binding` and
- # `post_processing` are optional.
- #
- # The `hyperlinks` option will cause OSC 8 escape sequence hyperlinks to be
- # highlighted.
- #
- # The fields `command`, `binding.key`, `binding.mods`, `binding.mode` and
- # `mouse.mods` accept the same values as they do in the `key_bindings` section.
- #
- # The `mouse.enabled` field controls if the hint should be underlined while
- # the mouse with all `mouse.mods` keys held or the vi mode cursor is above it.
- #
- # If the `post_processing` field is set to `true`, heuristics will be used to
- # shorten the match if there are characters likely not to be part of the hint
- # (e.g. a trailing `.`). This is most useful for URIs and applies only to
- # `regex` matches.
- #
- # Values for `action`:
- # - Copy
- # Copy the hint's text to the clipboard.
- # - Paste
- # Paste the hint's text to the terminal or search.
- # - Select
- # Select the hint's text.
- # - MoveViModeCursor
- # Move the vi mode cursor to the beginning of the hint.
- #enabled:
- # - regex: "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)\
- # [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+"
- # hyperlinks: true
- # command: xdg-open
- # post_processing: true
- # mouse:
- # enabled: true
- # mods: None
- # binding:
- # key: U
- # mods: Control|Shift
-
-# Mouse bindings
-#
-# Mouse bindings are specified as a list of objects, much like the key
-# bindings further below.
-#
-# To trigger mouse bindings when an application running within Alacritty
-# captures the mouse, the `Shift` modifier is automatically added as a
-# requirement.
-#
-# Each mouse binding will specify a:
-#
-# - `mouse`:
-#
-# - Middle
-# - Left
-# - Right
-# - Numeric identifier such as `5`
-#
-# - `action` (see key bindings for actions not exclusive to mouse mode)
-#
-# - Mouse exclusive actions:
-#
-# - ExpandSelection
-# Expand the selection to the current mouse cursor location.
-#
-# And optionally:
-#
-# - `mods` (see key bindings)
-#mouse_bindings:
-# - { mouse: Right, action: ExpandSelection }
-# - { mouse: Right, mods: Control, action: ExpandSelection }
-# - { mouse: Middle, mode: ~Vi, action: PasteSelection }
-
-# Key bindings
-#
-# Key bindings are specified as a list of objects. For example, this is the
-# default paste binding:
-#
-# `- { key: V, mods: Control|Shift, action: Paste }`
-#
-# Each key binding will specify a:
-#
-# - `key`: Identifier of the key pressed
-#
-# - A-Z
-# - F1-F24
-# - Key0-Key9
-#
-# A full list with available key codes can be found here:
-# https://docs.rs/winit/*/winit/event/enum.VirtualKeyCode.html#variants
-#
-# Instead of using the name of the keys, the `key` field also supports using
-# the scancode of the desired key. Scancodes have to be specified as a
-# decimal number. This command will allow you to display the hex scancodes
-# for certain keys:
-#
-# `showkey --scancodes`.
-#
-# Then exactly one of:
-#
-# - `chars`: Send a byte sequence to the running application
-#
-# The `chars` field writes the specified string to the terminal. This makes
-# it possible to pass escape sequences. To find escape codes for bindings
-# like `PageUp` (`"\x1b[5~"`), you can run the command `showkey -a` outside
-# of tmux. Note that applications use terminfo to map escape sequences back
-# to keys. It is therefore required to update the terminfo when changing an
-# escape sequence.
-#
-# - `action`: Execute a predefined action
-#
-# - ToggleViMode
-# - SearchForward
-# Start searching toward the right of the search origin.
-# - SearchBackward
-# Start searching toward the left of the search origin.
-# - Copy
-# - Paste
-# - IncreaseFontSize
-# - DecreaseFontSize
-# - ResetFontSize
-# - ScrollPageUp
-# - ScrollPageDown
-# - ScrollHalfPageUp
-# - ScrollHalfPageDown
-# - ScrollLineUp
-# - ScrollLineDown
-# - ScrollToTop
-# - ScrollToBottom
-# - ClearHistory
-# Remove the terminal's scrollback history.
-# - Hide
-# Hide the Alacritty window.
-# - Minimize
-# Minimize the Alacritty window.
-# - Quit
-# Quit Alacritty.
-# - ToggleFullscreen
-# - ToggleMaximized
-# - SpawnNewInstance
-# Spawn a new instance of Alacritty.
-# - CreateNewWindow
-# Create a new Alacritty window from the current process.
-# - ClearLogNotice
-# Clear Alacritty's UI warning and error notice.
-# - ClearSelection
-# Remove the active selection.
-# - ReceiveChar
-# - None
-#
-# - Vi mode exclusive actions:
-#
-# - Open
-# Perform the action of the first matching hint under the vi mode cursor
-# with `mouse.enabled` set to `true`.
-# - ToggleNormalSelection
-# - ToggleLineSelection
-# - ToggleBlockSelection
-# - ToggleSemanticSelection
-# Toggle semantic selection based on `selection.semantic_escape_chars`.
-# - CenterAroundViCursor
-# Center view around vi mode cursor
-#
-# - Vi mode exclusive cursor motion actions:
-#
-# - Up
-# One line up.
-# - Down
-# One line down.
-# - Left
-# One character left.
-# - Right
-# One character right.
-# - First
-# First column, or beginning of the line when already at the first column.
-# - Last
-# Last column, or beginning of the line when already at the last column.
-# - FirstOccupied
-# First non-empty cell in this terminal row, or first non-empty cell of
-# the line when already at the first cell of the row.
-# - High
-# Top of the screen.
-# - Middle
-# Center of the screen.
-# - Low
-# Bottom of the screen.
-# - SemanticLeft
-# Start of the previous semantically separated word.
-# - SemanticRight
-# Start of the next semantically separated word.
-# - SemanticLeftEnd
-# End of the previous semantically separated word.
-# - SemanticRightEnd
-# End of the next semantically separated word.
-# - WordLeft
-# Start of the previous whitespace separated word.
-# - WordRight
-# Start of the next whitespace separated word.
-# - WordLeftEnd
-# End of the previous whitespace separated word.
-# - WordRightEnd
-# End of the next whitespace separated word.
-# - Bracket
-# Character matching the bracket at the cursor's location.
-# - SearchNext
-# Beginning of the next match.
-# - SearchPrevious
-# Beginning of the previous match.
-# - SearchStart
-# Start of the match to the left of the vi mode cursor.
-# - SearchEnd
-# End of the match to the right of the vi mode cursor.
-#
-# - Search mode exclusive actions:
-# - SearchFocusNext
-# Move the focus to the next search match.
-# - SearchFocusPrevious
-# Move the focus to the previous search match.
-# - SearchConfirm
-# - SearchCancel
-# - SearchClear
-# Reset the search regex.
-# - SearchDeleteWord
-# Delete the last word in the search regex.
-# - SearchHistoryPrevious
-# Go to the previous regex in the search history.
-# - SearchHistoryNext
-# Go to the next regex in the search history.
-#
-# - macOS exclusive actions:
-# - ToggleSimpleFullscreen
-# Enter fullscreen without occupying another space.
-#
-# - Linux/BSD exclusive actions:
-#
-# - CopySelection
-# Copy from the selection buffer.
-# - PasteSelection
-# Paste from the selection buffer.
-#
-# - `command`: Fork and execute a specified command plus arguments
-#
-# The `command` field must be a map containing a `program` string and an
-# `args` array of command line parameter strings. For example:
-# `{ program: "alacritty", args: ["-e", "vttest"] }`
-#
-# And optionally:
-#
-# - `mods`: Key modifiers to filter binding actions
-#
-# - Command
-# - Control
-# - Option
-# - Super
-# - Shift
-# - Alt
-#
-# Multiple `mods` can be combined using `|` like this:
-# `mods: Control|Shift`.
-# Whitespace and capitalization are relevant and must match the example.
-#
-# - `mode`: Indicate a binding for only specific terminal reported modes
-#
-# This is mainly used to send applications the correct escape sequences
-# when in different modes.
-#
-# - AppCursor
-# - AppKeypad
-# - Search
-# - Alt
-# - Vi
-#
-# A `~` operator can be used before a mode to apply the binding whenever
-# the mode is *not* active, e.g. `~Alt`.
-#
-# Bindings are always filled by default, but will be replaced when a new
-# binding with the same triggers is defined. To unset a default binding, it can
-# be mapped to the `ReceiveChar` action. Alternatively, you can use `None` for
-# a no-op if you do not wish to receive input characters for that binding.
-#
-# If the same trigger is assigned to multiple actions, all of them are executed
-# in the order they were defined in.
-#key_bindings:
- #- { key: Paste, action: Paste }
- #- { key: Copy, action: Copy }
- #- { key: L, mods: Control, action: ClearLogNotice }
- #- { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" }
- #- { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp }
- #- { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown }
- #- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop }
- #- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom }
-
- # Vi Mode
- #- { key: Space, mods: Shift|Control, mode: ~Search, action: ToggleViMode }
- #- { key: Space, mods: Shift|Control, mode: Vi|~Search, action: ScrollToBottom }
- #- { key: Escape, mode: Vi|~Search, action: ClearSelection }
- #- { key: I, mode: Vi|~Search, action: ToggleViMode }
- #- { key: I, mode: Vi|~Search, action: ScrollToBottom }
- #- { key: C, mods: Control, mode: Vi|~Search, action: ToggleViMode }
- #- { key: Y, mods: Control, mode: Vi|~Search, action: ScrollLineUp }
- #- { key: E, mods: Control, mode: Vi|~Search, action: ScrollLineDown }
- #- { key: G, mode: Vi|~Search, action: ScrollToTop }
- #- { key: G, mods: Shift, mode: Vi|~Search, action: ScrollToBottom }
- #- { key: B, mods: Control, mode: Vi|~Search, action: ScrollPageUp }
- #- { key: F, mods: Control, mode: Vi|~Search, action: ScrollPageDown }
- #- { key: U, mods: Control, mode: Vi|~Search, action: ScrollHalfPageUp }
- #- { key: D, mods: Control, mode: Vi|~Search, action: ScrollHalfPageDown }
- #- { key: Y, mode: Vi|~Search, action: Copy }
- #- { key: Y, mode: Vi|~Search, action: ClearSelection }
- #- { key: Copy, mode: Vi|~Search, action: ClearSelection }
- #- { key: V, mode: Vi|~Search, action: ToggleNormalSelection }
- #- { key: V, mods: Shift, mode: Vi|~Search, action: ToggleLineSelection }
- #- { key: V, mods: Control, mode: Vi|~Search, action: ToggleBlockSelection }
- #- { key: V, mods: Alt, mode: Vi|~Search, action: ToggleSemanticSelection }
- #- { key: Return, mode: Vi|~Search, action: Open }
- #- { key: Z, mode: Vi|~Search, action: CenterAroundViCursor }
- #- { key: K, mode: Vi|~Search, action: Up }
- #- { key: J, mode: Vi|~Search, action: Down }
- #- { key: H, mode: Vi|~Search, action: Left }
- #- { key: L, mode: Vi|~Search, action: Right }
- #- { key: Up, mode: Vi|~Search, action: Up }
- #- { key: Down, mode: Vi|~Search, action: Down }
- #- { key: Left, mode: Vi|~Search, action: Left }
- #- { key: Right, mode: Vi|~Search, action: Right }
- #- { key: Key0, mode: Vi|~Search, action: First }
- #- { key: Key4, mods: Shift, mode: Vi|~Search, action: Last }
- #- { key: Key6, mods: Shift, mode: Vi|~Search, action: FirstOccupied }
- #- { key: H, mods: Shift, mode: Vi|~Search, action: High }
- #- { key: M, mods: Shift, mode: Vi|~Search, action: Middle }
- #- { key: L, mods: Shift, mode: Vi|~Search, action: Low }
- #- { key: B, mode: Vi|~Search, action: SemanticLeft }
- #- { key: W, mode: Vi|~Search, action: SemanticRight }
- #- { key: E, mode: Vi|~Search, action: SemanticRightEnd }
- #- { key: B, mods: Shift, mode: Vi|~Search, action: WordLeft }
- #- { key: W, mods: Shift, mode: Vi|~Search, action: WordRight }
- #- { key: E, mods: Shift, mode: Vi|~Search, action: WordRightEnd }
- #- { key: Key5, mods: Shift, mode: Vi|~Search, action: Bracket }
- #- { key: Slash, mode: Vi|~Search, action: SearchForward }
- #- { key: Slash, mods: Shift, mode: Vi|~Search, action: SearchBackward }
- #- { key: N, mode: Vi|~Search, action: SearchNext }
- #- { key: N, mods: Shift, mode: Vi|~Search, action: SearchPrevious }
-
- # Search Mode
- #- { key: Return, mode: Search|Vi, action: SearchConfirm }
- #- { key: Escape, mode: Search, action: SearchCancel }
- #- { key: C, mods: Control, mode: Search, action: SearchCancel }
- #- { key: U, mods: Control, mode: Search, action: SearchClear }
- #- { key: W, mods: Control, mode: Search, action: SearchDeleteWord }
- #- { key: P, mods: Control, mode: Search, action: SearchHistoryPrevious }
- #- { key: N, mods: Control, mode: Search, action: SearchHistoryNext }
- #- { key: Up, mode: Search, action: SearchHistoryPrevious }
- #- { key: Down, mode: Search, action: SearchHistoryNext }
- #- { key: Return, mode: Search|~Vi, action: SearchFocusNext }
- #- { key: Return, mods: Shift, mode: Search|~Vi, action: SearchFocusPrevious }
-
- # (Windows, Linux, and BSD only)
- #- { key: V, mods: Control|Shift, mode: ~Vi, action: Paste }
- #- { key: C, mods: Control|Shift, action: Copy }
- #- { key: F, mods: Control|Shift, mode: ~Search, action: SearchForward }
- #- { key: B, mods: Control|Shift, mode: ~Search, action: SearchBackward }
- #- { key: C, mods: Control|Shift, mode: Vi|~Search, action: ClearSelection }
- #- { key: Insert, mods: Shift, action: PasteSelection }
- #- { key: Key0, mods: Control, action: ResetFontSize }
- #- { key: Equals, mods: Control, action: IncreaseFontSize }
- #- { key: Plus, mods: Control, action: IncreaseFontSize }
- #- { key: NumpadAdd, mods: Control, action: IncreaseFontSize }
- #- { key: Minus, mods: Control, action: DecreaseFontSize }
- #- { key: NumpadSubtract, mods: Control, action: DecreaseFontSize }
-
- # (Windows only)
- #- { key: Return, mods: Alt, action: ToggleFullscreen }
-
- # (macOS only)
- #- { key: K, mods: Command, mode: ~Vi|~Search, chars: "\x0c" }
- #- { key: K, mods: Command, mode: ~Vi|~Search, action: ClearHistory }
- #- { key: Key0, mods: Command, action: ResetFontSize }
- #- { key: Equals, mods: Command, action: IncreaseFontSize }
- #- { key: Plus, mods: Command, action: IncreaseFontSize }
- #- { key: NumpadAdd, mods: Command, action: IncreaseFontSize }
- #- { key: Minus, mods: Command, action: DecreaseFontSize }
- #- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize }
- #- { key: V, mods: Command, action: Paste }
- #- { key: C, mods: Command, action: Copy }
- #- { key: C, mods: Command, mode: Vi|~Search, action: ClearSelection }
- #- { key: H, mods: Command, action: Hide }
- #- { key: H, mods: Command|Alt, action: HideOtherApplications }
- #- { key: M, mods: Command, action: Minimize }
- #- { key: Q, mods: Command, action: Quit }
- #- { key: W, mods: Command, action: Quit }
- #- { key: N, mods: Command, action: CreateNewWindow }
- #- { key: F, mods: Command|Control, action: ToggleFullscreen }
- #- { key: F, mods: Command, mode: ~Search, action: SearchForward }
- #- { key: B, mods: Command, mode: ~Search, action: SearchBackward }
-
-#debug:
- # Display the time it takes to redraw each frame.
- #render_timer: false
-
- # Keep the log file after quitting Alacritty.
- #persistent_logging: false
-
- # Log level
- #
- # Values for `log_level`:
- # - Off
- # - Error
- # - Warn
- # - Info
- # - Debug
- # - Trace
- #log_level: Warn
-
- # Renderer override.
- # - glsl3
- # - gles2
- # - gles2_pure
- #renderer: None
-
- # Print all received window events.
- #print_events: false
-
- # Highlight window damage information.
- #highlight_damage: false
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index aa9e817e..e7980c77 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -39,6 +39,7 @@ raw-window-handle = "0.5.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml = "0.8"
+toml = "0.7.1"
unicode-width = "0.1"
winit = { version = "0.28.2", default-features = false, features = ["serde"] }
diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs
index 7f39e527..7eb281d9 100644
--- a/alacritty/src/cli.rs
+++ b/alacritty/src/cli.rs
@@ -2,12 +2,10 @@ use std::cmp::max;
use std::os::raw::c_ulong;
use std::path::PathBuf;
-#[cfg(unix)]
-use clap::Subcommand;
-use clap::{ArgAction, Args, Parser, ValueHint};
+use clap::{ArgAction, Args, Parser, Subcommand, ValueHint};
use log::{self, error, LevelFilter};
use serde::{Deserialize, Serialize};
-use serde_yaml::Value;
+use toml::{Table, Value};
use alacritty_terminal::config::{Program, PtyConfig};
@@ -30,17 +28,18 @@ pub struct Options {
#[clap(long)]
pub embed: Option<String>,
- /// Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.yml].
+ /// Specify alternative configuration file [default:
+ /// $XDG_CONFIG_HOME/alacritty/alacritty.toml].
#[cfg(not(any(target_os = "macos", windows)))]
#[clap(long, value_hint = ValueHint::FilePath)]
pub config_file: Option<PathBuf>,
- /// Specify alternative configuration file [default: %APPDATA%\alacritty\alacritty.yml].
+ /// Specify alternative configuration file [default: %APPDATA%\alacritty\alacritty.toml].
#[cfg(windows)]
#[clap(long, value_hint = ValueHint::FilePath)]
pub config_file: Option<PathBuf>,
- /// Specify alternative configuration file [default: $HOME/.config/alacritty/alacritty.yml].
+ /// Specify alternative configuration file [default: $HOME/.config/alacritty/alacritty.toml].
#[cfg(target_os = "macos")]
#[clap(long, value_hint = ValueHint::FilePath)]
pub config_file: Option<PathBuf>,
@@ -64,14 +63,13 @@ pub struct Options {
/// CLI options for config overrides.
#[clap(skip)]
- pub config_options: Value,
+ pub config_options: TomlValue,
/// Options which can be passed via IPC.
#[clap(flatten)]
pub window_options: WindowOptions,
/// Subcommand passed to the CLI.
- #[cfg(unix)]
#[clap(subcommand)]
pub subcommands: Option<Subcommands>,
}
@@ -81,7 +79,7 @@ impl Options {
let mut options = Self::parse();
// Convert `--option` flags into serde `Value`.
- options.config_options = options_as_value(&options.option);
+ options.config_options = TomlValue(options_as_value(&options.option));
options
}
@@ -125,9 +123,9 @@ impl Options {
}
}
-/// Combine multiple options into a [`serde_yaml::Value`].
+/// Combine multiple options into a [`toml::Value`].
pub fn options_as_value(options: &[String]) -> Value {
- options.iter().fold(Value::default(), |value, option| match option_as_value(option) {
+ options.iter().fold(Value::Table(Table::new()), |value, option| match toml::from_str(option) {
Ok(new_value) => serde_utils::merge(value, new_value),
Err(_) => {
eprintln!("Ignoring invalid option: {:?}", option);
@@ -136,31 +134,6 @@ pub fn options_as_value(options: &[String]) -> Value {
})
}
-/// Parse an option in the format of `parent.field=value` as a serde Value.
-fn option_as_value(option: &str) -> Result<Value, serde_yaml::Error> {
- let mut yaml_text = String::with_capacity(option.len());
- let mut closing_brackets = String::new();
-
- for (i, c) in option.chars().enumerate() {
- match c {
- '=' => {
- yaml_text.push_str(": ");
- yaml_text.push_str(&option[i + 1..]);
- break;
- },
- '.' => {
- yaml_text.push_str(": {");
- closing_brackets.push('}');
- },
- _ => yaml_text.push(c),
- }
- }
-
- yaml_text += &closing_brackets;
-
- serde_yaml::from_str(&yaml_text)
-}
-
/// Parse the class CLI parameter.
fn parse_class(input: &str) -> Result<Class, String> {
let (general, instance) = match input.split_once(',') {
@@ -259,10 +232,11 @@ impl WindowIdentity {
}
/// Available CLI subcommands.
-#[cfg(unix)]
#[derive(Subcommand, Debug)]
pub enum Subcommands {
+ #[cfg(unix)]
Msg(MessageOptions),
+ Migrate(MigrateOptions),
}
/// Send a message to the Alacritty socket.
@@ -289,6 +263,30 @@ pub enum SocketMessage {
Config(IpcConfig),
}
+/// Migrate the configuration file.
+#[derive(Args, Clone, Debug)]
+pub struct MigrateOptions {
+ /// Path to the configuration file.
+ #[clap(short, long, value_hint = ValueHint::FilePath)]
+ pub config_file: Option<PathBuf>,
+
+ /// Only output TOML config to stdout.
+ #[clap(short, long)]
+ pub dry_run: bool,
+
+ /// Do not recurse over imports.
+ #[clap(short = 'i', long)]
+ pub skip_imports: bool,
+
+ /// Do not move renamed fields to their new location.
+ #[clap(long)]
+ pub skip_renames: bool,
+
+ #[clap(short, long)]
+ /// Do not output to STDOUT.
+ pub silent: bool,
+}
+
/// Subset of options that we pass to 'create-window' IPC subcommand.
#[derive(Serialize, Deserialize, Args, Default, Clone, Debug, PartialEq, Eq)]
pub struct WindowOptions {
@@ -320,6 +318,16 @@ pub struct IpcConfig {
pub reset: bool,
}
+/// Toml value with default implementation.
+#[derive(Debug)]
+pub struct TomlValue(pub Value);
+
+impl Default for TomlValue {
+ fn default() -> Self {
+ Self(Value::Table(Table::new()))
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -333,7 +341,7 @@ mod tests {
use clap::CommandFactory;
#[cfg(target_os = "linux")]
use clap_complete::Shell;
- use serde_yaml::mapping::Mapping;
+ use toml::Table;
#[test]
fn dynamic_title_ignoring_options_by_default() {
@@ -371,38 +379,38 @@ mod tests {
#[test]
fn valid_option_as_value() {
// Test with a single field.
- let value = option_as_value("field=true").unwrap();
+ let value: Value = toml::from_str("field=true").unwrap();
- let mut mapping = Mapping::new();
- mapping.insert(Value::String(String::from("field")), Value::Bool(true));
+ let mut table = Table::new();
+ table.insert(String::from("field"), Value::Boolean(true));
- assert_eq!(value, Value::Mapping(mapping));
+ assert_eq!(value, Value::Table(table));
// Test with nested fields
- let value = option_as_value("parent.field=true").unwrap();
+ let value: Value = toml::from_str("parent.field=true").unwrap();
- let mut parent_mapping = Mapping::new();
- parent_mapping.insert(Value::String(String::from("field")), Value::Bool(true));
- let mut mapping = Mapping::new();
- mapping.insert(Value::String(String::from("parent")), Value::Mapping(parent_mapping));
+ let mut parent_table = Table::new();
+ parent_table.insert(String::from("field"), Value::Boolean(true));
+ let mut table = Table::new();
+ table.insert(String::from("parent"), Value::Table(parent_table));
- assert_eq!(value, Value::Mapping(mapping));
+ assert_eq!(value, Value::Table(table));
}
#[test]
fn invalid_option_as_value() {
- let value = option_as_value("}");
+ let value = toml::from_str::<Value>("}");
assert!(value.is_err());
}
#[test]
fn float_option_as_value() {
- let value = option_as_value("float=3.4").unwrap();
+ let value: Value = toml::from_str("float=3.4").unwrap();
- let mut expected = Mapping::new();
- expected.insert(Value::String(String::from("float")), Value::Number(3.4.into()));
+ let mut expected = Table::new();
+ expected.insert(String::from("float"), Value::Float(3.4));
- assert_eq!(value, Value::Mapping(expected));
+ assert_eq!(value, Value::Table(expected));
}
#[test]
diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs
index 692cf7e9..8fd16361 100644
--- a/alacritty/src/config/bindings.rs
+++ b/alacritty/src/config/bindings.rs
@@ -5,7 +5,7 @@ use std::fmt::{self, Debug, Display};
use bitflags::bitflags;
use serde::de::{self, Error as SerdeError, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer};
-use serde_yaml::Value as SerdeValue;
+use toml::Value as SerdeValue;
use winit::event::VirtualKeyCode::*;
use winit::event::{ModifiersState, MouseButton, VirtualKeyCode};
@@ -1011,19 +1011,20 @@ impl<'a> Deserialize<'a> for RawBinding {
return Err(<V::Error as Error>::duplicate_field("key"));
}
- let val = map.next_value::<SerdeValue>()?;
- if val.is_u64() {
- let scancode = val.as_u64().unwrap();
- if scancode > u64::from(u32::MAX) {
- return Err(<V::Error as Error>::custom(format!(
- "Invalid key binding, scancode too big: {}",
- scancode
- )));
- }
- key = Some(Key::Scancode(scancode as u32));
- } else {
- let k = Key::deserialize(val).map_err(V::Error::custom)?;
- key = Some(k);
+ let value = map.next_value::<SerdeValue>()?;
+ match value.as_integer() {
+ Some(scancode) => match u32::try_from(scancode) {
+ Ok(scancode) => key = Some(Key::Scancode(scancode)),
+ Err(_) => {
+ return Err(<V::Error as Error>::custom(format!(
+ "Invalid key binding, scancode is too big: {}",
+ scancode
+ )));
+ },
+ },
+ None => {
+ key = Some(Key::deserialize(value).map_err(V::Error::custom)?);
+ },
}
},
Field::Mods => {
@@ -1066,15 +1067,6 @@ impl<'a> Deserialize<'a> for RawBinding {
Err(err) => {
let value = match value {
SerdeValue::String(string) => string,
- SerdeValue::Mapping(map) if map.len() == 1 => {
- match map.into_iter().next() {
- Some((
- SerdeValue::String(string),
- SerdeValue::Null,
- )) => string,
- _ => return Err(err),
- }
- },
_ => return Err(err),
};
return Err(V::Error::custom(format!(
diff --git a/alacritty/src/config/color.rs b/alacritty/src/config/color.rs
index 23c18e50..e08b08b4 100644
--- a/alacritty/src/config/color.rs
+++ b/alacritty/src/config/color.rs
@@ -18,16 +18,17 @@ pub struct Colors {
pub line_indicator: LineIndicatorColors,
pub hints: HintColors,
pub transparent_background_colors: bool,
+ pub draw_bold_text_with_bright_colors: bool,
footer_bar: BarColors,
}
impl Colors {
pub fn footer_bar_foreground(&self) -> Rgb {
- self.search.bar.foreground.or(self.footer_bar.foreground).unwrap_or(self.primary.background)
+ self.footer_bar.foreground.unwrap_or(self.primary.background)
}
pub fn footer_bar_background(&self) -> Rgb {
- self.search.bar.background.or(self.footer_bar.background).unwrap_or(self.primary.foreground)
+ self.footer_bar.background.unwrap_or(self.primary.foreground)
}
}
@@ -126,8 +127,6 @@ impl Default for InvertedCellColors {
pub struct SearchColors {
pub focused_match: FocusedMatchColors,
pub matches: MatchColors,
- #[config(deprecated = "use `colors.footer_bar` instead")]
- bar: BarColors,
}
#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)]
diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs
index 2f230b06..821e9b6b 100644
--- a/alacritty/src/config/mod.rs
+++ b/alacritty/src/config/mod.rs
@@ -1,11 +1,14 @@
use std::fmt::{self, Display, Formatter};
use std::path::{Path, PathBuf};
+use std::result::Result as StdResult;
use std::{env, fs, io};
-use log::{debug, error, info};
+use log::{debug, error, info, warn};
use serde::Deserialize;
-use serde_yaml::mapping::Mapping;
-use serde_yaml::Value;
+use serde_yaml::Error as YamlError;
+use toml::de::Error as TomlError;
+use toml::ser::Error as TomlSeError;
+use toml::{Table, Value};
use alacritty_terminal::config::LOG_TARGET_CONFIG;
@@ -30,7 +33,7 @@ pub use crate::config::mouse::{ClickHandler, Mouse};
pub use crate::config::ui_config::UiConfig;
/// Maximum number of depth for the configuration file imports.
-const IMPORT_RECURSION_LIMIT: usize = 5;
+pub const IMPORT_RECURSION_LIMIT: usize = 5;
/// Result from config loading.
pub type Result<T> = std::result::Result<T, Error>;
@@ -47,8 +50,14 @@ pub enum Error {
/// io error reading file.
Io(io::Error),
- /// Not valid yaml or missing parameters.
- Yaml(serde_yaml::Error),
+ /// Invalid toml.
+ Toml(TomlError),
+
+ /// Failed toml serialization.
+ TomlSe(TomlSeError),
+
+ /// Invalid yaml.
+ Yaml(YamlError),
}
impl std::error::Error for Error {
@@ -57,6 +66,8 @@ impl std::error::Error for Error {
Error::NotFound => None,
Error::ReadingEnvHome(err) => err.source(),
Error::Io(err) => err.source(),
+ Error::Toml(err) => err.source(),
+ Error::TomlSe(err) => err.source(),
Error::Yaml(err) => err.source(),
}
}
@@ -70,6 +81,8 @@ impl Display for Error {
write!(f, "Unable to read $HOME environment variable: {}", err)
},
Error::Io(err) => write!(f, "Error reading config file: {}", err),
+ Error::Toml(err) => write!(f, "Config error: {}", err),
+ Error::TomlSe(err) => write!(f, "Yaml conversion error: {}", err),
Error::Yaml(err) => write!(f, "Config error: {}", err),
}
}
@@ -91,16 +104,32 @@ impl From<io::Error> for Error {
}
}
-impl From<serde_yaml::Error> for Error {
- fn from(val: serde_yaml::Error) -> Self {
+impl From<TomlError> for Error {
+ fn from(val: TomlError) -> Self {
+ Error::Toml(val)
+ }
+}
+
+impl From<TomlSeError> for Error {
+ fn from(val: TomlSeError) -> Self {
+ Error::TomlSe(val)
+ }
+}
+
+impl From<YamlError> for Error {
+ fn from(val: YamlError) -> Self {
Error::Yaml(val)
}
}
/// Load the configuration file.
pub fn load(options: &Options) -> UiConfig {
- let config_options = options.config_options.clone();
- let config_path = options.config_file.clone().or_else(installed_config);
+ let config_options = options.config_options.0.clone();
+ let config_path = options
+ .config_file
+ .clone()
+ .or_else(|| installed_config("toml"))
+ .or_else(|| installed_config("yml"));
// Load the config using the following fallback behavior:
// - Config path + CLI overrides
@@ -128,7 +157,7 @@ pub fn reload(config_path: &Path, options: &Options) -> Result<UiConfig> {
debug!("Reloading configuration file: {:?}", config_path);
// Load config, propagating errors.
- let config_options = options.config_options.clone();
+ let config_options = options.config_options.0.clone();
let mut config = load_from(config_path, config_options)?;
after_loading(&mut config, options);
@@ -179,6 +208,16 @@ fn parse_config(
) -> Result<Value> {
config_paths.push(path.to_owned());
+ // Deserialize the configuration file.
+ let config = deserialize_config(path)?;
+
+ // Merge config with imports.
+ let imports = load_imports(&config, config_paths, recursion_limit);
+ Ok(serde_utils::merge(imports, config))
+}
+
+/// Deserialize a configuration file.
+pub fn deserialize_config(path: &Path) -> Result<Value> {
let mut contents = fs::read_to_string(path)?;
// Remove UTF-8 BOM.
@@ -186,51 +225,84 @@ fn parse_config(
contents = contents.split_off(3);
}
+ // Convert YAML to TOML as a transitionary fallback mechanism.
+ let extension = path.extension().unwrap_or_default();
+ if (extension == "yaml" || extension == "yml") && !contents.trim().is_empty() {
+ warn!("YAML config {path:?} is deprecated, please migrate to TOML");
+
+ let value: serde_yaml::Value = serde_yaml::from_str(&contents)?;
+ contents = toml::to_string(&value)?;
+ }
+
// Load configuration file as Value.
- let config: Value = match serde_yaml::from_str(&contents) {
- Ok(config) => config,
- Err(error) => {
- // Prevent parsing error with an empty string and commented out file.
- if error.to_string() == "EOF while parsing a value" {
- Value::Mapping(Mapping::new())
- } else {
- return Err(Error::Yaml(error));
- }
- },
- };
+ let config: Value = toml::from_str(&contents)?;
- // Merge config with imports.
- let imports = load_imports(&config, config_paths, recursion_limit);
- Ok(serde_utils::merge(imports, config))
+ Ok(config)
}
/// Load all referenced configuration files.
fn load_imports(config: &Value, config_paths: &mut Vec<PathBuf>, recursion_limit: usize) -> Value {
- let imports = match config.get("import") {
- Some(Value::Sequence(imports)) => imports,
- Some(_) => {
- error!(target: LOG_TARGET_CONFIG, "Invalid import type: expected a sequence");
- return Value::Null;
+ // Get paths for all imports.
+ let import_paths = match imports(config, recursion_limit) {
+ Ok(import_paths) => import_paths,
+ Err(err) => {
+ error!(target: LOG_TARGET_CONFIG, "{err}");
+ return Value::Table(Table::new());
},
- None => return Value::Null,
+ };
+
+ // Parse configs for all imports recursively.
+ let mut merged = Value::Table(Table::new());
+ for import_path in import_paths {
+ let path = match import_path {
+ Ok(path) => path,
+ Err(err) => {
+ error!(target: LOG_TARGET_CONFIG, "{err}");
+ continue;
+ },
+ };
+
+ if !path.exists() {
+ info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display());
+ continue;
+ }
+
+ match parse_config(&path, config_paths, recursion_limit - 1) {
+ Ok(config) => merged = serde_utils::merge(merged, config),
+ Err(err) => {
+ error!(target: LOG_TARGET_CONFIG, "Unable to import config {:?}: {}", path, err)
+ },
+ }
+ }
+
+ merged
+}
+
+// TODO: Merge back with `load_imports` once `alacritty migrate` is dropped.
+//
+/// Get all import paths for a configuration.
+pub fn imports(
+ config: &Value,
+ recursion_limit: usize,
+) -> StdResult<Vec<StdResult<PathBuf, String>>, String> {
+ let imports = match config.get("import") {
+ Some(Value::Array(imports)) => imports,
+ Some(_) => return Err("Invalid import type: expected a sequence".into()),
+ None => return Ok(Vec::new()),
};
// Limit recursion to prevent infinite loops.
if !imports.is_empty() && recursion_limit == 0 {
- error!(target: LOG_TARGET_CONFIG, "Exceeded maximum configuration import depth");
- return Value::Null;
+ return Err("Exceeded maximum configuration import depth".into());
}
- let mut merged = Value::Null;
+ let mut import_paths = Vec::new();
for import in imports {
let mut path = match import {
Value::String(path) => PathBuf::from(path),
_ => {
- error!(
- target: LOG_TARGET_CONFIG,
- "Invalid import element type: expected path string"
- );
+ import_paths.push(Err("Invalid import element type: expected path string".into()));
continue;
},
};
@@ -240,49 +312,42 @@ fn load_imports(config: &Value, config_paths: &mut Vec<PathBuf>, recursion_limit
path = home_dir.join(stripped);
}
- if !path.exists() {
- info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display());
- continue;
- }
-
- match parse_config(&path, config_paths, recursion_limit - 1) {
- Ok(config) => merged = serde_utils::merge(merged, config),
- Err(err) => {
- error!(target: LOG_TARGET_CONFIG, "Unable to import config {:?}: {}", path, err)
- },
- }
+ import_paths.push(Ok(path));
}
- merged
+ Ok(import_paths)
}
/// Get the location of the first found default config file paths
/// according to the following order:
///
-/// 1. $XDG_CONFIG_HOME/alacritty/alacritty.yml
-/// 2. $XDG_CONFIG_HOME/alacritty.yml
-/// 3. $HOME/.config/alacritty/alacritty.yml
-/// 4. $HOME/.alacritty.yml
+/// 1. $XDG_CONFIG_HOME/alacritty/alacritty.toml
+/// 2. $XDG_CONFIG_HOME/alacritty.toml
+/// 3. $HOME/.config/alacritty/alacritty.toml
+/// 4. $HOME/.alacritty.toml
#[cfg(not(windows))]
-fn installed_config() -> Option<PathBuf> {
+pub fn installed_config(suffix: &str) -> Option<PathBuf> {
+ let file_name = format!("alacritty.{suffix}");
+
// Try using XDG location by default.
xdg::BaseDirectories::with_prefix("alacritty")
.ok()
- .and_then(|xdg| xdg.find_config_file("alacritty.yml"))
+ .and_then(|xdg| xdg.find_config_file(&file_name))
.or_else(|| {
xdg::BaseDirectories::new()
.ok()
- .and_then(|fallback| fallback.find_config_file("alacritty.yml"))
+ .and_then(|fallback| fallback.find_config_file(&file_name))
})
.or_else(|| {
if let Ok(home) = env::var("HOME") {
- // Fallback path: $HOME/.config/alacritty/alacritty.yml.
- let fallback = PathBuf::from(&home).join(".config/alacritty/alacritty.yml");
+ // Fallback path: $HOME/.config/alacritty/alacritty.toml.
+ let fallback = PathBuf::from(&home).join(".config/alacritty").join(&file_name);
if fallback.exists() {
return Some(fallback);
}
- // Fallback path: $HOME/.alacritty.yml.
- let fallback = PathBuf::from(&home).join(".alacritty.yml");
+ // Fallback path: $HOME/.alacritty.toml.
+ let hidden_name = format!(".{file_name}");
+ let fallback = PathBuf::from(&home).join(hidden_name);
if fallback.exists() {
return Some(fallback);
}
@@ -292,22 +357,17 @@ fn installed_config() -> Option<PathBuf> {
}
#[cfg(windows)]
-fn installed_config() -> Option<PathBuf> {
- dirs::config_dir().map(|path| path.join("alacritty\\alacritty.yml")).filter(|new| new.exists())
+pub fn installed_config(suffix: &str) -> Option<PathBuf> {
+ let file_name = format!("alacritty.{suffix}");
+ dirs::config_dir().map(|path| path.join("alacritty").join(file_name)).filter(|new| new.exists())
}
#[cfg(test)]
mod tests {
use super::*;
- static DEFAULT_ALACRITTY_CONFIG: &str =
- concat!(env!("CARGO_MANIFEST_DIR"), "/../alacritty.yml");
-
#[test]
- fn config_read_eof() {
- let config_path: PathBuf = DEFAULT_ALACRITTY_CONFIG.into();
- let mut config = read_config(&config_path, Value::Null).unwrap();
- config.config_paths = Vec::new();
- assert_eq!(config, UiConfig::default());
+ fn empty_config() {
+ toml::from_str::<UiConfig>("").unwrap();
}
}
diff --git a/alacritty/src/config/mouse.rs b/alacritty/src/config/mouse.rs
index 291e4c61..b6556a2c 100644
--- a/alacritty/src/config/mouse.rs
+++ b/alacritty/src/config/mouse.rs
@@ -1,14 +1,18 @@
use std::time::Duration;
-use alacritty_config_derive::ConfigDeserialize;
+use serde::{Deserialize, Deserializer};
+
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
+
+use crate::config::bindings::{self, MouseBinding};
+use crate::config::ui_config;
#[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq, Eq)]
pub struct Mouse {
pub double_click: ClickHandler,
pub triple_click: ClickHandler,
pub hide_when_typing: bool,
- #[config(deprecated = "use `hints` section instead")]
- pub url: Option<serde_yaml::Value>,
+ pub bindings: MouseBindings,
}
#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
@@ -27,3 +31,21 @@ impl ClickHandler {
Duration::from_millis(self.threshold as u64)
}
}
+
+#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
+pub struct MouseBindings(pub Vec<MouseBinding>);
+
+impl Default for MouseBindings {
+ fn default() -> Self {
+ Self(bindings::default_mouse_bindings())
+ }
+}
+
+impl<'de> Deserialize<'de> for MouseBindings {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ Ok(Self(ui_config::deserialize_bindings(deserializer, Self::default().0)?))
+ }
+}
diff --git a/alacritty/src/config/serde_utils.rs b/alacritty/src/config/serde_utils.rs
index beb9c36b..476133e0 100644
--- a/alacritty/src/config/serde_utils.rs
+++ b/alacritty/src/config/serde_utils.rs
@@ -1,7 +1,6 @@
//! Serde helpers.
-use serde_yaml::mapping::Mapping;
-use serde_yaml::Value;
+use toml::{Table, Value};
/// Merge two serde structures.
///
@@ -9,20 +8,19 @@ use serde_yaml::Value;
/// `replacement`.
pub fn merge(base: Value, replacement: Value) -> Value {
match (base, replacement) {
- (Value::Sequence(mut base), Value::Sequence(mut replacement)) => {
+ (Value::Array(mut base), Value::Array(mut replacement)) => {
base.append(&mut replacement);
- Value::Sequence(base)
+ Value::Array(base)
},
- (Value::Mapping(base), Value::Mapping(replacement)) => {
- Value::Mapping(merge_mapping(base, replacement))
+ (Value::Table(base), Value::Table(replacement)) => {
+ Value::Table(merge_tables(base, replacement))
},
- (value, Value::Null) => value,
(_, value) => value,
}
}
-/// Merge two key/value mappings.
-fn merge_mapping(mut base: Mapping, replacement: Mapping) -> Mapping {
+/// Merge two key/value tables.
+fn merge_tables(mut base: Table, replacement: Table) -> Table {
for (key, value) in replacement {
let value = match base.remove(&key) {
Some(base_value) => merge(base_value, value),
@@ -40,54 +38,54 @@ mod tests {
#[test]
fn merge_primitive() {
- let base = Value::Null;
- let replacement = Value::Bool(true);
+ let base = Value::Table(Table::new());
+ let replacement = Value::Boolean(true);
assert_eq!(merge(base, replacement.clone()), replacement);
- let base = Value::Bool(false);
- let replacement = Value::Bool(true);
+ let base = Value::Boolean(false);
+ let replacement = Value::Boolean(true);
assert_eq!(merge(base, replacement.clone()), replacement);
- let base = Value::Number(0.into());
- let replacement = Value::Number(1.into());
+ let base = Value::Integer(0.into());
+ let replacement = Value::Integer(1.into());
assert_eq!(merge(base, replacement.clone()), replacement);
let base = Value::String(String::new());
let replacement = Value::String(String::from("test"));
assert_eq!(merge(base, replacement.clone()), replacement);
- let base = Value::Mapping(Mapping::new());
- let replacement = Value::Null;
+ let base = Value::Table(Table::new());
+ let replacement = Value::Table(Table::new());
assert_eq!(merge(base.clone(), replacement), base);
}
#[test]
fn merge_sequence() {
- let base = Value::Sequence(vec![Value::Null]);
- let replacement = Value::Sequence(vec![Value::Bool(true)]);
- let expected = Value::Sequence(vec![Value::Null, Value::Bool(true)]);
+ let base = Value::Array(vec![Value::Table(Table::new())]);
+ let replacement = Value::Array(vec![Value::Boolean(true)]);
+ let expected = Value::Array(vec![Value::Table(Table::new()), Value::Boolean(true)]);
assert_eq!(merge(base, replacement), expected);
}
#[test]
- fn merge_mapping() {
- let mut base_mapping = Mapping::new();
- base_mapping.insert(Value::String(String::from("a")), Value::Bool(true));
- base_mapping.insert(Value::String(String::from("b")), Value::Bool(false));
- let base = Value::Mapping(base_mapping);
+ fn merge_tables() {
+ let mut base_table = Table::new();
+ base_table.insert(String::from("a"), Value::Boolean(true));
+ base_table.insert(String::from("b"), Value::Boolean(false));
+ let base = Value::Table(base_table);
- let mut replacement_mapping = Mapping::new();
- replacement_mapping.insert(Value::String(String::from("a")), Value::Bool(true));
- replacement_mapping.insert(Value::String(String::from("c")), Value::Bool(false));
- let replacement = Value::Mapping(replacement_mapping);
+ let mut replacement_table = Table::new();
+ replacement_table.insert(String::from("a"), Value::Boolean(true));
+ replacement_table.insert(String::from("c"), Value::Boolean(false));
+ let replacement = Value::Table(replacement_table);
let merged = merge(base, replacement);
- let mut expected_mapping = Mapping::new();
- expected_mapping.insert(Value::String(String::from("b")), Value::Bool(false));
- expected_mapping.insert(Value::String(String::from("a")), Value::Bool(true));
- expected_mapping.insert(Value::String(String::from("c")), Value::Bool(false));
- let expected = Value::Mapping(expected_mapping);
+ let mut expected_table = Table::new();
+ expected_table.insert(String::from("b"), Value::Boolean(false));
+ expected_table.insert(String::from("a"), Value::Boolean(true));
+ expected_table.insert(String::from("c"), Value::Boolean(false));
+ let expected = Value::Table(expected_table);
assert_eq!(merged, expected);
}
diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs
index 29ff2c4c..0933ea42 100644
--- a/alacritty/src/config/ui_config.rs
+++ b/alacritty/src/config/ui_config.rs
@@ -3,16 +3,14 @@ use std::fmt::{self, Formatter};
use std::path::PathBuf;
use std::rc::Rc;
-use log::error;
+use log::{error, warn};
use serde::de::{Error as SerdeError, MapAccess, Visitor};
use serde::{self, Deserialize, Deserializer};
use unicode_width::UnicodeWidthChar;
use winit::event::{ModifiersState, VirtualKeyCode};
use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
-use alacritty_terminal::config::{
- Config as TerminalConfig, Percentage, Program, LOG_TARGET_CONFIG,
-};
+use alacritty_terminal::config::{Config as TerminalConfig, Program, LOG_TARGET_CONFIG};
use alacritty_terminal::term::search::RegexSearch;
use crate::config::bell::BellConfig;
@@ -22,7 +20,7 @@ use crate::config::bindings::{
use crate::config::color::Colors;
use crate::config::debug::Debug;
use crate::config::font::Font;
-use crate::config::mouse::Mouse;
+use crate::config::mouse::{Mouse, MouseBindings};
use crate::config::window::WindowConfig;
/// Regex used for the default URL hint.
@@ -38,6 +36,7 @@ pub struct UiConfig {
/// Window configuration.
pub window: WindowConfig,
+ /// Mouse configuration.
pub mouse: Mouse,
/// Debug options.
@@ -57,9 +56,6 @@ pub struct UiConfig {
/// RGB values for colors.
pub colors: Colors,
- /// Should draw bold text with brighter colors instead of bold font.
- pub draw_bold_text_with_bright_colors: bool,
-
/// Path where config was loaded from.
#[config(skip)]
pub config_paths: Vec<PathBuf>,
@@ -75,37 +71,42 @@ pub struct UiConfig {
#[config(flatten)]
pub terminal_config: TerminalConfig,
+ /// Keyboard configuration.
+ keyboard: Keyboard,
+
+ /// Should draw bold text with brighter colors instead of bold font.
+ #[config(deprecated = "use colors.draw_bold_text_with_bright_colors instead")]
+ draw_bold_text_with_bright_colors: bool,
+
/// Keybindings.
+ #[config(deprecated = "use keyboard.bindings instead")]
key_bindings: KeyBindings,
/// Bindings for the mouse.
+ #[config(deprecated = "use mouse.bindings instead")]
mouse_bindings: MouseBindings,
-
- /// Background opacity from 0.0 to 1.0.
- #[config(deprecated = "use window.opacity instead")]
- background_opacity: Option<Percentage>,
}
impl Default for UiConfig {
fn default() -> Self {
Self {
live_config_reload: true,
- alt_send_esc: Default::default(),
#[cfg(unix)]
ipc_socket: true,
- font: Default::default(),
- window: Default::default(),
- mouse: Default::default(),
- debug: Default::default(),
+ draw_bold_text_with_bright_colors: Default::default(),
+ terminal_config: Default::default(),
+ mouse_bindings: Default::default(),
config_paths: Default::default(),
key_bindings: Default::default(),
- mouse_bindings: Default::default(),
- terminal_config: Default::default(),
- background_opacity: Default::default(),
- bell: Default::default(),
+ alt_send_esc: Default::default(),
+ keyboard: Default::default(),
+ window: Default::default(),
colors: Default::default(),
- draw_bold_text_with_bright_colors: Default::default(),
+ mouse: Default::default(),
+ debug: Default::default(),
hints: Default::default(),
+ font: Default::default(),
+ bell: Default::default(),
}
}
}
@@ -113,6 +114,15 @@ impl Default for UiConfig {
impl UiConfig {
/// Generate key bindings for all keyboard hints.
pub fn generate_hint_bindings(&mut self) {
+ // Check which key bindings is most likely to be the user's configuration.
+ //
+ // Both will be non-empty due to the presence of the default keybindings.
+ let key_bindings = if self.keyboard.bindings.0.len() >= self.key_bindings.0.len() {
+ &mut self.keyboard.bindings.0
+ } else {
+ &mut self.key_bindings.0
+ };
+
for hint in &self.hints.enabled {
let binding = match hint.binding {
Some(binding) => binding,
@@ -127,54 +137,56 @@ impl UiConfig {
action: Action::Hint(hint.clone()),
};
- self.key_bindings.0.push(binding);
+ key_bindings.push(binding);
}
}
#[inline]
pub fn window_opacity(&self) -> f32 {
- self.background_opacity.unwrap_or(self.window.opacity).as_f32()
+ self.window.opacity.as_f32()
}
#[inline]
pub fn key_bindings(&self) -> &[KeyBinding] {
- self.key_bindings.0.as_slice()
+ if self.keyboard.bindings.0.len() >= self.key_bindings.0.len() {
+ self.keyboard.bindings.0.as_slice()
+ } else {
+ self.key_bindings.0.as_slice()
+ }
}
#[inline]
pub fn mouse_bindings(&self) -> &[MouseBinding] {
- self.mouse_bindings.0.as_slice()
+ if self.mouse.bindings.0.len() >= self.mouse_bindings.0.len() {
+ self.mouse.bindings.0.as_slice()
+ } else {
+ self.mouse_bindings.0.as_slice()
+ }
}
-}
-
-#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
-struct KeyBindings(Vec<KeyBinding>);
-impl Default for KeyBindings {
- fn default() -> Self {
- Self(bindings::default_key_bindings())
+ #[inline]
+ pub fn draw_bold_text_with_bright_colors(&self) -> bool {
+ self.colors.draw_bold_text_with_bright_colors || self.draw_bold_text_with_bright_colors
}
}
-impl<'de> Deserialize<'de> for KeyBindings {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: Deserializer<'de>,
- {
- Ok(Self(deserialize_bindings(deserializer, Self::default().0)?))
- }
+/// Keyboard configuration.
+#[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq)]
+struct Keyboard {
+ /// Keybindings.
+ bindings: KeyBindings,
}
#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
-struct MouseBindings(Vec<MouseBinding>);
+struct KeyBindings(Vec<KeyBinding>);
-impl Default for MouseBindings {
+impl Default for KeyBindings {
fn default() -> Self {
- Self(bindings::default_mouse_bindings())
+ Self(bindings::default_key_bindings())
}
}
-impl<'de> Deserialize<'de> for MouseBindings {
+impl<'de> Deserialize<'de> for KeyBindings {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
@@ -183,7 +195,7 @@ impl<'de> Deserialize<'de> for MouseBindings {
}
}
-fn deserialize_bindings<'a, D, T>(
+pub fn deserialize_bindings<'a, D, T>(
deserializer: D,
mut default: Vec<Binding<T>>,
) -> Result<Vec<Binding<T>>, D::Error>
@@ -192,7 +204,7 @@ where
T: Copy + Eq,
Binding<T>: Deserialize<'a>,
{
- let values = Vec::<serde_yaml::Value>::deserialize(deserializer)?;
+ let values = Vec::<toml::Value>::deserialize(deserializer)?;
// Skip all invalid values.
let mut bindings = Vec::with_capacity(values.len());
@@ -388,7 +400,7 @@ impl<'de> Deserialize<'de> for HintContent {
{
let mut content = Self::Value::default();
- while let Some((key, value)) = map.next_entry::<String, serde_yaml::Value>()? {
+ while let Some((key, value)) = map.next_entry::<String, toml::Value>()? {
match key.as_str() {
"regex" => match Option::<LazyRegex>::deserialize(value) {
Ok(regex) => content.regex = regex,
@@ -408,7 +420,8 @@ impl<'de> Deserialize<'de> for HintContent {
);
},
},
- _ => (),
+ "command" | "action" => (),
+ key => warn!(target: LOG_TARGET_CONFIG, "Unrecognized hint field: {key}"),
}
}
diff --git a/alacritty/src/config/window.rs b/alacritty/src/config/window.rs
index db29fd85..e4236b99 100644
--- a/alacritty/src/config/window.rs
+++ b/alacritty/src/config/window.rs
@@ -232,7 +232,7 @@ impl<'de> Deserialize<'de> for Class {
{
let mut class = Self::Value::default();
- while let Some((key, value)) = map.next_entry::<String, serde_yaml::Value>()? {
+ while let Some((key, value)) = map.next_entry::<String, toml::Value>()? {
match key.as_str() {
"instance" => match String::deserialize(value) {
Ok(instance) => class.instance = instance,
@@ -252,7 +252,7 @@ impl<'de> Deserialize<'de> for Class {
);
},
},
- _ => (),
+ key => warn!(target: LOG_TARGET_CONFIG, "Unrecognized class field: {key}"),
}
}
diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs
index da211094..72f71e9b 100644
--- a/alacritty/src/display/content.rs
+++ b/alacritty/src/display/content.rs
@@ -314,7 +314,7 @@ impl RenderableCell {
_ => rgb.into(),
},
Color::Named(ansi) => {
- match (config.draw_bold_text_with_bright_colors, flags & Flags::DIM_BOLD) {
+ match (config.draw_bold_text_with_bright_colors(), flags & Flags::DIM_BOLD) {
// If no bright foreground is set, treat it like the BOLD flag doesn't exist.
(_, Flags::DIM_BOLD)
if ansi == NamedColor::Foreground
@@ -334,7 +334,7 @@ impl RenderableCell {
},
Color::Indexed(idx) => {
let idx = match (
- config.draw_bold_text_with_bright_colors,
+ config.draw_bold_text_with_bright_colors(),
flags & Flags::DIM_BOLD,
idx,
) {
diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs
index 29120b35..55f81502 100644
--- a/alacritty/src/main.rs
+++ b/alacritty/src/main.rs
@@ -42,6 +42,7 @@ mod logging;
#[cfg(target_os = "macos")]
mod macos;
mod message_bar;
+mod migrate;
#[cfg(windows)]
mod panic;
mod renderer;
@@ -54,9 +55,9 @@ mod gl {
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}
-use crate::cli::Options;
#[cfg(unix)]
-use crate::cli::{MessageOptions, Subcommands};
+use crate::cli::MessageOptions;
+use crate::cli::{Options, Subcommands};
use crate::config::{monitor, UiConfig};
use crate::event::{Event, Processor};
#[cfg(target_os = "macos")]
@@ -77,14 +78,14 @@ fn main() -> Result<(), Box<dyn Error>> {
// Load command line options.
let options = Options::new();
- #[cfg(unix)]
match options.subcommands {
- Some(Subcommands::Msg(options)) => msg(options),
- None => alacritty(options),
+ #[cfg(unix)]
+ Some(Subcommands::Msg(options)) => msg(options)?,
+ Some(Subcommands::Migrate(options)) => migrate::migrate(options),
+ None => alacritty(options)?,
}
- #[cfg(not(unix))]
- alacritty(options)
+ Ok(())
}
/// `msg` subcommand entrypoint.
diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs
new file mode 100644
index 00000000..07a10ba4
--- /dev/null
+++ b/alacritty/src/migrate.rs
@@ -0,0 +1,249 @@
+//! Configuration file migration.
+
+use std::fs;
+use std::path::Path;
+
+use toml::map::Entry;
+use toml::{Table, Value};
+
+use crate::cli::MigrateOptions;
+use crate::config;
+
+/// Handle migration.
+pub fn migrate(options: MigrateOptions) {
+ // Find configuration file path.
+ let config_path = options
+ .config_file
+ .clone()
+ .or_else(|| config::installed_config("toml"))
+ .or_else(|| config::installed_config("yml"));
+
+ // Abort if system has no installed configuration.
+ let config_path = match config_path {
+ Some(config_path) => config_path,
+ None => {
+ eprintln!("No configuration file found");
+ std::process::exit(1);
+ },
+ };
+
+ // If we're doing a wet run, perform a dry run first for safety.
+ if !options.dry_run {
+ let mut options = options.clone();
+ options.silent = true;
+ options.dry_run = true;
+ if let Err(err) = migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) {
+ eprintln!("Configuration file migration failed:");
+ eprintln!(" {config_path:?}: {err}");
+ std::process::exit(1);
+ }
+ }
+
+ // Migrate the root config.
+ match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) {
+ Ok(new_path) => {
+ if !options.silent {
+ println!("Successfully migrated {config_path:?} to {new_path:?}");
+ }
+ },
+ Err(err) => {
+ eprintln!("Configuration file migration failed:");
+ eprintln!(" {config_path:?}: {err}");
+ std::process::exit(1);
+ },
+ }
+}
+
+/// Migrate a specific configuration file.
+fn migrate_config(
+ options: &MigrateOptions,
+ path: &Path,
+ recursion_limit: usize,
+) -> Result<String, String> {
+ // Ensure configuration file has an extension.
+ let path_str = path.to_string_lossy();
+ let (prefix, suffix) = match path_str.rsplit_once('.') {
+ Some((prefix, suffix)) => (prefix, suffix),
+ None => return Err("missing file extension".to_string()),
+ };
+
+ // Abort if config is already toml.
+ if suffix == "toml" {
+ return Err("already in TOML format".to_string());
+ }
+
+ // Try to parse the configuration file.
+ let mut config = match config::deserialize_config(path) {
+ Ok(config) => config,
+ Err(err) => return Err(format!("parsing error: {err}")),
+ };
+
+ // Migrate config imports.
+ if !options.skip_imports {
+ migrate_imports(options, &mut config, recursion_limit)?;
+ }
+
+ // Migrate deprecated field names to their new location.
+ if !options.skip_renames {
+ migrate_renames(&mut config)?;
+ }
+
+ // Convert to TOML format.
+ let toml = toml::to_string(&config).map_err(|err| format!("conversion error: {err}"))?;
+ let new_path = format!("{prefix}.toml");
+
+ if options.dry_run && !options.silent {
+ // Output new content to STDOUT.
+ println!(
+ "\nv-----Start TOML for {path:?}-----v\n\n{toml}\n^-----End TOML for {path:?}-----^"
+ );
+ } else if !options.dry_run {
+ // Write the new toml configuration.
+ fs::write(&new_path, toml).map_err(|err| format!("filesystem error: {err}"))?;
+ }
+
+ Ok(new_path)
+}
+
+/// Migrate the imports of a config.
+fn migrate_imports(
+ options: &MigrateOptions,
+ config: &mut Value,
+ recursion_limit: usize,
+) -> Result<(), String> {
+ let imports = match config::imports(config, recursion_limit) {
+ Ok(imports) => imports,
+ Err(err) => return Err(format!("import error: {err}")),
+ };
+
+ // Migrate the individual imports.
+ let mut new_imports = Vec::new();
+ for import in imports {
+ let import = match import {
+ Ok(import) => import,
+ Err(err) => return Err(format!("import error: {err}")),
+ };
+ let new_path = migrate_config(options, &import, recursion_limit - 1)?;
+ new_imports.push(Value::String(new_path));
+ }
+
+ // Update the imports field.
+ if let Some(import) = config.get_mut("import") {
+ *import = Value::Array(new_imports);
+ }
+
+ Ok(())
+}
+
+/// Migrate deprecated fields.
+fn migrate_renames(config: &mut Value) -> Result<(), String> {
+ let config_table = match config.as_table_mut() {
+ Some(config_table) => config_table,
+ None => return Ok(()),
+ };
+
+ // draw_bold_text_with_bright_colors -> colors.draw_bold_text_with_bright_colors
+ move_value(config_table, &["draw_bold_text_with_bright_colors"], &[
+ "colors",
+ "draw_bold_text_with_bright_colors",
+ ])?;
+
+ // key_bindings -> keyboard.bindings
+ move_value(config_table, &["key_bindings"], &["keyboard", "bindings"])?;
+
+ // mouse_bindings -> keyboard.bindings
+ move_value(config_table, &["mouse_bindings"], &["mouse", "bindings"])?;
+
+ Ok(())
+}
+
+/// Move a toml value from one map to another.
+fn move_value(config_table: &mut Table, origin: &[&str], target: &[&str]) -> Result<(), String> {
+ if let Some(value) = remove_node(config_table, origin)? {
+ if !insert_node_if_empty(config_table, target, value)? {
+ return Err(format!(
+ "conflict: both `{}` and `{}` are set",
+ origin.join("."),
+ target.join(".")
+ ));
+ }
+ }
+
+ Ok(())
+}
+
+/// Remove a node from a tree of tables.
+fn remove_node(table: &mut Table, path: &[&str]) -> Result<Option<Value>, String> {
+ if path.len() == 1 {
+ Ok(table.remove(path[0]))
+ } else {
+ let next_table_value = match table.get_mut(path[0]) {
+ Some(next_table_value) => next_table_value,
+ None => return Ok(None),
+ };
+
+ let next_table = match next_table_value.as_table_mut() {
+ Some(next_table) => next_table,
+ None => return Err(format!("invalid `{}` table", path[0])),
+ };
+
+ remove_node(next_table, &path[1..])
+ }
+}
+
+/// Try to insert a node into a tree of tables.
+///
+/// Returns `false` if the node already exists.
+fn insert_node_if_empty(table: &mut Table, path: &[&str], node: Value) -> Result<bool, String> {
+ if path.len() == 1 {
+ match table.entry(path[0]) {
+ Entry::Vacant(vacant_entry) => {
+ vacant_entry.insert(node);
+ Ok(true)
+ },
+ Entry::Occupied(_) => Ok(false),
+ }
+ } else {
+ let next_table_value = table.entry(path[0]).or_insert_with(|| Value::Table(Table::new()));
+
+ let next_table = match next_table_value.as_table_mut() {
+ Some(next_table) => next_table,
+ None => return Err(format!("invalid `{}` table", path[0])),
+ };
+
+ insert_node_if_empty(next_table, &path[1..], node)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn move_values() {
+ let input = r#"
+root_value = 3
+
+[table]
+table_value = 5
+
+[preexisting]
+not_moved = 9
+ "#;
+
+ let mut value: Value = toml::from_str(input).unwrap();
+ let table = value.as_table_mut().unwrap();
+
+ move_value(table, &["root_value"], &["new_table", "root_value"]).unwrap();
+ move_value(table, &["table", "table_value"], &["preexisting", "subtable", "new_name"])
+ .unwrap();
+
+ let output = toml::to_string(table).unwrap();
+
+ assert_eq!(
+ output,
+ "[new_table]\nroot_value = 3\n\n[preexisting]\nnot_moved = \
+ 9\n\n[preexisting.subtable]\nnew_name = 5\n\n[table]\n"
+ );
+ }
+}
diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs
index 885d71a4..a450c77d 100644
--- a/alacritty/src/window_context.rs
+++ b/alacritty/src/window_context.rs
@@ -70,7 +70,7 @@ pub struct WindowContext {
master_fd: RawFd,
#[cfg(not(windows))]
shell_pid: u32,
- ipc_config: Vec<(String, serde_yaml::Value)>,
+ ipc_config: Vec<(String, toml::Value)>,
config: Rc<UiConfig>,
}
@@ -379,8 +379,8 @@ impl WindowContext {
},
};
- // Try and parse value as yaml.
- match serde_yaml::from_str(value) {
+ // Try and parse value as toml.
+ match toml::from_str(value) {
Ok(value) => self.ipc_config.push((key.to_owned(), value)),
Err(err) => error!(
target: LOG_TARGET_IPC_CONFIG,
diff --git a/alacritty_config/Cargo.toml b/alacritty_config/Cargo.toml
index 995edfa1..b7ed5658 100644
--- a/alacritty_config/Cargo.toml
+++ b/alacritty_config/Cargo.toml
@@ -10,8 +10,8 @@ rust-version = "1.65.0"
[dependencies]
log = { version = "0.4.17", features = ["serde"] }
-serde_yaml = "0.8.24"
serde = "1.0.163"
+toml = "0.7.1"
[target.'cfg(target_os = "macos")'.dependencies]
winit = { version = "0.28.2", default-features = false, features = ["serde"] }
diff --git a/alacritty_config/src/lib.rs b/alacritty_config/src/lib.rs
index 5ed9e1a5..c9d73622 100644
--- a/alacritty_config/src/lib.rs
+++ b/alacritty_config/src/lib.rs
@@ -3,7 +3,7 @@ use std::error::Error;
use log::LevelFilter;
use serde::Deserialize;
-use serde_yaml::Value;
+use toml::Value;
pub trait SerdeReplace {
fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>>;
diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml
index d50b6b1d..12ef2169 100644
--- a/alacritty_config_derive/Cargo.toml
+++ b/alacritty_config_derive/Cargo.toml
@@ -12,15 +12,15 @@ rust-version = "1.65.0"
proc-macro = true
[dependencies]
-syn = { version = "2.0.16", features = ["derive", "parsing", "proc-macro", "printing"], default-features = false }
proc-macro2 = "1.0.24"
quote = "1.0.7"
+syn = { version = "2.0.16", features = ["derive", "parsing", "proc-macro", "printing"], default-features = false }
[dev-dependencies.alacritty_config]
path = "../alacritty_config"
version = "0.1.2-dev"
[dev-dependencies]
-serde = { version = "1.0.117", features = ["derive"] }
-serde_yaml = "0.8.14"
log = "0.4.11"
+serde = { version = "1.0.117", features = ["derive"] }
+toml = "0.7.1"
diff --git a/alacritty_config_derive/src/config_deserialize/de_struct.rs b/alacritty_config_derive/src/config_deserialize/de_struct.rs
index 1846f925..d2a7dd82 100644
--- a/alacritty_config_derive/src/config_deserialize/de_struct.rs
+++ b/alacritty_config_derive/src/config_deserialize/de_struct.rs
@@ -42,20 +42,25 @@ pub fn derive_deserialize<T>(
{
let mut config = Self::Value::default();
- // NOTE: This could be used to print unused keys.
- let mut unused = serde_yaml::Mapping::new();
+ // Unused keys for flattening and warning.
+ let mut unused = toml::Table::new();
- while let Some((key, value)) = map.next_entry::<String, serde_yaml::Value>()? {
+ while let Some((key, value)) = map.next_entry::<String, toml::Value>()? {
match key.as_str() {
#match_assignments
_ => {
- unused.insert(serde_yaml::Value::String(key), value);
+ unused.insert(key, value);
},
}
}
#flatten
+ // Warn about unused keys.
+ for key in unused.keys() {
+ log::warn!(target: #LOG_TARGET, "Unused config key: {}", key);
+ }
+
Ok(config)
}
}
@@ -109,7 +114,12 @@ fn field_deserializer(field_streams: &mut FieldStreams, field: &Field) -> Result
match serde::Deserialize::deserialize(value) {
Ok(value) => config.#ident = value,
Err(err) => {
- log::error!(target: #LOG_TARGET, "Config error: {}: {}", #literal, err);
+ log::error!(
+ target: #LOG_TARGET,
+ "Config error: {}: {}",
+ #literal,
+ err.to_string().trim(),
+ );
},
}
};
@@ -133,8 +143,10 @@ fn field_deserializer(field_streams: &mut FieldStreams, field: &Field) -> Result
// Create the tokens to deserialize the flattened struct from the unused fields.
field_streams.flatten.extend(quote! {
- let unused = serde_yaml::Value::Mapping(unused);
- config.#ident = serde::Deserialize::deserialize(unused).unwrap_or_default();
+ // Drain unused fields since they will be used for flattening.
+ let flattened = std::mem::replace(&mut unused, toml::Table::new());
+
+ config.#ident = serde::Deserialize::deserialize(flattened).unwrap_or_default();
});
},
"deprecated" | "removed" => {
diff --git a/alacritty_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs
index 4a0a6a99..7ca5ca7c 100644
--- a/alacritty_config_derive/src/serde_replace.rs
+++ b/alacritty_config_derive/src/serde_replace.rs
@@ -28,7 +28,7 @@ pub fn derive(input: TokenStream) -> TokenStream {
pub fn derive_direct(ident: Ident, generics: Generics) -> TokenStream2 {
quote! {
impl <#generics> alacritty_config::SerdeReplace for #ident <#generics> {
- fn replace(&mut self, key: &str, value: serde_yaml::Value) -> Result<(), Box<dyn std::error::Error>> {
+ fn replace(&mut self, key: &str, value: toml::Value) -> Result<(), Box<dyn std::error::Error>> {
if !key.is_empty() {
let error = format!("Fields \"{}\" do not exist", key);
return Err(error.into());
@@ -53,7 +53,7 @@ pub fn derive_recursive<T>(
quote! {
#[allow(clippy::extra_unused_lifetimes)]
impl <'de, #constrained> alacritty_config::SerdeReplace for #ident <#unconstrained> {
- fn replace(&mut self, key: &str, value: serde_yaml::Value) -> Result<(), Box<dyn std::error::Error>> {
+ fn replace(&mut self, key: &str, value: toml::Value) -> Result<(), Box<dyn std::error::Error>> {
if key.is_empty() {
*self = serde::Deserialize::deserialize(value)?;
return Ok(());
diff --git a/alacritty_config_derive/tests/config.rs b/alacritty_config_derive/tests/config.rs
index bd449ff8..15bc62a9 100644
--- a/alacritty_config_derive/tests/config.rs
+++ b/alacritty_config_derive/tests/config.rs
@@ -86,20 +86,22 @@ fn config_deserialize() {
log::set_logger(logger).unwrap();
log::set_max_level(log::LevelFilter::Warn);
- let test: Test = serde_yaml::from_str(
+ let test: Test = toml::from_str(
r#"
- field1: 3
- field3: 32
- nesting:
- field1: "testing"
- field2: None
- field3: 99
- aliased: 8
- flatty: 123
- enom_small: "one"
- enom_big: "THREE"
- enom_error: "HugaBuga"
- gone: false
+ field1 = 3
+ field3 = 32
+
+ flatty = 123
+ enom_small = "one"
+ enom_big = "THREE"
+ enom_error = "HugaBuga"
+ gone = false
+
+ [nesting]
+ field1 = "testing"
+ field2 = "None"
+ field3 = 99
+ aliased = 8
"#,
)
.unwrap();
@@ -121,15 +123,16 @@ fn config_deserialize() {
// Verify all log messages are correct.
let error_logs = logger.error_logs.lock().unwrap();
assert_eq!(error_logs.as_slice(), [
- "Config error: field1: invalid type: string \"testing\", expected usize",
"Config error: enom_error: unknown variant `HugaBuga`, expected one of `One`, `Two`, \
`Three`",
+ "Config error: field1: invalid type: string \"testing\", expected usize",
]);
let warn_logs = logger.warn_logs.lock().unwrap();
assert_eq!(warn_logs.as_slice(), [
"Config warning: field1 has been deprecated; use field2 instead",
"Config warning: enom_error has been deprecated",
"Config warning: gone has been removed; it's gone",
+ "Unused config key: field3",
]);
}
@@ -170,7 +173,7 @@ impl Log for Logger {
fn field_replacement() {
let mut test = Test::default();
- let value = serde_yaml::to_value(13).unwrap();
+ let value = toml::Value::Integer(13);
test.replace("nesting.field2", value).unwrap();
assert_eq!(test.nesting.field2, Some(13));
@@ -180,7 +183,7 @@ fn field_replacement() {
fn replace_derive() {
let mut test = Test::default();
- let value = serde_yaml::to_value(9).unwrap();
+ let value = toml::Value::Integer(9);
test.replace("nesting.newtype", value).unwrap();
assert_eq!(test.nesting.newtype, NewType(9));
@@ -190,7 +193,7 @@ fn replace_derive() {
fn replace_flatten() {
let mut test = Test::default();
- let value = serde_yaml::to_value(7).unwrap();
+ let value = toml::Value::Integer(7);
test.replace("flatty", value).unwrap();
assert_eq!(test.flatten.flatty, 7);
diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml
index 7d354f39..9844939f 100644
--- a/alacritty_terminal/Cargo.toml
+++ b/alacritty_terminal/Cargo.toml
@@ -29,6 +29,7 @@ parking_lot = "0.12.0"
regex-automata = "0.1.9"
serde = { version = "1", features = ["derive", "rc"] }
serde_yaml = "0.8"
+toml = "0.7.1"
unicode-width = "0.1"
vte = { version = "0.11.1", default-features = false, features = ["ansi", "serde"] }
diff --git a/alacritty_terminal/src/ansi.rs b/alacritty_terminal/src/ansi.rs
index b596cc82..5a28bda5 100644
--- a/alacritty_terminal/src/ansi.rs
+++ b/alacritty_terminal/src/ansi.rs
@@ -52,11 +52,7 @@ impl<'de> serde::Deserialize<'de> for CursorShapeShim {
}
impl alacritty_config::SerdeReplace for CursorShapeShim {
- fn replace(
- &mut self,
- key: &str,
- value: serde_yaml::Value,
- ) -> Result<(), Box<dyn std::error::Error>> {
+ fn replace(&mut self, key: &str, value: toml::Value) -> Result<(), Box<dyn std::error::Error>> {
if !key.is_empty() {
return Err(format!("Fields \"{0}\" do not exist", key).into());
}
diff --git a/docs/features.md b/docs/features.md
index a97c143d..c1fff46e 100644
--- a/docs/features.md
+++ b/docs/features.md
@@ -14,8 +14,8 @@ opening URLs with the keyboard. By default you can launch it using
### Motion
The cursor motions are setup by default to mimic vi, however they are fully
-configurable. If you don't like vi's bindings, take a look at the [configuration
-file] to change the various movements.
+configurable. If you don't like vi's bindings, take a look at the [onfiguration
+file to change the various movements.
### Selection
@@ -77,8 +77,6 @@ file. If an application captures your mouse clicks, which is indicated by a
change in mouse cursor shape, you're required to hold <kbd>Shift</kbd> to bypass
that.
-[configuration file]: ../alacritty.yml
-
## Multi-Window
Alacritty supports running multiple terminal emulators from the same Alacritty
diff --git a/extra/alacritty.yml b/extra/alacritty.yml
deleted file mode 120000
index 2db9ba40..00000000
--- a/extra/alacritty.yml
+++ /dev/null
@@ -1 +0,0 @@
-../alacritty.yml \ No newline at end of file
diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty
index c4f586bb..6f21f450 100644
--- a/extra/completions/_alacritty
+++ b/extra/completions/_alacritty
@@ -16,7 +16,7 @@ _alacritty() {
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED: ' \
-'--config-file=[Specify alternative configuration file \[default\: \$XDG_CONFIG_HOME/alacritty/alacritty.yml\]]:CONFIG_FILE:_files' \
+'--config-file=[Specify alternative configuration file \[default\: \$XDG_CONFIG_HOME/alacritty/alacritty.toml\]]:CONFIG_FILE:_files' \
'--socket=[Path for IPC socket creation]:SOCKET:_files' \
'*-o+[Override configuration file options \[example\: cursor.style=Beam\]]:OPTION: ' \
'*--option=[Override configuration file options \[example\: cursor.style=Beam\]]:OPTION: ' \
@@ -116,6 +116,21 @@ esac
;;
esac
;;
+(migrate)
+_arguments "${_arguments_options[@]}" \
+'-c+[Path to the configuration file]:CONFIG_FILE:_files' \
+'--config-file=[Path to the configuration file]:CONFIG_FILE:_files' \
+'-d[Only output TOML config to stdout]' \
+'--dry-run[Only output TOML config to stdout]' \
+'-i[Do not recurse over imports]' \
+'--skip-imports[Do not recurse over imports]' \
+'--skip-renames[Do not move renamed fields to their new location]' \
+'-s[Do not output to STDOUT]' \
+'--silent[Do not output to STDOUT]' \
+'-h[Print help]' \
+'--help[Print help]' \
+&& ret=0
+;;
(help)
_arguments "${_arguments_options[@]}" \
":: :_alacritty__help_commands" \
@@ -152,6 +167,10 @@ _arguments "${_arguments_options[@]}" \
;;
esac
;;
+(migrate)
+_arguments "${_arguments_options[@]}" \
+&& ret=0
+;;
(help)
_arguments "${_arguments_options[@]}" \
&& ret=0
@@ -169,6 +188,7 @@ esac
_alacritty_commands() {
local commands; commands=(
'msg:Send a message to the Alacritty socket' \
+'migrate:Migrate the configuration file' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'alacritty commands' commands "$@"
@@ -207,6 +227,7 @@ _alacritty__msg__help__create-window_commands() {
_alacritty__help_commands() {
local commands; commands=(
'msg:Send a message to the Alacritty socket' \
+'migrate:Migrate the configuration file' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'alacritty help commands' commands "$@"
@@ -230,6 +251,16 @@ _alacritty__msg__help__help_commands() {
local commands; commands=()
_describe -t commands 'alacritty msg help help commands' commands "$@"
}
+(( $+functions[_alacritty__help__migrate_commands] )) ||
+_alacritty__help__migrate_commands() {
+ local commands; commands=()
+ _describe -t commands 'alacritty help migrate commands' commands "$@"
+}
+(( $+functions[_alacritty__migrate_commands] )) ||
+_alacritty__migrate_commands() {
+ local commands; commands=()
+ _describe -t commands 'alacritty migrate commands' commands "$@"
+}
(( $+functions[_alacritty__help__msg_commands] )) ||
_alacritty__help__msg_commands() {
local commands; commands=(
diff --git a/extra/completions/alacritty.bash b/extra/completions/alacritty.bash
index bb70ef3f..f7f2caf1 100644
--- a/extra/completions/alacritty.bash
+++ b/extra/completions/alacritty.bash
@@ -15,12 +15,18 @@ _alacritty() {
alacritty,help)
cmd="alacritty__help"
;;
+ alacritty,migrate)
+ cmd="alacritty__migrate"
+ ;;
alacritty,msg)
cmd="alacritty__msg"
;;
alacritty__help,help)
cmd="alacritty__help__help"
;;
+ alacritty__help,migrate)
+ cmd="alacritty__help__migrate"
+ ;;
alacritty__help,msg)
cmd="alacritty__help__msg"
;;
@@ -55,7 +61,7 @@ _alacritty() {
case "${cmd}" in
alacritty)
- opts="-q -v -o -e -T -h -V --print-events --ref-test --embed --config-file --socket --option --working-directory --hold --command --title --class --help --version msg help"
+ opts="-q -v -o -e -T -h -V --print-events --ref-test --embed --config-file --socket --option --working-directory --hold --command --title --class --help --version msg migrate help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -113,7 +119,7 @@ _alacritty() {
return 0
;;
alacritty__help)
- opts="msg help"
+ opts="msg migrate help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -140,6 +146,20 @@ _alacritty() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
+ alacritty__help__migrate)
+ opts=""
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
alacritty__help__msg)
opts="create-window config"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
@@ -182,6 +202,28 @@ _alacritty() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
+ alacritty__migrate)
+ opts="-c -d -i -s -h --config-file --dry-run --skip-imports --skip-renames --silent --help"
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --config-file)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ -c)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
alacritty__msg)
opts="-s -h --socket --help create-window config help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
diff --git a/extra/completions/alacritty.fish b/extra/completions/alacritty.fish
index 2d80be62..fe02ea82 100644
--- a/extra/completions/alacritty.fish
+++ b/extra/completions/alacritty.fish
@@ -1,5 +1,5 @@
complete -c alacritty -n "__fish_use_subcommand" -l embed -d 'X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)' -r
-complete -c alacritty -n "__fish_use_subcommand" -l config-file -d 'Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.yml]' -r -F
+complete -c alacritty -n "__fish_use_subcommand" -l config-file -d 'Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.toml]' -r -F
complete -c alacritty -n "__fish_use_subcommand" -l socket -d 'Path for IPC socket creation' -r -F
complete -c alacritty -n "__fish_use_subcommand" -s o -l option -d 'Override configuration file options [example: cursor.style=Beam]' -r
complete -c alacritty -n "__fish_use_subcommand" -l working-directory -d 'Start the shell in the specified working directory' -r -F
@@ -14,6 +14,7 @@ complete -c alacritty -n "__fish_use_subcommand" -l hold -d 'Remain open after c
complete -c alacritty -n "__fish_use_subcommand" -s h -l help -d 'Print help'
complete -c alacritty -n "__fish_use_subcommand" -s V -l version -d 'Print version'
complete -c alacritty -n "__fish_use_subcommand" -f -a "msg" -d 'Send a message to the Alacritty socket'
+complete -c alacritty -n "__fish_use_subcommand" -f -a "migrate" -d 'Migrate the configuration file'
complete -c alacritty -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s s -l socket -d 'IPC socket connection path override' -r -F
complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help'
@@ -32,7 +33,14 @@ complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subco
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process'
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "config" -d 'Update the Alacritty configuration'
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from help" -f -a "msg" -d 'Send a message to the Alacritty socket'
-complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s c -l config-file -d 'Path to the configuration file' -r -F
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s d -l dry-run -d 'Only output TOML config to stdout'
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s i -l skip-imports -d 'Do not recurse over imports'
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -l skip-renames -d 'Do not move renamed fields to their new location'
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s s -l silent -d 'Do not output to STDOUT'
+complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s h -l help -d 'Print help'
+complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "msg" -d 'Send a message to the Alacritty socket'
+complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "migrate" -d 'Migrate the configuration file'
+complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c alacritty -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config" -f -a "create-window" -d 'Create a new window in the same Alacritty process'
complete -c alacritty -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config" -f -a "config" -d 'Update the Alacritty configuration'
diff --git a/extra/man/alacritty-bindings.5.scd b/extra/man/alacritty-bindings.5.scd
new file mode 100644
index 00000000..2db753b1
--- /dev/null
+++ b/extra/man/alacritty-bindings.5.scd
@@ -0,0 +1,478 @@
+ALACRITTY-BINDINGS(5)
+
+# NAME
+
+Alacritty Bindings - Default configuration file bindings
+
+# SYNOPSIS
+
+This page documents all key and mouse bindings for the default Alacritty
+configuration. See *alacritty*(5) for full configuration format documentation.
+
+# Mouse Bindings
+
+[[ *mouse*
+:[ *mods*
+:[ *action*
+| _"Right"_
+:[
+: _"ExpandSelection"_
+| _"Right"_
+: _"Control"_
+: _"ExpandSelection"_
+| _"Middle"_
+: _"~Vi"_
+: _"PasteSelection"_
+
+# Key Bindings
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action* / *chars*
+| _"Paste"_
+:[
+:[
+: _"Paste"_
+| _"Copy"_
+:[
+:[
+: _"Copy"_
+| _"L"_
+: _"Control"_
+:[
+: _"ClearLogNotice"_
+| _"L"_
+: _"Control"_
+: _"~Vi|~Search"_
+: *chars*: _"\\u000c"_
+| _"PageUp"_
+: _"Shift"_
+: _"~Alt"_
+: _"ScrollPageUp"_
+| _"PageDown"_
+: _"Shift"_
+: _"~Alt"_
+: _"ScrollPageDown"_
+| _"Home"_
+: _"Shift"_
+: _"~Alt"_
+: _"ScrollToTop"_
+| _"End"_
+: _"Shift"_
+: _"~Alt"_
+: _"ScrollToBottom"_
+
+## Vi Mode
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action*
+| _"Space"_
+: _"Shift|Control"_
+: _"~Search"_
+: _"ToggleViMode"_
+| _"Space"_
+: _"Shift|Control"_
+: _"Vi|~Search"_
+: _"ScrollToBottom"_
+| _"Escape"_
+:[
+: _"Vi|~Search"_
+: _"ClearSelection"_
+| _"I"_
+:[
+: _"Vi|~Search"_
+: _"ToggleViMode"_
+| _"I"_
+:[
+: _"Vi|~Search"_
+: _"ScrollToBottom"_
+| _"C"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ToggleViMode"_
+| _"Y"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollLineUp"_
+| _"E"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollLineDown"_
+| _"G"_
+:[
+: _"Vi|~Search"_
+: _"ScrollToTop"_
+| _"G"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"ScrollToBottom"_
+| _"B"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollPageUp"_
+| _"F"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollPageDown"_
+| _"U"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollHalfPageUp"_
+| _"D"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ScrollHalfPageDown"_
+| _"Y"_
+:[
+: _"Vi|~Search"_
+: _"Copy"_
+| _"Y"_
+:[
+: _"Vi|~Search"_
+: _"ClearSelection"_
+| _"Copy"_
+:[
+: _"Vi|~Search"_
+: _"ClearSelection"_
+| _"V"_
+:[
+: _"Vi|~Search"_
+: _"ToggleNormalSelection"_
+| _"V"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"ToggleLineSelection"_
+| _"V"_
+: _"Control"_
+: _"Vi|~Search"_
+: _"ToggleBlockSelection"_
+| _"V"_
+: _"Alt"_
+: _"Vi|~Search"_
+: _"ToggleSemanticSelection"_
+| _"Return"_
+:[
+: _"Vi|~Search"_
+: _"Open"_
+| _"Z"_
+:[
+: _"Vi|~Search"_
+: _"CenterAroundViCursor"_
+| _"K"_
+:[
+: _"Vi|~Search"_
+: _"Up"_
+| _"J"_
+:[
+: _"Vi|~Search"_
+: _"Down"_
+| _"H"_
+:[
+: _"Vi|~Search"_
+: _"Left"_
+| _"L"_
+:[
+: _"Vi|~Search"_
+: _"Right"_
+| _"Up"_
+:[
+: _"Vi|~Search"_
+: _"Up"_
+| _"Down"_
+:[
+: _"Vi|~Search"_
+: _"Down"_
+| _"Left"_
+:[
+: _"Vi|~Search"_
+: _"Left"_
+| _"Right"_
+:[
+: _"Vi|~Search"_
+: _"Right"_
+| _"Key0"_
+:[
+: _"Vi|~Search"_
+: _"First"_
+| _"Key4"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"Last"_
+| _"Key6"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"FirstOccupied"_
+| _"H"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"High"_
+| _"M"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"Middle"_
+| _"L"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"Low"_
+| _"B"_
+:[
+: _"Vi|~Search"_
+: _"SemanticLeft"_
+| _"W"_
+:[
+: _"Vi|~Search"_
+: _"SemanticRight"_
+| _"E"_
+:[
+: _"Vi|~Search"_
+: _"SemanticRightEnd"_
+| _"B"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"WordLeft"_
+| _"W"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"WordRight"_
+| _"E"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"WordRightEnd"_
+| _"Key5"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"Bracket"_
+| _"Slash"_
+:[
+: _"Vi|~Search"_
+: _"SearchForward"_
+| _"Slash"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"SearchBackward"_
+| _"N"_
+:[
+: _"Vi|~Search"_
+: _"SearchNext"_
+| _"N"_
+: _"Shift"_
+: _"Vi|~Search"_
+: _"SearchPrevious"_
+
+
+## Search Mode
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action*
+| _"Return"_
+:[
+: _"Search|Vi"_
+: _"SearchConfirm"_
+| _"Escape"_
+:[
+: _"Search"_
+: _"SearchCancel"_
+| _"C"_
+: _"Control"_
+: _"Search"_
+: _"SearchCancel"_
+| _"U"_
+: _"Control"_
+: _"Search"_
+: _"SearchClear"_
+| _"W"_
+: _"Control"_
+: _"Search"_
+: _"SearchDeleteWord"_
+| _"P"_
+: _"Control"_
+: _"Search"_
+: _"SearchHistoryPrevious"_
+| _"N"_
+: _"Control"_
+: _"Search"_
+: _"SearchHistoryNext"_
+| _"Up"_
+:[
+: _"Search"_
+: _"SearchHistoryPrevious"_
+| _"Down"_
+:[
+: _"Search"_
+: _"SearchHistoryNext"_
+| _"Return"_
+:[
+: _"Search|~Vi"_
+: _"SearchFocusNext"_
+
+## Windows, Linux, and BSD only
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action*
+| _"V"_
+: _"Control|Shift"_
+: _"~Vi"_
+: _"Paste"_
+| _"C"_
+: _"Control|Shift"_
+:[
+: _"Copy"_
+| _"F"_
+: _"Control|Shift"_
+: _"~Search"_
+: _"SearchForward"_
+| _"B"_
+: _"Control|Shift"_
+: _"~Search"_
+: _"SearchBackward"_
+| _"C"_
+: _"Control|Shift"_
+: _"Vi|~Search"_
+: _"ClearSelection"_
+| _"Insert"_
+: _"Shift"_
+:[
+: _"PasteSelection"_
+| _"Key0"_
+: _"Control"_
+:[
+: _"ResetFontSize"_
+| _"Equals"_
+: _"Control"_
+:[
+: _"IncreaseFontSize"_
+| _"Plus"_
+: _"Control"_
+:[
+: _"IncreaseFontSize"_
+| _"NumpadAdd"_
+: _"Control"_
+:[
+: _"IncreaseFontSize"_
+| _"Minus"_
+: _"Control"_
+:[
+: _"DecreaseFontSize"_
+| _"NumpadSubtract"_
+: _"Control"_
+:[
+: _"DecreaseFontSize"_
+
+## Windows only
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action*
+| _"Return"_
+: _"Alt"_
+:[
+: _"ToggleFullscreen"_
+
+## macOS only
+
+[[ *key*
+:[ *mods*
+:[ *mode*
+:[ *action* / *chars*
+| _"K"_
+: _"Command"_
+: _"~Vi|~Search"_
+: *chars*: _"\\u000c"_
+| _"K"_
+: _"Command"_
+: _"~Vi|~Search"_
+: _"ClearHistory"_
+| _"Key0"_
+: _"Command"_
+:[
+: _"ResetFontSize"_
+| _"Equals"_
+: _"Command"_
+:[
+: _"IncreaseFontSize"_
+| _"Plus"_
+: _"Command"_
+:[
+: _"IncreaseFontSize"_
+| _"NumpadAdd"_
+: _"Command"_
+:[
+: _"IncreaseFontSize"_
+| _"Minus"_
+: _"Command"_
+:[
+: _"DecreaseFontSize"_
+| _"NumpadSubtract"_
+: _"Command"_
+:[
+: _"DecreaseFontSize"_
+| _"V"_
+: _"Command"_
+:[
+: _"Paste"_
+| _"C"_
+: _"Command"_
+:[
+: _"Copy"_
+| _"C"_
+: _"Command"_
+: _"Vi|~Search"_
+: _"ClearSelection"_
+| _"H"_
+: _"Command"_
+:[
+: _"Hide"_
+| _"H"_
+: _"Command|Alt"_
+:[
+: _"HideOtherApplications"_
+| _"M"_
+: _"Command"_
+:[
+: _"Minimize"_
+| _"Q"_
+: _"Command"_
+:[
+: _"Quit"_
+| _"W"_
+: _"Command"_
+:[
+: _"Quit"_
+| _"N"_
+: _"Command"_
+:[
+: _"CreateNewWindow"_
+| _"F"_
+: _"Command|Control"_
+:[
+: _"ToggleFullscreen"_
+| _"F"_
+: _"Command"_
+: _"~Search"_
+: _"SearchForward"_
+| _"B"_
+: _"Command"_
+: _"~Search"_
+: _"SearchBackward"_
+
+# SEE ALSO
+
+See the alacritty github repository at https://github.com/alacritty/alacritty
+for the full documentation.
+
+# BUGS
+
+Found a bug? Please report it at https://github.com/alacritty/alacritty/issues.
+
+# MAINTAINERS
+
+- Christian Duerr <contact@christianduerr.com>
+- Kirill Chibisov <contact@kchibisov.com>
diff --git a/extra/man/alacritty.1.scd b/extra/man/alacritty.1.scd
index 4278eba1..46d34e7b 100644
--- a/extra/man/alacritty.1.scd
+++ b/extra/man/alacritty.1.scd
@@ -50,12 +50,12 @@ set of features with high performance.
Specify alternative configuration file
Alacritty looks for the configuration file at the following paths:
- . $XDG_CONFIG_HOME/alacritty/alacritty.yml
- . $XDG_CONFIG_HOME/alacritty.yml
- . $HOME/.config/alacritty/alacritty.yml
- . $HOME/.alacritty.yml
+ . $XDG_CONFIG_HOME/alacritty/alacritty.toml
+ . $XDG_CONFIG_HOME/alacritty.toml
+ . $HOME/.config/alacritty/alacritty.toml
+ . $HOME/.alacritty.toml
- On Windows, the configuration file is located at %APPDATA%\\alacritty\\alacritty.yml.
+ On Windows, the configuration file is located at %APPDATA%\\alacritty\\alacritty.toml
*--embed* <parent>
X11 window ID to embed Alacritty within (decimal or hexadecimal with _0x_ prefix)
diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd
new file mode 100644
index 00000000..055cacfa
--- /dev/null
+++ b/extra/man/alacritty.5.scd
@@ -0,0 +1,823 @@
+ALACRITTY(5)
+
+# NAME
+
+Alacritty - TOML configuration file format
+
+# SYNTAX
+
+Alacritty's configuration file uses the TOML format. The format's specification
+can be found at https://toml.io/en/v1.0.0.
+
+# GENERAL
+
+This section documents the root level of the configuration file.
+
+*import* [<string>,]
+
+ Import additional configuration files
+
+ Imports are loaded in order, skipping all missing files, with the importing
+ file being loaded last. If a field is already present in a previous import,
+ it will be replaced.
+
+ All imports must either be absolute paths starting with _/_, or paths
+ relative to the user's home directory starting with _~/_.
+
+*working_directory* <string> | "None"
+
+ Directory the shell is started in. When this is unset, or _None_, the
+ working directory of the parent process will be used.
+
+ Default: _None_
+
+*live_config_reload* <boolean>
+
+ Live config reload (changes require restart)
+
+*ipc_socket* <boolean> _(unix only)_
+
+ Offer IPC using _alacritty msg_
+
+# ENV
+
+All key-value pairs in the *env* section will be added as environment variables
+for any process spawned by Alacritty, including its shell. Some entries may
+override variables set by alacritty itself.
+
+```
+[env]
+TERM = "alacritty"
+```
+
+# WINDOW
+
+This section documents the *[window]* table of the configuration file.
+
+*dimensions* { columns = <integer>, lines = <integer> }
+
+ Window dimensions (changes require restart)
+
+ Number of lines/columns (not pixels) in the terminal. Both lines and columns
+ must be non-zero for this to take effect. The number of columns must be at
+ least _2_, while using a value of _0_ for columns and lines will fall back
+ to the window manager's recommended size
+
+ Default: _{ column = 0, lines = 0 }_
+
+*padding* { x = <integer>, y = <integer> }
+
+ Blank space added around the window in pixels. This padding is scaled
+ by DPI and the specified value is always added at both opposing sides.
+
+ Default: _{ x = 0, y = 0 }_
+
+*dynamic_padding* <boolean>
+
+ Spread additional padding evenly around the terminal content.
+
+ Default: _false_
+
+*decorations* "Full" | "None" | "Transparent" | "Buttonless"
+
+ Window decorations
+
+ *Full*
+ Borders and title bar
+ *None*
+ Neither borders nor title bar
+ *Transparent* _(macOS only)_
+ Title bar, transparent background and title bar buttons
+ *Buttonless* _(macOS only)_
+ Title bar, transparent background and no title bar buttons
+
+ Default: _"Full"_
+
+*opacity* <float>
+
+ Background opacity as a floating point number from _0.0_ to _1.0_. The value
+ \_0.0_ is completely transparent and _1.0_ is opaque.
+
+ Default: _1.0_
+
+*startup_mode* "Windowed" | "Maximized" | "Fullscreen" | "SimpleFullscreen"
+
+ Startup mode (changes require restart)
+
+ Default: _"Windowed"_
+
+*title* <string>
+
+ Window title
+
+ Default: _"Alacritty"_
+
+*dynamic_title* <boolean>
+
+ Allow terminal applications to change Alacritty's window title.
+
+ Default: _true_
+
+*class* { instance = <string>, general = <string> } _(Linux/BSD only)_
+
+ Window class
+
+ On Wayland, *general* is used as _app\_id_ and *instance* is ignored.
+
+ Default: _{ instance = "Alacritty", general = "Alacritty" }_
+
+*decoration_theme_variant* "Dark" | "Light" | "None"
+
+ Override the variant of the System theme/GTK theme/Wayland client side
+ decorations. Set this to _"None"_ to use the system's default theme variant.
+
+ Default: _"None"_
+
+*resize_increments* <boolean>
+
+ Prefer resizing window by discrete steps equal to cell dimensions.
+
+ Default: _false_
+
+*option_as_alt* "OnlyLeft" | "OnlyRight" | "Both" | "None" _(macos only)_
+
+ Make _Option_ key behave as _Alt_
+
+ Default: _"None"_
+
+# Scrolling
+
+This section documents the *[scrolling]* table of the configuration file.
+
+*history* <integer>
+
+ Maximum number of lines in the scrollback buffer.++
+Specifying _0_ will disable scrolling.++
+Limited to _100000_.
+
+ Default: _10000_
+
+*multiplier* <integer>
+
+ Number of line scrolled for every input scroll increment.
+
+ Default: _3_
+
+# Font
+
+This section documents the *[font]* table of the configuration file.
+
+*normal* { family = <string>, style = <string> }
+
+ Default:
+ Linux/BSD: _{ family = "monospace", style = "Regular" }_++
+Windows: _{ family = "Consolas", style = "Regular" }_++
+macOS: _{ family = "Menlo", style = "Regular" }_
+
+*bold* { family = <string>, style = <string> }
+
+ If the family is not specified, it will fall back to the value specified for
+ the normal font.
+
+ Default: _{ style = "Bold" }_
+
+*italic* { family = <string>, style = <string> }
+
+ If the family is not specified, it will fall back to the value specified for
+ the normal font.
+
+ Default: _{ style = "Italic" }_
+
+*bold_italic* { family = <string>, style = <string> }
+
+ If the family is not specified, it will fall back to the value specified for
+ the normal font.
+
+ Default: _{ style = "Bold Italic" }_
+
+*size* <float>
+
+ Font size in points.
+
+ Default: _11.0_
+
+*offset* { x = <integer>, y = <integer> }
+
+ Offset is the extra space around each character. _y_ can be thought of as
+ modifying the line spacing, and _x_ as modifying the letter spacing.
+
+ Default: _{ x = 0, y = 0 }_
+
+*glyph_offset* { x = <integer>, y = <integer> }
+
+ Glyph offset determines the locations of the glyphs within their cells with
+ the default being at the bottom. Increasing _x_ moves the glyph to the
+ right, increasing _y_ moves the glyph upward.
+
+*builtin_box_drawing* <boolean>
+
+ When _true_, Alacritty will use a custom built-in font for box drawing
+ characters (Unicode points _U+2500_ - _U+259f_).
+
+ Default: _true_
+
+# Colors
+
+This section documents the *[colors]* table of the configuration file.
+
+Colors are specified using their hexadecimal values with a _#_ prefix: _#RRGGBB_
+
+*primary*
+
+ *foreground* <string>
+
+ Default: _"#1d1f21"_
+
+ *background* <string>
+
+ Default: _"#c5c8c6"_
+
+ *dim_foreground* <string>
+
+ If this is not set, the color is automatically calculated based on the
+ foreground color.
+
+ Default: _"#828482"_
+
+ *bright_foreground* <string>
+
+ This color is only used when _draw\_bold\_text\_with\_bright\_colors_ is
+ _true_.
+
+ If this is not set, the normal foreground will be used.
+
+ Default: _"None"_
+
+*cursor* { text = <string>, cursor = <string> }
+
+ Colors which should be used to draw the terminal cursor.
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ Default: _{ text = "CellBackground", cursor: "CellForeground" }_
+
+*vi_mode_cursor* { text = <string>, cursor = <string> }
+
+ Colors for the cursor when the vi mode is active.
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ Default: _{ text = "CellBackground", cursor: "CellForeground" }_
+
+*search*
+
+ Colors used for the search bar and match highlighting.
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ *matches* { foreground = <string>, background = <string> }
+
+ Default: _{ foreground = "#000000", background: "#ffffff" }_
+
+ *focused_match* { foreground = <string>, background = <string> }
+
+ Default: _{ foreground = "#ffffff", background: "#000000" }_
+
+*hints*
+
+ *start* { foreground = <string>, background = <string> }
+
+ First character in the hint label
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ Default: _{ foreground = "#1d1f21", background = "#e9ff5e" }_
+
+ *end* { foreground = <string>, background = <string> }
+
+ All characters after the first one in the hint label
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ Default: _{ foreground = "#e9ff5e", background = "#1d1f21" }_
+
+*line_indicator* { foreground = <string>, background = <string> }
+
+ Color used for the indicator displaying the position in history during
+ search and vi mode.
+
+ Setting this to _"None"_ will use the opposing primary color.
+
+ Default: _{ foreground = "None", background = "None" }_
+
+*footer_bar* { foreground = <string>, background = <string> }
+
+ Color used for the footer bar on the bottom, used by search regex input,
+ hyperlink URI preview, etc.
+
+ Default: _{ foreground = "#c5c8c6", background = "#1d1f21" }_
+
+*selection* { text = <string>, background = <string> }
+
+ Colors used for drawing selections.
+
+ Allowed values are hexadecimal colors like _#ff00ff_, or
+ _CellForeground_/_CellBackground_, which references the affected cell.
+
+ Default: _{ text = "CellBackground", background = "CellForeground" }_
+
+*normal*
+
+ *black* <string>
+ Default: _"#1d1f21"_
+ *red* <string>
+ Default: _"#cc6666"_
+ *green* <string>
+ Default: _"#b5bd68"_
+ *yellow* <string>
+ Default: _"#f0c674"_
+ *blue* <string>
+ Default: _"#81a2be"_
+ *magenta* <string>
+ Default: _"#b294bb"_
+ *cyan* <string>
+ Default: _"#8abeb7"_
+ *white* <string>
+ Default: _"#c5c8c6"_
+
+*bright*
+
+ *black* <string>
+ Default: _"#666666"_
+ *red* <string>
+ Default: _"#d54e53"_
+ *green* <string>
+ Default: _"#b9ca4a"_
+ *yellow* <string>
+ Default: _"#e7c547"_
+ *blue* <string>
+ Default: _"#7aa6da"_
+ *magenta* <string>
+ Default: _"#c397d8"_
+ *cyan* <string>
+ Default: _"#70c0b1"_
+ *white* <string>
+ Default: _"#eaeaea"_
+
+*dim*
+
+ If the dim colors are not set, they will be calculated automatically based
+ on the _normal_ colors.
+
+ *black* <string>
+ Default: _"#131415"_
+ *red* <string>
+ Default: _"#864343"_
+ *green* <string>
+ Default: _"#777c44"_
+ *yellow* <string>
+ Default: _"#9e824c"_
+ *blue* <string>
+ Default: _"#556a7d"_
+ *magenta* <string>
+ Default: _"#75617b"_
+ *cyan* <string>
+ Default: _"#5b7d78"_
+ *white* <string>
+ Default: _"#828482"_
+
+*indexed_colors* [{ index = <integer>, color = <string> },]
+
+ The indexed colors include all colors from 16 to 256.
+ When these are not set, they're filled with sensible defaults.
+
+ Default: _[]_
+
+*transparent_background_colors* <boolean>
+
+ Whether or not _window.opacity_ applies to all cell backgrounds, or only to
+ the default background. When set to _true_ all cells will be transparent
+ regardless of their background color.
+
+ Default: _false_
+
+*draw_bold_text_with_bright_colors* <boolean>
+
+ When _true_, bold text is drawn using the bright color variants.
+
+# Bell
+
+This section documents the *[bell]* table of the configuration file.
+
+*animation* "Ease" | "EaseOut" | "EaseOutSine" | "EaseOutQuad" | "EaseOutCubic"
+\| "EaseOutQuart" | "EaseOutQuint" | "EaseOutExpo" | "EaseOutCirc" | "Linear"
+
+ Visual bell animation effect for flashing the screen when the visual bell is rung.
+
+ Default: _"EaseOutExpo"_
+
+*duration* <integer>
+
+ Duration of the visual bell flash in milliseconds. A `duration` of `0` will
+ disable the visual bell animation.
+
+ Default: _0_
+
+*color* <string>
+
+ Visual bell animation color.
+
+ Default: _"#ffffff"_
+
+*command* <string> | { program = <string>, args = [<string>,] }
+
+ This program is executed whenever the bell is rung.
+
+ When set to _"None"_, no command will be executed.
+
+ Default: _"None"_
+
+# Selection
+
+This section documents the *[selection]* table of the configuration file.
+
+*semantic_escape_chars* <string>
+
+ This string contains all characters that are used as separators for
+ "semantic words" in Alacritty.
+
+ Default: _",│`|:\"' ()[]{}<>\t"_
+
+*save_to_clipboard* <boolean>
+
+ When set to _true_, selected text will be copied to the primary clipboard.
+
+ Default: _false_
+
+# Cursor
+
+This section documents the *[cursor]* table of the configuration file.
+
+*style*
+
+ *shape* "Block" | "Underline" | "Beam"
+
+ Default: _"Block"_
+
+ *blinking* "Never" | "Off" | "On" | "Always"
+
+ *Never*
+ Prevent the cursor from ever blinking
+ *Off*
+ Disable blinking by default
+ *On*
+ Enable blinking by default
+ *Always*
+ Force the cursor to always blink
+
+ Default: _"Off"_
+
+*vi_mode_style*
+
+ If the vi mode cursor style is _None_ or not specified, it will fall back to
+ the active value of the normal cursor.
+
+ See _cursor.style_ for available options.
+
+ Default: _None_
+
+*blink_interval* <integer>
+
+ Cursor blinking interval in milliseconds.
+
+ Default: _750_
+
+*blink_timeout* <integer>
+
+ Time after which cursor stops blinking, in seconds.
+
+ Specifying _0_ will disable timeout for blinking.
+
+ Default: _5_
+
+*unfocused_hollow* <boolean>
+
+ When this is _true_, the cursor will be rendered as a hollow box when the
+ window is not focused.
+
+ Default: _true_
+
+*thickness* <float>
+
+ Thickness of the cursor relative to the cell width as floating point number
+ from _0.0_ to _1.0_.
+
+ Default: _0.15_
+
+*shell* <string> | { program = <string>, args = [<string>,] }
+
+ You can set _shell.program_ to the path of your favorite shell, e.g.
+ _/bin/zsh_. Entries in _shell.args_ are passed as arguments to the shell.
+
+ Default:
+ Linux/BSD/macOS: _$SHELL_ or the user's login shell, if _$SHELL_ is unset++
+Windows: _"powershell"_
+
+# Mouse
+
+This section documents the *[mouse]* table of the configuration file.
+
+*double_click* { threshold = <integer> }
+
+ Set maximum time between double-clicks in milliseconds.
+
+ Default: _300_
+
+*triple_click* { threshold = <integer> }
+
+ Set maximum time between triple-clicks in milliseconds.
+
+ Default: _300_
+
+*hide_when_typing* <boolean>
+
+ When this is _true_, the cursor is temporarily hidden when typing.
+
+ Default: _false_
+
+# Hints
+
+This section documents the *[hints]* table of the configuration file.
+
+Terminal hints can be used to find text or hyperlinks in the visible part of the
+terminal and pipe it to other applications.
+
+*alphabet* <string>
+
+ Keys used for the hint labels.
+
+ Default: _"jfkdls;ahgurieowpq"_
+
+*enabled* [{ <regex>, <hyperlinks>, <post_processing>, <action>, <command> <binding>, <mouse> },]
+
+Array with all available hints.
+
+Each hint must have at least one of _regex_ or _hyperlinks_ and either an
+_action_ or a _command_.
+
+ *regex* <string>
+
+ Regex each line will be compared against.
+
+ *hyperlinks* <boolean>
+
+ When this is _true_, all OSC 8 escape sequence hyperlinks will be
+ included in the hints.
+
+ *post_processing* <boolean>
+
+ When this is _true_, heuristics will be used to shorten the match if
+ there are characters likely not to be part of the hint (e.g. a trailing
+ _._). This is most useful for URIs and applies only to _regex_ matches.
+
+ *action* "Copy" | "Paste" | "Select" | "MoveViModeCursor"
+
+ *Copy*
+ Copy the hint's text to the clipboard.
+ *Paste*
+ Paste the hint's text to the terminal or search.
+ *Select*
+ Select the hint's text.
+ *MoveViModeCursor*
+ Move the vi mode cursor to the beginning of the hint.
+
+ *command* <string> | { program = <string>, args = [<string>,] }
+
+ Command which will be executed when the hint is clicked or selected with
+ the _binding_.
+
+ The hint's text is always attached as the last argument.
+
+ *binding* { key = <string>, mods = <string>, mode = <string> }
+
+ See _key_bindings_ for documentation on available values.
+
+ This controls which key binding is used to start the keyboard hint
+ selection process.
+
+ *mouse* { mods = <string>, enabled = <boolean> }
+
+ See _key_bindings_ for documentation on available _mods_.
+
+ The _enabled_ field controls if the hint should be underlined when
+ hovering over the hint text with all _mods_ pressed.
+
+Default: _[{
+ regex = "(mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)[^\\u0000-\\u001F\\u007F-\\u009F<>\\"\\\\s{-}\\\\^⟨⟩`]+",++
+hyperlinks = true,++
+post_processing = true,++
+mouse = { enabled = true },++
+binding = { key = "U", mods = "Control | Shift" },
+}]_
+
+# Bindings
+
+This section documents the *mouse_bindings* and *key_bindings* at the root level
+of the configuration file.
+
+*mouse_bindings* [{ <mouse>, <mods>, <mode>, <action> | chars = <string> },]
+
+ See _key_bindings_ for full documentation on _mods_, _mode_, _action_, and
+ _chars_.
+
+ To trigger mouse bindings when an application running within Alacritty
+ captures the mouse, the `Shift` modifier is automatically added as a
+ requirement.
+
+ *mouse* "Middle" | "Left" | "Right" | <number>
+
+ Mouse button which needs to be pressed to trigger this binding.
+
+ *action* <key_bindings.action> | "ExpandSelection"
+
+ *ExpandSelection*
+ Expand the selection to the current mouse cursor location.
+
+*key_bindings* [{ <key>, <mods>, <mode>, <action> | chars = <string> },]
+
+ To unset a default binding, you can use the action _"ReceiveChar"_ to remove
+ it or _"None"_ to inhibit any action.
+
+ Multiple keybindings can be triggered by a single key press and will be
+ executed in the order they are defined in.
+
+ *key* <string>
+
+ Identifier of the binding's key, for example: _"A"_, _"F1"_, or
+ _"Key0"_.
+
+ A full list with available key codes can be found here:++
+https://docs.rs/winit/\*/winit/event/enum.VirtualKeyCode.html#variants
+
+ The _key_ field also supports using scancodes, which are specified as a
+ decimal number.
+
+ *mods* "Command" | "Control" | "Option" | "Super" | "Shift" | "Alt"
+
+ Multiple modifiers can be combined using _|_, like this: _"Control |
+ Shift"_.
+
+ *mode* "AppCursor" | "AppKeypad" | "Search" | "Alt" | "Vi"
+
+ This defines a terminal mode which must be active for this binding to
+ have an effect.
+
+ Prepending _~_ to a mode will require the mode to *not* be active for
+ the binding to take effect.
+
+ Multiple modes can be combined using _|_, like this: _"~Vi|Search"_.
+
+ *chars*
+
+ Writes the specified string to the terminal.
+
+ *action*
+
+ *Up*
+ One line up.
+ *Down*
+ One line down.
+ *Left*
+ One character left.
+ *Right*
+ One character right.
+ *First*
+ First column, or beginning of the line when already at the first column.
+ *Last*
+ Last column, or beginning of the line when already at the last column.
+ *FirstOccupied*
+ First non-empty cell in this terminal row, or first non-empty cell
+ of the line when already at the first cell of the row.
+ *High*
+ Top of the screen.
+ *Middle*
+ Center of the screen.
+ *Low*
+ Bottom of the screen.
+ *SemanticLeft*
+ the previous semantically separated word.
+ *SemanticRight*
+ he next semantically separated word.
+ *SemanticLeftEnd*
+ revious semantically separated word.
+ *SemanticRightEnd*
+ End of the next semantically separated word.
+ *WordLeft*
+ Start of the previous whitespace separated word.
+ *WordRight*
+ Start of the next whitespace separated word.
+ *WordLeftEnd*
+ End of the previous whitespace separated word.
+ *WordRightEnd*
+ End of the next whitespace separated word.
+ *Bracket*
+ Character matching the bracket at the cursor's location.
+ *SearchNext*
+ Beginning of the next match.
+ *SearchPrevious*
+ Beginning of the previous match.
+ *SearchStart*
+ Start of the match to the left of the vi mode cursor.
+ *SearchEnd*
+ End of the match to the right of the vi mode cursor.
+
+ _Search mode exclusive:_
+
+ *SearchFocusNext*
+ Move the focus to the next search match.
+ *SearchFocusPrevious*
+ Move the focus to the previous search match.
+ *SearchConfirm*
+ *SearchCancel*
+ *SearchClear*
+ Reset the search regex.
+ *SearchDeleteWord*
+ Delete the last word in the search regex.
+ *SearchHistoryPrevious*
+ Go to the previous regex in the search history.
+ *SearchHistoryNext*
+ Go to the next regex in the search history.
+
+ _macOS exclusive:_
+
+ *ToggleSimpleFullscreen*
+ Enter fullscreen without occupying another space.
+
+ _Linux/BSD exclusive:_
+
+ *CopySelection*
+ Copy from the selection buffer.
+ *PasteSelection*
+ Paste from the selection buffer.
+
+# Debug
+
+This section documents the *[debug]* table of the configuration file.
+
+Debug options are meant to help troubleshoot issues with Alacritty. These can
+change or be removed entirely without warning, so their stability shouldn't be
+relied upon.
+
+*render_timer* <boolean>
+
+ Display the time it takes to draw each frame.
+
+ Default: _false_
+
+*persistent_logging* <boolean>
+
+ Keep the log file after quitting Alacritty.
+
+ Default: _false_
+
+*log_level* "Off" | "Error" | "Warn" | "Info" | "Debug" | "Trace"
+
+ Default: _"Warn"_
+
+*renderer* "glsl3" | "gles2" | "gles2_pure" | "None"
+
+ Force use of a specific renderer, _"None"_ will use the highest available
+ one.
+
+ Default: _"None"_
+
+*print_events* <boolean>
+
+ Log all received window events.
+
+ Default: _false_
+
+*highlight_damage* <boolean>
+
+ Highlight window damage information.
+
+ Default: _false_
+
+# SEE ALSO
+
+See the alacritty github repository at https://github.com/alacritty/alacritty
+for the full documentation.
+
+# BUGS
+
+Found a bug? Please report it at https://github.com/alacritty/alacritty/issues.
+
+# MAINTAINERS
+
+- Christian Duerr <contact@christianduerr.com>
+- Kirill Chibisov <contact@kchibisov.com>