<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AsfhtgkDavid</title>
    <description>The latest articles on DEV Community by AsfhtgkDavid (@asfhtgkdavid).</description>
    <link>https://dev.to/asfhtgkdavid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3438759%2F1d987288-11d0-4eba-8119-ac8addeeefea.jpg</url>
      <title>DEV Community: AsfhtgkDavid</title>
      <link>https://dev.to/asfhtgkdavid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asfhtgkdavid"/>
    <language>en</language>
    <item>
      <title>The Shit - say NO to typos</title>
      <dc:creator>AsfhtgkDavid</dc:creator>
      <pubDate>Sat, 16 Aug 2025 09:53:36 +0000</pubDate>
      <link>https://dev.to/asfhtgkdavid/the-shit-say-no-to-typos-2g4a</link>
      <guid>https://dev.to/asfhtgkdavid/the-shit-say-no-to-typos-2g4a</guid>
      <description>&lt;p&gt;Hello, everyone! How often do you make mistakes while working in the terminal? I'm sure everyone has forgotten &lt;code&gt;sudo&lt;/code&gt; at least once or typed &lt;code&gt;cs&lt;/code&gt; instead of &lt;code&gt;cd&lt;/code&gt;. Once, I saw the alias &lt;code&gt;fuck&lt;/code&gt; for adding &lt;code&gt;sudo&lt;/code&gt; to the previous command. I got interested and started digging.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first solution worthy of respect
&lt;/h2&gt;

&lt;p&gt;In my search, I found the utility &lt;a href="https://github.com/nvbn/thefuck" rel="noopener noreferrer"&gt;thefuck&lt;/a&gt;. In addition to simply adding &lt;code&gt;sudo&lt;/code&gt; where necessary, it can correct typos in commands, add missing flags, and much more.&lt;/p&gt;

&lt;p&gt;However, I found two drawbacks. First, the program is written in Python, which can make it slow. Second, it has not been supported for a long time, so it does not work on newer versions of the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick alternative
&lt;/h2&gt;

&lt;p&gt;We're programmers here, I thought, and decided to write an alternative in Rust called &lt;a href="https://github.com/AsfhtgkDavid/theshit" rel="noopener noreferrer"&gt;theshit&lt;/a&gt;. Honestly, it was my first experience with Rust, which made it even more interesting. The author of thefuck used an interesting approach to pass the last command to the program, and I borrowed it. Rather than calling our program directly, we create a special alias (function) for the shell.&lt;/p&gt;

&lt;p&gt;An example of the theshit alias for zsh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;name&lt;span class="o"&gt;}()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  &lt;span class="c"&gt;# {name} - alias name&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SH_SHELL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;zsh&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;SH_PREV_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;fc&lt;/span&gt; &lt;span class="nt"&gt;-ln&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;SH_PREV_CMD&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;SH_SHELL_ALIASES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;SH_SHELL_ALIASES&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;SH_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;
      &lt;span class="o"&gt;{}&lt;/span&gt; fix &lt;span class="nv"&gt;$@&lt;/span&gt;  &lt;span class="c"&gt;# {} - путь к программе&lt;/span&gt;
    &lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$SH_CMD&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;unset &lt;/span&gt;SH_PREV_CMD&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;unset &lt;/span&gt;SH_SHELL&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;unset &lt;/span&gt;SH_SHELL_ALIASES&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we pass all the necessary information through environment variables and built-in shell commands. How do we correct commands? Just like in &lt;code&gt;thefuck&lt;/code&gt;, we have certain "rules" consisting of two functions: checking and correcting.&lt;/p&gt;

&lt;p&gt;An example of a rule for correcting the &lt;code&gt;cargo&lt;/code&gt; subcommand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.stderr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"no such command"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;
            &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.stderr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nf"&gt;.contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a command with a similar name exists:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="nf"&gt;.parts&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"cargo"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;broken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="nf"&gt;.parts&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;r"a command with a similar name exists: `([^`]*)`"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.captures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.stderr&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="nf"&gt;.as_str&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nn"&gt;misc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;replace_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="nf"&gt;.command&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;broken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we enter a command incorrectly, &lt;code&gt;cargo&lt;/code&gt; itself suggests the correct equivalent. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ cargo builrt
error: no such command: `builrt`

help: a command with a similar name exists: `build`

help: view all installed commands with `cargo --list`
help: find a package to install `builrt` with `cargo search cargo-builrt`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In turn, we simply check for a hint and retrieve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I told you about two utilities for correcting errors and explained how they work. I hope you enjoyed it and that you will be able to work faster in the terminal. Finally, I would like to ask for your help in developing and testing &lt;code&gt;theshit&lt;/code&gt;. Please open issues, send pull requests, and, most importantly, don't be afraid to experiment!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>cli</category>
      <category>shell</category>
    </item>
  </channel>
</rss>
