Repository: helix-editor/helix
File: helix-view/src/editor.rs (Rust)

Code before:
impl Default for AutoSaveAfterDelay {
    fn default() -> Self {
        Self {
            enable: false,
            timeout: DEFAULT_AUTO_SAVE_DELAY,
        }
    }
}

impl<'de> Deserialize<'de> for AutoSave {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        Ok(AutoSaveToml::deserialize(deserializer)?.into())
    }
}
impl Serialize for AutoSave {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let a: AutoSaveToml = self.clone().into();
        a.serialize(serializer)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub struct WhitespaceCharacters {
    pub space: char,
    pub nbsp: char,
    pub nnbsp: char,
    pub tab: char,
    pub tabpad: char,
    pub newline: char,
}

impl Default for WhitespaceCharacters {
    fn default() -> Self {
        Self {
            space: '·',   // U+00B7
            nbsp: '⍽',    // U+237D
            nnbsp: '␣',   // U+2423
            tab: '→',     // U+2192
            newline: '⏎', // U+23CE
            tabpad: ' ',
        }
    }
}


Review comment (suggestion):
This is a bit much boiler plate for my liking. I usually just put the `enum AutoSaveToml {` inside a standalone deserialize function. You can just but a `#[serde(deserialize_with = "deserialize_auto_save")]` attribute on the `auto_save` field. Combined with the other changes I roughly had the following in mind:


```suggestion
fn deserialize_auto_save<'de, D>(deserializer: D) -> Result<AutoSavei, D::Error>
where
    D: serde::Deserializer<'de>,
{
	#[derive(Deserialize, Serialize)]
	#[serde(untagged, deny_unknown_fields, rename_all = "kebab-case")]
	enum AutoSaveToml {
	    EnableFocusLost(bool),
	    AutoSave(AutoSave),
	}
	
    match AutoSaveToml::deserilaize(deserializer)? {
	    AutoSaveToml::EnableFocusLost(focus_lost) => Ok(AutoSave {
	        focus_lost,
	        ..Default::default()
	    }),
	    AutoSaveToml::AutoSave(auto_save) => Ok(auto_save)
    }
}

```

We actually want to just use the derived `Serialize` implementation for AutoSave instead of going back to `AutoSaveToml` so you don't need to do this for serialize

Code after:

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default, rename_all = "kebab-case")]
pub struct IndentGuidesConfig {
    pub render: bool,
    pub character: char,
    pub skip_levels: u8,
}

impl Default for IndentGuidesConfig {
    fn default() -> Self {
        Self {
            skip_levels: 0,
            render: false,
            character: '│',
        }
    }
}

/// Line ending configuration.
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LineEndingConfig {
    /// The platform's native line ending.
    ///
    /// `crlf` on Windows, otherwise `lf`.
    #[default]
    Native,
    /// Line feed.
    LF,
    /// Carriage return followed by line feed.
    Crlf,
    /// Form feed.
    #[cfg(feature = "unicode-lines")]
    FF,
    /// Carriage return.
    #[cfg(feature = "unicode-lines")]
    CR,
    /// Next line.
    #[cfg(feature = "unicode-lines")]
    Nel,
}

impl From<LineEndingConfig> for LineEnding {
    fn from(line_ending: LineEndingConfig) -> Self {
        match line_ending {
            LineEndingConfig::Native => NATIVE_LINE_ENDING,
            LineEndingConfig::LF => LineEnding::LF,
            LineEndingConfig::Crlf => LineEnding::Crlf,
            #[cfg(feature = "unicode-lines")]
            LineEndingConfig::FF => LineEnding::FF,