<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Saladin's blog]]></title><description><![CDATA[Saladin's blog]]></description><link>https://blog.saladin.pro</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 11:22:59 GMT</lastBuildDate><atom:link href="https://blog.saladin.pro/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Unity + Neovim setup ft. Nix]]></title><description><![CDATA[Getting the nvim-unity plugin
 Special thanks to this plugin for allowing this whole thing to work. https://github.com/apyra/nvim-unity.
 Thanks to Apyra, this plugin allows the functionality to work in the first place by allowing 3 things that satis...]]></description><link>https://blog.saladin.pro/unity-neovim-setup-ft-nix</link><guid isPermaLink="true">https://blog.saladin.pro/unity-neovim-setup-ft-nix</guid><category><![CDATA[neovim]]></category><category><![CDATA[Nix]]></category><category><![CDATA[NixOS]]></category><category><![CDATA[Unity3D]]></category><category><![CDATA[unity]]></category><category><![CDATA[C#]]></category><category><![CDATA[.NET]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Saladin]]></dc:creator><pubDate>Wed, 22 Oct 2025 16:30:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761150414522/4351e380-28eb-4128-b672-61ed0cb39646.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ol>
<li><h2 id="heading-getting-the-nvim-unity-plugin">Getting the nvim-unity plugin</h2>
<p> Special thanks to this plugin for allowing this whole thing to work. <a target="_blank" href="https://github.com/apyra/nvim-unity">https://github.com/apyra/nvim-unity</a>.</p>
<p> Thanks to Apyra, this plugin allows the functionality to work in the first place by allowing 3 things that satisfy what Unity and Neovim need to work together.</p>
<ul>
<li><p><strong>Nvim Socket compatibility</strong> -&gt; This is essential for the Engine functionality to work with Neovim. Which is simply to open a specific file or line you desire to open in nvim. For such integrations, nvim has a handy command to use, which simply listens to the arguments passed to the socket. As an example -</p>
<pre><code>nvim --listen $SOCKET <span class="hljs-string">"+$LINE"</span> $FILE<span class="hljs-string">"</span>
</code></pre><p>You can even easily pass arguments to cd into a specific directory &amp; open to a certain line. Basically, this means that with this, nvim starts as a server instance, enabling other clients and processes to send commands, in our case, that's Unity!</p>
</li>
<li><p><strong>LSP Ready</strong> -&gt; One of the best things Microsoft created is the LSP (Language Server Protocol). This simply allows features like auto-complete, go to definition, in all the beloved code editors we know. The one that we care about is <strong>Omnisharp</strong>. Now, Omnisharp depends on 2 things, which it needs in order for it to provide you with goodness. A <code>.csproj</code> and <code>.sln</code> to be in the root folder of our project. However, Unity doesn't generate these by default. This Unity plugin simply allows us to generate these Project Files directly from the Engine! And once this plugin is enabled in the project, it shall automatically generate the project files for you on launch.</p>
<p><img src="https://cdn.saladin.pro/unity_neovim_generate.png" alt="nvim plugin generate" /></p>
</li>
<li><p><strong>Auto-detection</strong> * -&gt; It auto-detects Neovim present on your system, recognising it as a valid "Neovim Code Editor". All tho nothing major, this saves you an extra step for your Unity Project. However, this can have some caveats that are easily fixable depending on your setup, which I will describe later.</p>
<p>So let's simply install the Unity plugin by going to <strong>Window -&gt; Package Management -&gt; Package Manager</strong> and from the top left <strong>+</strong> icon choosing <strong>Install package from git URL...</strong> and using the URL -&gt; <a target="_blank" href="https://github.com/apyra/nvim-unity">https://github.com/apyra/nvim-unity</a>.</p>
<p><img src="https://cdn.saladin.pro/get-nvim-unity.png" alt="get nvim unity" /></p>
</li>
</ul>
</li>
<li><h2 id="heading-download-the-lsp-syntax-highlighting-amp-setup-nvim">Download the LSP, Syntax highlighting &amp; Setup nvim.</h2>
<ul>
<li><p>First, we need the required LSP (Omnisharp) for Neovim; this is pretty straightforward depending on how you manage LSPs on your Neovim. I simply use Mason.nvim to install my LSPs. I have my dotfiles here -&gt; <a target="_blank" href="https://github.com/Saladin1812/dotfiles">https://github.com/Saladin1812/dotfiles</a>. I use the nvchad base configuration. 
My <strong>config/lspconfig.lua</strong> -&gt;</p>
<pre><code><span class="hljs-built_in">require</span>(<span class="hljs-string">"nvchad.configs.lspconfig"</span>).defaults()
local servers = { <span class="hljs-string">"html"</span>, <span class="hljs-string">"cssls"</span>, <span class="hljs-string">"pyright"</span>, <span class="hljs-string">"zls"</span>, <span class="hljs-string">"taplo"</span>, <span class="hljs-string">"nil_ls"</span>, <span class="hljs-string">"ols"</span>, <span class="hljs-string">"omnisharp"</span> }
vim.lsp.enable(servers)
</code></pre><p>Here I have added <strong>omnisharp</strong> for the LSP. </p>
</li>
<li><p>Now, to configure syntax highlighting I simply use nvim-treesitter. Here in my <strong>plugins/init.lua</strong> -&gt;</p>
<pre><code>{
<span class="hljs-string">"nvim-treesitter/nvim-treesitter"</span>,
opts = {
ensure_installed = {
  <span class="hljs-string">"vim"</span>,
  <span class="hljs-string">"lua"</span>,
  <span class="hljs-string">"vimdoc"</span>,
  <span class="hljs-string">"html"</span>,
  <span class="hljs-string">"css"</span>,
  <span class="hljs-string">"json"</span>,
  <span class="hljs-string">"go"</span>,
  <span class="hljs-string">"python"</span>,
  <span class="hljs-string">"rust"</span>,
  <span class="hljs-string">"odin"</span>,
  <span class="hljs-string">"zig"</span>,
  <span class="hljs-string">"toml"</span>,
  <span class="hljs-string">"dart"</span>,
  <span class="hljs-string">"c_sharp"</span>,
        },
  },
},
</code></pre><p>Here I have simply added <strong>c_sharp</strong> to make sure I have syntax highlighting.</p>
</li>
<li><p>Now we need a couple of extra extensions to make sure we are good to go. The first is <strong>ahmedkhalf/project.nvim</strong> required for automatically cd into the project directory. This is important because when nvim with the socket listener is launched, we need it to automatically cd into our Unity project directory with .sln &amp; .csproj at the root. This is required for LSP to work. We can also cd into the project. And launch nvim with the socket listener, but this requires us to manually cd into the project every time we want to work with our project, which is simply not ideal for most all tho mostly I find myself doing it manually either way. Also, keep in mind that sometimes your LSP may attach before project.nvim kicks in. In that case, simply restart your LSP server by doing <code>:LspRestart</code>. Here in my <strong>plugins/init.lua</strong> -&gt;</p>
<pre><code>{
<span class="hljs-string">"ahmedkhalf/project.nvim"</span>,
lazy = <span class="hljs-literal">false</span>,
config = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)
<span class="hljs-title">require</span>(<span class="hljs-params"><span class="hljs-string">"project_nvim"</span></span>).<span class="hljs-title">setup</span> </span>{}
end,
},
</code></pre></li>
<li><p>The other plugin we absolutely need is <strong>apyra/nvim-unity-sync</strong>. This is by the same person who created the Unity nvim plugin. This automatically updates our .csproj file whenever any C# files are created, deleted, or renamed. This also provides a couple of useful commands for manually managing our .csproj. However, for me, I never had to run those commands manually. Here in my <strong>plugins/init.lua</strong></p>
<pre><code>{
<span class="hljs-string">"apyra/nvim-unity-sync"</span>,
lazy = <span class="hljs-literal">false</span>,
config = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)
<span class="hljs-title">require</span>(<span class="hljs-params"><span class="hljs-string">"unity.plugin"</span></span>).<span class="hljs-title">setup</span>(<span class="hljs-params"></span>)
<span class="hljs-title">end</span>,
},</span>
</code></pre></li>
<li><p>Also, it's really beneficial to install Unity Snippets to work with Luasnip. I have created <code>cs.lua</code> for Unity Snippets here -&gt; <a target="_blank" href="https://github.com/Saladin1812/dotfiles/blob/main/.config/nvim/lua/snippets/cs.lua">https://github.com/Saladin1812/dotfiles/blob/main/.config/nvim/lua/snippets/cs.lua</a>. And I have enabled it in my <strong>chadrc.lua</strong> -&gt; </p>
<pre><code>vim.g.lua_snippets_path = vim.fn.stdpath <span class="hljs-string">"config"</span> .. <span class="hljs-string">"/lua/snippets"</span>
</code></pre><p>Make sure to use the correct path where you have saved your snippets. As I am using Nvchad, it comes with Luasnip. However, enable the <strong>L3MON4D3/LuaSnip</strong> plugin if you have to.</p>
</li>
</ul>
</li>
<li><h2 id="heading-install-net-sdk">Install .NET SDK</h2>
<p> Omnisharp does require the .NET SDK to work properly, depending on your Unity version. Currently with Unity 6.2 requires .NET 9 SDK. Download it with your package manager. On nix this is simply -&gt;
<strong>dotnetCorePackages.dotnet_9.sdk</strong></p>
</li>
<li><h2 id="heading-launching-nvim-with-the-socket-listener">Launching nvim with the socket listener.</h2>
<p> Note: If you are using <strong>nix</strong>, you don't need to deal with this; simply use the nix file I talk about later.</p>
<p> We are basically all set. However, we need to launch our nvim instance with the socket listener so it can listen to the commands sent by the Unity plugin to our nvim instance. There is a repository by the same developer that includes standalone scripts for launching an nvim instance for your operating system here -&gt;
<a target="_blank" href="https://github.com/apyra/nvim-unity-standalone">https://github.com/apyra/nvim-unity-standalone</a>. However, on Linux &amp; possibly MacOS, there is a caveat. The script is likely converted from a Windows environment. Due to which you may get errors like <code>nvimunity: line 2: $'\r': command not found</code>. This is because <code>$'\r'</code> is the Carriage Return (CR) character, which is part of the Windows-style line ending (CRLF). Linux (and the Bash shell) only expects the Line Feed (LF) character as a line ending. The shell is trying to interpret the hidden \r character at the end of each line as part of the command itself, leading to the error. The easiest way is to convert them using the <code>dos2unix</code> utility. Assuming you have the <code>nvimunity.sh</code> script renamed <code>nvimunity</code> from the standalone repository, simply run <code>dos2unix nvimunity</code> and run the script again using <code>bash nvimunity</code> or <code>./nvimunity</code> depending on your default shell. The repository also provides a .desktop file so you can launch it from the GUI. You can edit the .desktop file to use your preferred terminal like so -&gt; </p>
<pre><code>exec = <span class="hljs-string">"ghostty -e $HOME/.local/bin/nvimunity %f"</span>;
</code></pre><p> In this case, the script is in <strong>~/.local/bin/nvimunity</strong>. Which I prefer. If it is in <strong>/usr/bin</strong>, you can also create a symlink. As the script by default uses <strong>/usr/bin</strong>. Regardless Unity plugin will autodetect <code>nvimunity</code>. If not, you can simply choose it manually from the External Tools settings in Unity. And it will detect is as a valid Neovim Code Editor. The script itself requires <code>jq</code>, <code>xdotool'; you can download them from your distro's package manager. In the end, the plugin just cares about finding the valid socket listener. Once you have the</code>nvimunity.sh<code>script running, the socket should be in</code>$HOME/.cache/nvimunity.sock`. This is all that the plugin needs. Voila! Double-clicking on a C# file in Unity should now launch the file in your nvim instance with the LSP and everything working seamlessly.</p>
<p> <img src="https://cdn.saladin.pro/unity-nvim-ss.png" alt="Unity nvim ss" /></p>
<p> For NixOS users, I have created a nvimunity.nix that sets up the nvimunity instance without any manual steps, along with the desktop launcher and the nvimunity desktop icon. Here is the script -&gt; <a target="_blank" href="https://github.com/Saladin1812/dotfiles/blob/main/nix/home/nvimunity.nix">https://github.com/Saladin1812/dotfiles/blob/main/nix/home/nvimunity.nix</a>. This also creates a symlink in ~/.local/bin, which can be auto-detected by the Unity plugin, or you can easily choose this path manually. This is helpful because by default on Nix, the packages exist either inside nix stores, or under your per-user profiles, depending on the way you install things example -&gt; <code>/etc/profiles/per-user/YourUsername/bin/nvimunity</code>.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Why strict coding standards are NOT objectively right.]]></title><description><![CDATA[What are coding standards ?
Coding standards are a set of guidelines and best practices that software developers adhere to when writing code. These standards play a crucial role in maintaining code quality, readability, maintainability, and collabora...]]></description><link>https://blog.saladin.pro/why-strict-coding-standards-are-not-objectively-right</link><guid isPermaLink="true">https://blog.saladin.pro/why-strict-coding-standards-are-not-objectively-right</guid><category><![CDATA[cpp]]></category><category><![CDATA[Rust]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[coding standards]]></category><category><![CDATA[coding]]></category><category><![CDATA[Google]]></category><category><![CDATA[C++]]></category><category><![CDATA[Java]]></category><category><![CDATA[Python]]></category><category><![CDATA[tools]]></category><dc:creator><![CDATA[Saladin]]></dc:creator><pubDate>Sat, 21 Jun 2025 10:30:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750501612469/a8d2072a-ff63-4389-b31f-ab4f77fbeaa2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-are-coding-standards">What are coding standards ?</h2>
<p>Coding standards are a set of guidelines and best practices that software developers adhere to when writing code. These standards play a crucial role in maintaining code quality, readability, maintainability, and collaboration among developers. However they can either be defined by the language itself, or can be defined by each team / individual for themselves.</p>
<p>Some examples of languages where <strong>coding standards are strictly either enforced by the language design or by the creators / foundation</strong> are <strong>Rust &amp; Go</strong>. The reason I really wanted to emphasize on these two is because they not only set standards for the code itself but also the <strong>tooling</strong>. In the case of rust tools like rustfmt (<strong>formatter</strong>), cargo (<strong>both a build tool and a package manager</strong>), rustc (<strong>compiler</strong>), rustup(<strong>installer</strong>) are examples where tooling is standardized. Rust goes an extra mile to also ensure stuff like lsp to be standardized. In 2022 the <a target="_blank" href="https://blog.rust-lang.org/2022/07/01/RLS-deprecation/">Rust Dev Tools team deprecated RLS in favor of rust-analyzer</a>. It is expected for them to take the community feedback and set the standards for each and everything and rust being rust is a strict language by design, and would usually <strong>force you to do things “the correct way”</strong> / basically following the standard. When it comes to Go’s language design, there aren’t many ways to achieve the same result as the language was designed to be simple and not be <strong>featureful.</strong> And when it comes to Go’s tooling it is consistent across the board, they get to standardize the fact that <a target="_blank" href="https://go.dev/doc/go1.13">Using Go's module system is now the standard in Go 1.13</a> among other things. It is common now for newer languages to create or adopt standards for the code and tooling, be it Zig, Odin or any newer language at least to some degree or more. I won’t define each language as I think you get the idea. However this was not always the norm. Here is a quote from Bjarne Stroustrup the creator of C++ himself, when asked about different implementations of C++ i.e clang, gcc, msvc.</p>
<blockquote>
<p>When I designed C++ most languages most languages had multiple implementations because if you wanna run on an IBM or run on a Sun or if you wanna run on a Motorolla, those are just many many companies each having their own compilation structure, their own compilers, it was just fairly common that those were many of them and I wrote C front assuming other people would write compilers for C++.</p>
</blockquote>
<p>Later on he also talked about different linkers and the positives where this freedom means there was competition and incentive to innovate and optimizations. <a target="_blank" href="https://www.youtube.com/watch?v=ZQds2aGHwDA">Here is the link of this talk with Lex Fridman</a> &amp; <a target="_blank" href="https://www.youtube.com/watch?v=uTxRF5ag27A">link for the full talk.</a></p>
<h2 id="heading-the-arguments-by-the-objective-people">The arguments by the "Objective People"</h2>
<p>Many devs these days use positive arguments for having strict coding and tooling standards without listing the negatives. Positives such as →</p>
<ul>
<li><p><strong>Ease of support</strong> - It is easy to support a single standard, which results in less edge cases as it removes stuff like compiler specific bugs. It allows more people to focus on improving a single standard rather than always endorsing competition.  </p>
</li>
<li><p><strong>Less developer overhead</strong> - When it comes to tooling the user no longer needs to figure out “Should I use <code>pip</code> with the <code>--user</code> flag ?, or maybe use <code>venv</code> or maybe anaconda or <code>pyenv</code> + <code>poetry</code> ?“. This point also makes it very <strong>easy for documentation</strong> and results in a lot of <strong>time saving</strong> for both be it the language devs or the devs using the language.  </p>
</li>
<li><p><strong>Consistency</strong> - This is probably the most common argument as due to having enforced coding styles code bases are generally considered more consistent, which help maintain uniformity across projects. This argument is very much so used against C++ due to the fact that many code bases are legacy and having different standards &amp; addition of features. Consistency results in <strong>better code readability</strong> which again contributes to <strong>time saving</strong> and saves you from <a target="_blank" href="https://www.google.com/search?q=cephalalgia">cephalalgia</a> which results in <strong>reduction of medical bills and cost saving</strong>.</p>
</li>
</ul>
<h2 id="heading-the-counter-arguments">The counter arguments</h2>
<p>I would just challenge the readers to take 5 minutes and try to counter each and every point i mentioned above with some positives, this is just to endorse some critical thinking and always questioning and try to play the devil's advocate. And if you are still feel blinding, you might be eating some Primeagens for breakfast. here are some of the counters -</p>
<ul>
<li><strong>Less Incentive</strong> - Due to having a set standard there is <strong>less incentive</strong> for the community to develop something better, as that is something the community doesn’t expect. With languages like C++, Python and even Java there is a common psychology where there is expectation from the community and companies alike to create compilers, package management and third-party tooling in general.  </li>
</ul>
<p>    Java for example <strong>rallies heavily on third-party tooling</strong>. If there was no IntelliJ, or Eclipse or Netbeans back in those days there is always <strong>a psychological incentive / expectation from the community to come up with something</strong>, same thing with build tools, package management like Gradle and Maven.  </p>
<p>    Now taking example of Rust before it adopted rust-analyzer and axed RLS. Many people still stayed to RLS due to it being the “official“ standard. As the psychology of the community will always be to stick with the standard. rust-analyzer was better than RLS long before it was the standard. If a better compiler for C++ was to develop today it will get much <strong>quicker adoption</strong> as community generally expects it. There were discussions on Reddit and various forums where even <a target="_blank" href="https://www.reddit.com/r/rust/comments/lur37d/why_is_rls_still_so_bad/">the creator of RLS was asking people to use rust-analyzer</a>, but it had more downloads and was always the top result on the VS Code Marketplace.  </p>
<p>    A developer is expected to ask himself/herself “Which <em>x</em> should I use“ (compiler, tool, package manager, coding style etc.). This also <strong>incentives a healthy competition</strong> and opens a whole new market and innovation.  </p>
<ul>
<li><p><strong>Less choices / Deal with it</strong> - All tho I do agree that if you have set standards they should be of a better high quality than the alternatives (if they exist in the first place) as most of the focus is usually on maintaining and improving that standard. There are cases where this may NOT be the best standard available. rls again is a great example of that. Another great example of this is Node.</p>
<p>  I consider JavaScript’s eco system does not fit this article because the default standard is just garbage that many would just look at the alternatives just for that. So community has an incentive to create alternatives for npm like yarn &amp; pnpm and alternatives for node like deno (created by the creator of node) &amp; bun. To a point where the creator of node regrets many design decisions. Usually the default standards for tooling is great and doesn’t give incentive or a reason for community to innovate like cargo for example (Rust community doesn’t expect alternative for cargo because they are happy with it). But JS eco system just does make the community develop stuff to fix its own standard.  </p>
</li>
</ul>
<ul>
<li>Keeping up to do things the "Right Way" - The consistency argument is the all tho valid for code readability but people don’t mention that it comes with an expectation that your code always follows the current standard.  </li>
</ul>
<p>    When <a target="_blank" href="https://go.dev/blog/go1.18">Go introduced generics in 1.18</a> the community overall was filled with mixed feelings about this. Many were asking for it, many didn’t like the introduction of generics. Now we do see go’s code bases are expected to use generics where it can, that is considered “<strong>idiomatic</strong>“.</p>
<p>    Now rust also keeps introducing features just like C++ but the difference is that in the rust case the definition of idiomatic keeps changing. Your code you wrote 10 years ago may not be idiomatic for today’s standards.  </p>
<p>    When it comes to C++ it allows versatility and allows companies and dev’s to define their standards. And here I am not talking about C++11, C++17, C++20. But the coding style guides. As an example <a target="_blank" href="https://google.github.io/styleguide/cppguide.html">Google C++ Style guide</a> allows google engineers to follow a single standard and would never be in a hurry to necessarily catchup. Talking about C++ editions, having a lot of legacy means they can’t simply change the standard but they can define one on top of another. Similarly if you look at Java formatters &amp; linters and Python formatters &amp; linters there is no <strong>“Right way“</strong>. Yes this results in code bases on being less consistent, but also allows freedom &amp; versatility.</p>
<p><a target="_blank" href="https://google.github.io/styleguide/cppguide.html">Google's C++ style guide</a> for example priorities Abstract classes and compositions over Inheritance. <a target="_blank" href="https://google.github.io/styleguide/javaguide.html">Google also has style guide for Java</a> so does <a target="_blank" href="https://source.android.com/docs/setup/contribute/code-style">AOSP</a> and so did <a target="_blank" href="https://github.com/twitter-archive/commons/blob/master/src/java/com/twitter/common/styleguide.md">twitter (they derived most from google)</a>.</p>
<p>Like reading code bases, picking and choosing standards can cost time &amp; cause <a target="_blank" href="https://www.google.com/search?q=cephalalgia">cephalalgia</a> likewise keeping with the standard can also cause the <a target="_blank" href="https://www.google.com/search?q=cephalalgia">cephalalgia</a>.  </p>
<p>Also when people talk about code readability what they usually don’t consider is the use of third-party tools. I am not fighting the code readability argument here but problems do force the community to create. If you try to figure out all the interface implementations, all the abstract classes, all the inheritance with those virtual functions without using the right tool you will end up wasting a lot of your valuable time.  </p>
<h2 id="heading-verdict">Verdict</h2>
<p>All I wanted to say is that I am NOT saying that strict coding standards are wrong to have, but I am saying they aren’t objectively right either. Many devs these days don’t try to question their own opinions and most don’t want to see things from a subjective eye.</p>
]]></content:encoded></item></channel></rss>