Repository: wezterm/wezterm
Pull request #6696: Add font configuration option for ActivateCommandPalette, CharSelect, PaneSelect
Author: login: mgpinf
Created: 2025-02-19T06:06:09Z | Merged: 2025-03-09T22:34:33Z

Add configuration option for font for the below entities:
- `ActivateCommandPalette`
- `CharSelect`
- `PaneSelect`

For the above entities, if the font is not set in configuration, it defaults to the font same font as `config.window_frame.font`


Diff:
diff --git a/config/src/config.rs b/config/src/config.rs
index 09064401fdb..e5c739c7437 100644
--- a/config/src/config.rs
+++ b/config/src/config.rs
@@ -142,6 +142,10 @@ pub struct Config {
     #[dynamic(default)]
     pub window_frame: WindowFrameConfig,
 
+    /// Font to use for CharSelect
+    #[dynamic(default)]
+    pub char_select_font: Option<TextStyle>,
+
     #[dynamic(default = "default_char_select_font_size")]
     pub char_select_font_size: f64,
 
@@ -151,6 +155,10 @@ pub struct Config {
     #[dynamic(default = "default_char_select_bg_color")]
     pub char_select_bg_color: RgbaColor,
 
+    /// Font to use for ActivateCommandPalette
+    #[dynamic(default)]
+    pub command_palette_font: Option<TextStyle>,
+
     #[dynamic(default = "default_command_palette_font_size")]
     pub command_palette_font_size: f64,
 
@@ -161,6 +169,10 @@ pub struct Config {
     #[dynamic(default = "default_command_palette_bg_color")]
     pub command_palette_bg_color: RgbaColor,
 
+    /// Font to use for PaneSelect
+    #[dynamic(default)]
+    pub pane_select_font: Option<TextStyle>,
+
     #[dynamic(default = "default_pane_select_font_size")]
     pub pane_select_font_size: f64,
 
diff --git a/docs/config/lua/config/char_select_font.md b/docs/config/lua/config/char_select_font.md
new file mode 100644
index 00000000000..72264bb8569
--- /dev/null
+++ b/docs/config/lua/config/char_select_font.md
@@ -0,0 +1,25 @@
+---
+tags:
+  - appearance
+  - char_select
+  - font
+---
+# `char_select_font`
+
+{{since('nightly')}}
+
+Configures the font to use for character selection. The `char_select_font`
+setting can specify a set of fallbacks and other options, and is described
+in more detail in the [Fonts](../../fonts.md) section.
+
+If not specified, the font is same as the font in `window_frame.font`
+
+You will typically use [wezterm.font](../wezterm/font.md) or
+[wezterm.font_with_fallback](../wezterm/font_with_fallback.md) to specify the
+font.
+
+To specify `char_select_font`:
+
+```lua
+config.char_select_font = wezterm.font 'Roboto'
+```
diff --git a/docs/config/lua/config/command_palette_font.md b/docs/config/lua/config/command_palette_font.md
new file mode 100644
index 00000000000..79dda636a3d
--- /dev/null
+++ b/docs/config/lua/config/command_palette_font.md
@@ -0,0 +1,24 @@
+---
+tags:
+  - font
+  - command_palette
+---
+# `command_palette_font`
+
+{{since('nightly')}}
+
+Configures the font to use for command palette. The `command_palette_font`
+setting can specify a set of fallbacks and other options, and is described
+in more detail in the [Fonts](../../fonts.md) section.
+
+If not specified, the font is same as the font in `window_frame.font`
+
+You will typically use [wezterm.font](../wezterm/font.md) or
+[wezterm.font_with_fallback](../wezterm/font_with_fallback.md) to specify the
+font.
+
+To specify `command_palette_font`:
+
+```lua
+config.command_palette_font = wezterm.font 'Roboto'
+```
diff --git a/docs/config/lua/config/pane_select_font.md b/docs/config/lua/config/pane_select_font.md
new file mode 100644
index 00000000000..06b9f4ccc2b
--- /dev/null
+++ b/docs/config/lua/config/pane_select_font.md
@@ -0,0 +1,25 @@
+---
+tags:
+  - appearance
+  - pane_select
+  - font
+---
+# `pane_select_font`
+
+{{since('nightly')}}
+
+Configures the font to use for pane selection mode. The `pane_select_font`
+setting can specify a set of fallbacks and other options, and is described
+in more detail in the [Fonts](../../fonts.md) section.
+
+If not specified, the font is same as the font in `window_frame.font`
+
+You will typically use [wezterm.font](../wezterm/font.md) or
+[wezterm.font_with_fallback](../wezterm/font_with_fallback.md) to specify the
+font.
+
+To specify `pane_select_font`:
+
+```lua
+config.pane_select_font = wezterm.font 'Roboto'
+```
diff --git a/docs/config/lua/keyassignment/ActivateCommandPalette.md b/docs/config/lua/keyassignment/ActivateCommandPalette.md
index 900f2e874e4..32593580002 100644
--- a/docs/config/lua/keyassignment/ActivateCommandPalette.md
+++ b/docs/config/lua/keyassignment/ActivateCommandPalette.md
@@ -41,6 +41,7 @@ action.
 
 See also:
 
+ * [command_palette_font](../config/command_palette_font.md)
  * [command_palette_font_size](../config/command_palette_font_size.md)
  * [command_palette_fg_color](../config/command_palette_fg_color.md)
  * [command_palette_bg_color](../config/command_palette_bg_color.md)
diff --git a/docs/config/lua/keyassignment/CharSelect.md b/docs/config/lua/keyassignment/CharSelect.md
index 630be9dae02..3c2fe095d97 100644
--- a/docs/config/lua/keyassignment/CharSelect.md
+++ b/docs/config/lua/keyassignment/CharSelect.md
@@ -43,7 +43,7 @@ The default assignment is equivalent to this config:
 
 ```lua
 -- Control the size of the font.
--- Uses the same font as window_frame.font
+-- Uses the same font as window_frame.font if char_select_font option is not set
 -- char_select_font_size = 18.0,
 
 config.keys = {
@@ -73,6 +73,7 @@ The `CharSelect` action accepts a lua table with the following fields:
   `"SmileysAndEmotion"` otherwise.
 
 See also:
+* [char_select_font](../config/char_select_font.md)
 * [char_select_font_size](../config/char_select_font_size.md)
 * [char_select_fg_color](../config/char_select_fg_color.md)
 * [char_select_bg_color](../config/char_select_bg_color.md)
diff --git a/docs/config/lua/keyassignment/PaneSelect.md b/docs/config/lua/keyassignment/PaneSelect.md
index 17e93110865..6b0a02e252b 100644
--- a/docs/config/lua/keyassignment/PaneSelect.md
+++ b/docs/config/lua/keyassignment/PaneSelect.md
@@ -41,7 +41,7 @@ local wezterm = require 'wezterm'
 local act = wezterm.action
 
 -- 36 is the default, but you can choose a different size.
--- Uses the same font as window_frame.font
+-- Uses the same font as window_frame.font if pane_select_font option is not set
 -- config.pane_select_font_size=36,
 
 config.keys = {
diff --git a/wezterm-font/src/lib.rs b/wezterm-font/src/lib.rs
index afefb4764ef..153482f9e9b 100644
--- a/wezterm-font/src/lib.rs
+++ b/wezterm-font/src/lib.rs
@@ -452,6 +452,14 @@ impl FallbackResolveInfo {
     }
 }
 
+#[derive(PartialEq, Eq)]
+enum Entity {
+    Title,
+    CommandPalette,
+    CharSelect,
+    PaneSelect,
+}
+
 struct FontConfigInner {
     fonts: RefCell<HashMap<TextStyle, Rc<LoadedFont>>>,
     metrics: RefCell<Option<FontMetrics>>,
@@ -584,18 +592,33 @@ impl FontConfigInner {
         )
     }
 
-    fn make_title_font_impl(
+    fn make_entity_font_impl(
         &self,
         myself: &Rc<Self>,
-        pref_size: Option<f64>,
-        make_bold: bool,
+        entity: Entity,
     ) -> anyhow::Result<Rc<LoadedFont>> {
         let config = self.config.borrow();
+        let make_bold = entity != Entity::CommandPalette;
         let (sys_font, sys_size) = self.compute_title_font(&config, make_bold);
 
-        let font_size = pref_size.unwrap_or(sys_size);
+        let (font_size, text_style) = match entity {
+            Entity::Title => (config.window_frame.font_size.unwrap_or(sys_size), None),
+            Entity::CommandPalette => (
+                config.command_palette_font_size,
+                config.command_palette_font.as_ref(),
+            ),
+            Entity::CharSelect => (
+                config.char_select_font_size,
+                config.char_select_font.as_ref(),
+            ),
+            Entity::PaneSelect => (
+                config.pane_select_font_size,
+                config.pane_select_font.as_ref(),
+            ),
+        };
 
-        let text_style = config.window_frame.font.as_ref().unwrap_or(&sys_font);
+        let text_style =
+            text_style.unwrap_or(config.window_frame.font.as_ref().unwrap_or(&sys_font));
 
         let dpi = *self.dpi.borrow() as u32;
         let pixel_size = (font_size * dpi as f64 / 72.0) as u16;
@@ -631,15 +654,13 @@ impl FontConfigInner {
     }
 
     fn title_font(&self, myself: &Rc<Self>) -> anyhow::Result<Rc<LoadedFont>> {
-        let config = self.config.borrow();
-
         let mut title_font = self.title_font.borrow_mut();
 
         if let Some(entry) = title_font.as_ref() {
             return Ok(Rc::clone(entry));
         }
 
-        let loaded = self.make_title_font_impl(myself, config.window_frame.font_size, true)?;
+        let loaded = self.make_entity_font_impl(myself, Entity::Title)?;
 
         title_font.replace(Rc::clone(&loaded));
 
@@ -647,16 +668,13 @@ impl FontConfigInner {
     }
 
     fn command_palette_font(&self, myself: &Rc<Self>) -> anyhow::Result<Rc<LoadedFont>> {
-        let config = self.config.borrow();
-
         let mut command_palette_font = self.command_palette_font.borrow_mut();
 
         if let Some(entry) = command_palette_font.as_ref() {
             return Ok(Rc::clone(entry));
         }
 
-        let loaded =
-            self.make_title_font_impl(myself, Some(config.command_palette_font_size), false)?;
+        let loaded = self.make_entity_font_impl(myself, Entity::CommandPalette)?;
 
         command_palette_font.replace(Rc::clone(&loaded));
 
@@ -664,15 +682,13 @@ impl FontConfigInner {
     }
 
     fn char_select_font(&self, myself: &Rc<Self>) -> anyhow::Result<Rc<LoadedFont>> {
-        let config = self.config.borrow();
-
         let mut char_select_font = self.char_select_font.borrow_mut();
 
         if let Some(entry) = char_select_font.as_ref() {
             return Ok(Rc::clone(entry));
         }
 
-        let loaded = self.make_title_font_impl(myself, Some(config.char_select_font_size), true)?;
+        let loaded = self.make_entity_font_impl(myself, Entity::CharSelect)?;
 
         char_select_font.replace(Rc::clone(&loaded));
 
@@ -680,15 +696,13 @@ impl FontConfigInner {
     }
 
     fn pane_select_font(&self, myself: &Rc<Self>) -> anyhow::Result<Rc<LoadedFont>> {
-        let config = self.config.borrow();
-
         let mut pane_select_font = self.pane_select_font.borrow_mut();
 
         if let Some(entry) = pane_select_font.as_ref() {
             return Ok(Rc::clone(entry));
         }
 
-        let loaded = self.make_title_font_impl(myself, Some(config.pane_select_font_size), true)?;
+        let loaded = self.make_entity_font_impl(myself, Entity::PaneSelect)?;
 
         pane_select_font.replace(Rc::clone(&loaded));
 


Reviews:
user: login: wez
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-08T13:57:19Z

Review comments:
diff_hunk: @@ -0,0 +1,19 @@
+---
+tags:
+  - appearance
+  - char_select
+  - font
+---
+# `char_select_font`
+
+{{since('nightly')}}
+
+Configures the font to use for character selection. The `char_select_font`
+setting can specify a set of fallbacks and other options, and is described
+in more detail in the [Fonts](../../fonts.md) section.
+
+If not specified, the font is same as the font in `window_frame.font`
+
+You will typically use [wezterm.font](../wezterm/font.md) or
+[wezterm.font_with_fallback](../wezterm/font_with_fallback.md) to specify the
+font.
path: docs/config/lua/config/char_select_font.md
user: login: wez
body: Can you show an actual example here? I think that makes the docs feel more accessible.
I typically will just show how to replicate the default config.

Something like this?

```
    ```lua
    config.char_select_font = wezterm.font 'Roboto'
    ```
```

same for the other doc pages
created_at: 2025-03-08T13:51:54Z
author_association: MEMBER
diff_hunk: @@ -655,8 +678,12 @@ impl FontConfigInner {
             return Ok(Rc::clone(entry));
         }
 
-        let loaded =
-            self.make_title_font_impl(myself, Some(config.command_palette_font_size), false)?;
+        let loaded = self.make_entity_font_impl(
+            myself,
+            Some(config.command_palette_font_size),
path: wezterm-font/src/lib.rs
user: login: wez
body: since you have `Entity`, you can resolve this value in your impl as well
created_at: 2025-03-08T13:53:30Z
author_association: MEMBER
diff_hunk: @@ -584,18 +591,33 @@ impl FontConfigInner {
         )
     }
 
-    fn make_title_font_impl(
+    fn make_entity_font_impl(
         &self,
         myself: &Rc<Self>,
         pref_size: Option<f64>,
         make_bold: bool,
+        entity: Entity,
     ) -> anyhow::Result<Rc<LoadedFont>> {
         let config = self.config.borrow();
         let (sys_font, sys_size) = self.compute_title_font(&config, make_bold);
 
         let font_size = pref_size.unwrap_or(sys_size);
 
-        let text_style = config.window_frame.font.as_ref().unwrap_or(&sys_font);
+        let text_style = match entity {
+            Entity::Title => config.window_frame.font.as_ref().unwrap_or(&sys_font),
path: wezterm-font/src/lib.rs
user: login: wez
body: I think you can eliminate the `pref_size` param and make this more succinct:

```rust
        let (pref_size, text_style) = match entity {
            Entity::Title => (config.window_frame.font_size, &config.window_frame.font),
            ...
         };

         let font_size = pref_size.unwrap_or(sys_size);
         let text_style = text_style.unwrap_or(&sys_font);
```
created_at: 2025-03-08T13:56:39Z
author_association: MEMBER

PR comments:
user: login: mgpinf
created_at: 2025-03-09T10:05:01Z
body: As of now I have made `char_select_font`, `command_palette_font`, `pane_select_font` default value to be `config.window_frame` font in order to avoid breaking changes. Should I keep it that way or default to system font rather than relying on `config.window_frame.font`?
author_association: CONTRIBUTOR
user: login: wez
created_at: 2025-03-09T11:22:42Z
body: What you have now sounds good to me; preserving the current behavior on upgrade is desirable
author_association: MEMBER
user: login: wez
created_at: 2025-03-09T22:37:29Z
body: Thank you!
author_association: MEMBER