<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Vim on mm-dev</title>
    <link>https://mm-dev.rocks/tags/vim/</link>
    <description>Recent content in Vim on mm-dev</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-gb</language>
    <lastBuildDate>Thu, 08 Aug 2024 17:47:33 +0100</lastBuildDate><atom:link href="https://mm-dev.rocks/tags/vim/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Set up Vim for Flutter</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/set-up-vim-for-flutter/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:33 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/set-up-vim-for-flutter/</guid>
      <description>&lt;p&gt;There are various ways of installing Vim plugins. I use &lt;code&gt;vim-plug&lt;/code&gt; in my examples here but I&amp;rsquo;ll add links to instructions for each plugin so you can do it your own way.&lt;/p&gt;
&lt;h2 id=&#34;dart&#34;&gt;Dart&lt;/h2&gt;
&lt;p&gt;As Flutter uses the Dart language, install &lt;a href = &#34;https://github.com/dart-lang/dart-vim-plugin&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Dart support for Vim&lt;/a&gt;. I add the following to my &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34; Between the &amp;#39;plug#begin()&amp;#39; and &amp;#39;plug#end()&amp;#39; lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;dart-lang/dart-vim-plugin&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I restart Vim and run &lt;code&gt;:PlugInstall&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This adds syntax highlighting and auto-indentation of Dart code.&lt;/p&gt;
&lt;h2 id=&#34;language-servers&#34;&gt;Language Servers&lt;/h2&gt;
&lt;p&gt;Language Servers/LSPs (LSP = Language Server Protocol but both terms are often used interchangeably) give your editor information about the structure of a language and enable it to do syntax highlighting and code completion, along with deeper functionality such as allowing you to jump to the definition of a function, do refactoring etc.&lt;/p&gt;
&lt;p&gt;LSPs are used in Visual Studio for a lot of its advanced functionality but they can also be used in Vim. There&amp;rsquo;s more than one way of doing this but I use &lt;a href = &#34;https://github.com/neoclide/coc.nvim&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;coc-nvim&lt;/a&gt; (despite the name it works in modern versions of Vim, not just Neovim).&lt;/p&gt;
&lt;h3 id=&#34;install-the-cocnvim-plugin-in-vim&#34;&gt;Install the &lt;code&gt;coc.nvim&lt;/code&gt; plugin in Vim&lt;/h3&gt;
&lt;p&gt;Using &lt;code&gt;vim-plug&lt;/code&gt; I add the following to my &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34; Between the &amp;#39;plug#begin()&amp;#39; and &amp;#39;plug#end()&amp;#39; lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;neoclide/coc.nvim&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; {&lt;span class=&#34;s1&#34;&gt;&amp;#39;branch&amp;#39;&lt;/span&gt;: &lt;span class=&#34;s1&#34;&gt;&amp;#39;release&amp;#39;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, I restart Vim and run &lt;code&gt;:PlugInstall&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For other ways of installing just follow the &lt;a href = &#34;https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;instructions &lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;install-a-flutter-lsp&#34;&gt;Install a Flutter LSP&lt;/h3&gt;
&lt;p&gt;Install the Flutter language server in CoC, &lt;a href = &#34;https://github.com/iamcco/coc-flutter&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;coc-flutter&lt;/a&gt;. This provides lots of helpful functionality for working with Flutter in Vim as described in the link.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CocInstall&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;flutter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This LSP needs to know where the Flutter SDK is installed. In Vim, run &lt;code&gt;:CocList FlutterSDKs&lt;/code&gt; and make sure it finds at least 1 SDK. If not, add a line to CoC settings (&lt;code&gt;:CocConfig&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;flutter.sdk.path&amp;#34;&lt;/span&gt;: &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/.local/flutter/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can find the correct path with &lt;code&gt;which flutter&lt;/code&gt; in the terminal.&lt;br&gt;
&lt;em&gt;Originally, I had installed my Flutter SDK at &lt;code&gt;/usr/bin&lt;/code&gt;. That caused invisible errors with &lt;code&gt;coc-flutter&lt;/code&gt; as it couldn&amp;rsquo;t access the path properly to find the Flutter SDK. I was having trouble getting this step working. I then moved the Flutter SDK to &lt;code&gt;$HOME/.local/flutter&lt;/code&gt; and everything started to work properly&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;cocnvim-settings&#34;&gt;&lt;code&gt;coc.nvim&lt;/code&gt; settings&lt;/h2&gt;
&lt;p&gt;To change CoC settings the command &lt;code&gt;:CocConfig&lt;/code&gt; can be used in Vim. On my system it opens up the file &lt;code&gt;~/.vim/coc-settings.json&lt;/code&gt;. You can open/edit this file directly but depending on your Vim configuration it may be in a different location.&lt;/p&gt;
&lt;p&gt;Here are some of the settings I prefer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;diagnostic.checkCurrentLine&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;diagnostic.enableMessage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;jump&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;colors.enable&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;suggest.noselect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;inlayHint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;diagnosticcheckcurrentline-true&#34;&gt;&lt;code&gt;&amp;quot;diagnostic.checkCurrentLine&amp;quot;: true,&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;By default, Coc will show you a diagnostic error or warning when your cursor is over the word causing the problem. Setting this to &lt;code&gt;true&lt;/code&gt; means you only have to be on the same line as the error to see the dialog, not the exact word.&lt;/p&gt;
&lt;h3 id=&#34;diagnosticenablemessage-jump&#34;&gt;&lt;code&gt;&amp;quot;diagnostic.enableMessage&amp;quot;: &amp;quot;jump&amp;quot;,&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This diagnostic popups can be really helpful, but it&amp;rsquo;s all a bit frenetic for me, I&amp;rsquo;m a &lt;code&gt;prefers-reduced-motion&lt;/code&gt; kind of person. Setting this to &lt;code&gt;jump&lt;/code&gt; means they don&amp;rsquo;t pop up automatically, but can still be shown when I want to see them. I also add this line to &lt;code&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;nmap&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;silent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gh&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;nmap&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;silent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gl&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;diagnostic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which allows me to show/hide the diagnostics with &lt;code&gt;gh&lt;/code&gt;/&lt;code&gt;gl&lt;/code&gt; respectively.&lt;/p&gt;
&lt;h3 id=&#34;colorsenable-true&#34;&gt;&lt;code&gt;&amp;quot;colors.enable&amp;quot;: true,&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This setting is for another CoC addition called &lt;code&gt;coc-highlight&lt;/code&gt;. I installed this in Vim with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-vim&#34; data-lang=&#34;vim&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CocInstall&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;highlight&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This adds various types of colour highlighting, but the one I was most interested in is how it will detect any colours (eg RGB or hex) in your code and change the colour of their text to give you a preview of them. This feature is enabled with the &lt;code&gt;colors.enable&lt;/code&gt; line as above.&lt;/p&gt;
&lt;h3 id=&#34;suggestnoselect-true&#34;&gt;&lt;code&gt;&amp;quot;suggest.noselect&amp;quot;: true,&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;When you start typing a word, CoC will default to inserting its first suggested autocompletion word. This is a bit more &amp;lsquo;help&amp;rsquo; than I like, so I add this setting to make the process more intentional.&lt;/p&gt;
&lt;h3 id=&#34;inlayhint-false&#34;&gt;&lt;code&gt;&amp;quot;inlayHint&amp;quot;: false,&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;By default CoC inserts &lt;em&gt;inlay hints&lt;/em&gt;, for example if you haven&amp;rsquo;t added a type hint to indicate what kind of widget is being referred to somewhere, it will insert the &lt;code&gt;&amp;lt;Widget&amp;gt;&lt;/code&gt; hint for you as a piece of magical ghost text.&lt;/p&gt;
&lt;p&gt;These bizarre bits of text appear in the middle of lines of code, except they aren&amp;rsquo;t really there, you can&amp;rsquo;t select them or delete them and if you&amp;rsquo;re moving your cursor around it acts as if they don&amp;rsquo;t exist. I&amp;rsquo;m sure some people enjoy them, and for those people I&amp;rsquo;m glad that they exist. For me, they are disgusting, obnoxious devil-warts.&lt;/p&gt;
&lt;p&gt;Thankfully, they can be vanquished by adding this line to the CoC settings.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Install Flutter</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/install-flutter/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:32 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/install-flutter/</guid>
      <description>&lt;h3 id=&#34;follow-instructions-from&#34;&gt;Follow instructions from &lt;a href = &#34;https://docs.flutter.dev/get-started/install/linux/android&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;https://docs.flutter.dev/get-started/install/linux/android&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Download the &lt;code&gt;flutter_*.tar.xz&lt;/code&gt; archive&lt;/li&gt;
&lt;li&gt;Unpack the archive into &lt;code&gt;$HOME/.local/bin&lt;/code&gt; (creates &lt;code&gt;$HOME/.local/bin/flutter/bin&lt;/code&gt;)&lt;br&gt;
&lt;em&gt;At first I tried putting this at &lt;code&gt;/usr/bin&lt;/code&gt;, but that caused invisible errors in coc-flutter as it couldn&amp;rsquo;t access the path properly to find the Flutter SDK&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Add the new path as above to $PATH eg in &lt;code&gt;~/.profile&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ~/.profile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/.local/bin/flutter/bin:&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;For ARM64 architectures the Flutter SDK cannot be found at the above link, nor in the archives. In this case the SDK can be obtained by cloning the main flutter repo, then running a &lt;code&gt;flutter&lt;/code&gt; command to trigger a download of dependencies&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;git clone -b main https://github.com/flutter/flutter.git
./flutter/bin/flutter --version
&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;h3 id=&#34;agree-to-more-licenses-and-get-flutter-doctor-to-pass&#34;&gt;Agree to more licenses and get Flutter doctor to pass&lt;/h3&gt;
&lt;p&gt;First, agree to several laughably long licence agreements which Google knows full well that nobody reads.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;flutter doctor --android-licenses
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then type Y and Enter for each prompt&lt;/p&gt;
&lt;p&gt;Now run &lt;code&gt;flutter doctor&lt;/code&gt;. It should pass every test except &amp;lsquo;Android Studio (not installed)&amp;rsquo;. If so, we&amp;rsquo;re ready to start building Flutter apps (with Android Studio not installed).&lt;/p&gt;
&lt;h3 id=&#34;sample-project&#34;&gt;Sample project&lt;/h3&gt;
&lt;p&gt;You can make a really simple sample project to check that everything&amp;rsquo;s installed correctly and see how it works.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;flutter create sample-project
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will create a &lt;code&gt;sample-project&lt;/code&gt; directory with a Flutter app in it, a simple built-in demo of a button which counts up as you tap it.&lt;/p&gt;
&lt;p&gt;To run the app:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; sample_project
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;flutter run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Install the Android SDK</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/install-the-android-sdk/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:31 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/install-the-android-sdk/</guid>
      <description>&lt;p&gt;Getting the Android SDK set up manually can be tricky, I think the expectation is that most people will use Android Studio so not a lot of work has been put in to making manual installation user-friendly.&lt;/p&gt;
&lt;h3 id=&#34;pick-a-directory-where-youll-keep-the-sdk&#34;&gt;Pick a directory where you&amp;rsquo;ll keep the SDK&lt;/h3&gt;
&lt;p&gt;This is an important directory that will always store all the Android-SDK specific tools, platforms, build tools etc. Various bits and pieces need to know where these things are, so we&amp;rsquo;ll set some environment variables for them later.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using &lt;code&gt;$HOME/android_sdk/&lt;/code&gt; in these examples.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mkdir &lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;install-the-sdk-manager&#34;&gt;Install the SDK Manager&lt;/h3&gt;
&lt;p&gt;This is a set of command line tools used to install different versions of the SDK (for when you want to target different Android devices).&lt;/p&gt;
&lt;p&gt;Based on Google&amp;rsquo;s instructions at &lt;a href = &#34;https://developer.android.com/tools/sdkmanager&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;https://developer.android.com/tools/sdkmanager&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From the &lt;a href = &#34;https://developer.android.com/studio&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;downloads page&lt;/a&gt; (I had to scroll down a long way), download the &lt;code&gt;cmdline-tools&lt;/code&gt; zip and unzip it to the directory you created above eg &lt;code&gt;$HOME/android_sdk/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Inside the unzipped directory &lt;code&gt;cmdline-tools&lt;/code&gt; make a &amp;rsquo;latest&amp;rsquo; directory and move all of the other contents of &amp;lsquo;cmdline-tools&amp;rsquo; inside it (so you end up with &lt;code&gt;cmdline-tools/latest/bin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should end up with something like the following (I&amp;rsquo;m using &lt;code&gt;tree&lt;/code&gt; to list the directory contents but don&amp;rsquo;t worry about that, just make sure your directories are in the right places):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ tree -L &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; cmdline-tools/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cmdline-tools/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── NOTICE.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ├── lib
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── source.properties
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;add-some-environment-variables-to-profile&#34;&gt;Add some environment variables to &lt;code&gt;~/.profile&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Make sure these make sense based on what we&amp;rsquo;ve done so far if you&amp;rsquo;ve used different directories to me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ~/.profile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ANDROID_SDK_ROOT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/android_sdk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;:&lt;span class=&#34;nv&#34;&gt;$ANDROID_SDK_ROOT&lt;/span&gt;/cmdline-tools/latest/bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PATH&lt;/span&gt;:&lt;span class=&#34;nv&#34;&gt;$ANDROID_SDK_ROOT&lt;/span&gt;/platform-tools
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Source the profile with &lt;code&gt;source ~/.profile&lt;/code&gt;. Then run &lt;code&gt;sdkmanager&lt;/code&gt; and see if it does something. If you get &lt;code&gt;command not found&lt;/code&gt; double-check everything and try rebooting.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;span&gt;My sdkmanager binary name clash (this won&amp;rsquo;t affect you but click to expand if you&amp;rsquo;re interested)&lt;/span&gt;&lt;/summary&gt;

&lt;div&gt;
&lt;p&gt;In my case I already had a binary installed with the name &lt;code&gt;sdkmanager&lt;/code&gt;, as that&amp;rsquo;s the name Garmin use for their ConnectIQ SDK Manager. Apparently neither Garmin nor Google could foresee that anyone other than themselves might call their SDK manager software &amp;lsquo;sdkmanager&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;So I had to do some hacky stuff with bash aliases in &lt;code&gt;~/.profile&lt;/code&gt; to let the two live alongside each other, and remind me of the situation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;alias&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;sdkmanager&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;echo &amp;#34;Use either *sdkmanager-garmin* or *sdkmanager-android*&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;alias&lt;/span&gt; sdkmanager-android&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ANDROID_SDK_ROOT&lt;/span&gt;/cmdline-tools/latest/bin/sdkmanager
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;alias&lt;/span&gt; sdkmanager-garmin&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.local/bin/sdkmanager
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h3 id=&#34;accept-sdk-licences&#34;&gt;Accept SDK licences&lt;/h3&gt;
&lt;p&gt;The SDK licences must be accepted for everything to work.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager --licenses
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then type Y and press Enter for each prompt&lt;/p&gt;
&lt;h3 id=&#34;install-the-android-toolchain&#34;&gt;Install the Android toolchain&lt;/h3&gt;
&lt;p&gt;To pass the &amp;lsquo;Android toolchain&amp;rsquo; step of &lt;code&gt;flutter doctor&lt;/code&gt; (in a bit) we need 3 things:&lt;/p&gt;
&lt;ol start=&#34;0&#34;&gt;
&lt;li&gt;Platform tools (generic)&lt;/li&gt;
&lt;li&gt;A valid platform&lt;/li&gt;
&lt;li&gt;Build tools to match the platform&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Various instructions online will tell you to do things like &lt;code&gt;sdkmanager &amp;quot;platform-tools&amp;quot; &amp;quot;platforms;android-33&amp;quot;&lt;/code&gt; (ie pass multiple arguments to &lt;code&gt;sdkmanager&lt;/code&gt;), but as observed in &lt;a href = &#34;https://stackoverflow.com/questions/76650927/failed-to-find-platform-sdk-with-path-platformsandroid-33&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;this StackOverflow answer&lt;/a&gt; &lt;em&gt;if using the command line tools, the platform tools need to be installed via separate commands ie:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;platform-tools&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-33&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;build-tools;33.0.2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the installation has worked correctly you should end up with something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ tree -L &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; android_sdk/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;android_sdk/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── build-tools
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── cmdline-tools
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── licenses
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── platform-tools
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── platforms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;&lt;span&gt;Another weird, me-specific problem I encountered&amp;hellip;&lt;/span&gt;&lt;/summary&gt;

&lt;div&gt;
&lt;p&gt;At first, my installations weren&amp;rsquo;t appearing in my &lt;code&gt;android_sdk&lt;/code&gt; directory and Flutter tools were complaining about not being able to find the Android SDK.&lt;/p&gt;
&lt;p&gt;Forcing the SDK path like this worked:
&lt;code&gt;sdkmanager --verbose &amp;quot;platform-tools&amp;quot; --sdk_root=$HOME/android_sdk/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But something smelt wrong, as the original &lt;code&gt;sdkmanager&lt;/code&gt; install commands seemed to be completing without error. I investigated this by running the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;platform-tools&amp;#39;&lt;/span&gt; --verbose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which revealed that they were going into:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/data/data/com.termux/files/usr/share/android-sdk/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is because I was on Android using Termux, in a proot container, and I had previously installed the SDK in the main (non proot) Termux environment. This was not needed any more so I deleted the other installation.&lt;/p&gt;
&lt;p&gt;This is an exotic situation and you&amp;rsquo;re probably not as stupid as I am to get into this situation, but maybe this note will help in some other situation.&lt;/p&gt;
&lt;/div&gt;
&lt;/details&gt;
</description>
    </item>
    
    <item>
      <title>Dependencies and Environment</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/dependencies-and-environment/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:30 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/dependencies-and-environment/</guid>
      <description>&lt;p&gt;To get started I&amp;rsquo;m presuming you have a Linux installation of something like Debian/Ubuntu.&lt;/p&gt;
&lt;h2 id=&#34;general-dependencies&#34;&gt;General Dependencies&lt;/h2&gt;
&lt;h3 id=&#34;git&#34;&gt;Git&lt;/h3&gt;
&lt;p&gt;You probably already have this but just in case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install git
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ensure-java-jdk-is-installed-and-recent-enough&#34;&gt;Ensure Java JDK is installed and recent enough&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install openjdk-17-jdk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;stuff-flutter-needs&#34;&gt;Stuff Flutter Needs&lt;/h3&gt;
&lt;p&gt;The latest info about this should be &lt;a href = &#34;https://docs.flutter.dev/get-started/install/linux/android&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;here&lt;/a&gt; but at time of writing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get install -y curl git unzip xz-utils zip libglu1-mesa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And some other tools Flutter uses:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install clang cmake ninja-build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;if-using-chromium-browser-instead-of-chrome&#34;&gt;If using Chromium browser instead of Chrome&lt;/h3&gt;
&lt;p&gt;The Android SDK likes to know where Chrome is on your system. I use Chromium and the SDK can&amp;rsquo;t find it.&lt;/p&gt;
&lt;p&gt;So I export an environment variable to let Flutter know where to find Chromium eg in &lt;code&gt;~/.profile&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;CHROME_EXECUTABLE&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/bin/chromium
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Parts of the SDK</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/parts-of-the-sdk/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:30 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/parts-of-the-sdk/</guid>
      <description>&lt;p&gt;There are several components making up the SDK. I&amp;rsquo;ll list them here along with examples of how they can be installed later on when the SDK manager is set up and working.&lt;/p&gt;
&lt;p&gt;This is just an overview to help your mental model of what&amp;rsquo;s what, we&amp;rsquo;re not installing anything just yet.&lt;/p&gt;
&lt;p&gt;We download them as a zip and place them in a specific directory, as detailed later.&lt;/p&gt;
&lt;h3 id=&#34;command-line-tools&#34;&gt;Command Line Tools&lt;/h3&gt;
&lt;p&gt;These commands can do several things like signing and optimising APKs, but the main one we are interested in is &lt;code&gt;sdkmanager&lt;/code&gt;. This is the command we use to install the other tools.&lt;/p&gt;
&lt;h3 id=&#34;platform-tools&#34;&gt;Platform Tools&lt;/h3&gt;
&lt;p&gt;These are tools for interfacing with Android which you may already be familiar with, such as &lt;code&gt;adb&lt;/code&gt; and &lt;code&gt;fastboot&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;platform-tools&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;platforms&#34;&gt;Platforms&lt;/h3&gt;
&lt;p&gt;A platform represents a specific version of Android. It includes multiple system images, which the device emulator uses to emulate various devices on that platform.&lt;/p&gt;
&lt;p&gt;Information used to compile your app for this platform version, and source code to be used for debugging are also included.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Multiple platforms can be installed alongside each other on the same system.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;platforms;android-33&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;build-tools&#34;&gt;Build Tools&lt;/h3&gt;
&lt;p&gt;These are tools used for building Android apps. I&amp;rsquo;m not 100% clear on what these are and why they are different from Platform Tools, it seems that they were part of Platform Tools in the past but have been sectioned off into their own thing.&lt;/p&gt;
&lt;p&gt;Anyway, we need them. Usually use the latest version, but sometimes if you&amp;rsquo;re targeting specific platforms eg older ones, errors may indicate that you need an older version.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdkmanager &lt;span class=&#34;s1&#34;&gt;&amp;#39;build-tools;33.0.2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Intro</title>
      <link>https://mm-dev.rocks/posts/flutter-in-the-terminal/intro/</link>
      <pubDate>Thu, 08 Aug 2024 17:47:29 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/flutter-in-the-terminal/intro/</guid>
      <description>&lt;p&gt;Given the choice, I&amp;rsquo;d rather avoid huge complex apps like Android Studio. They use a lot of system resources and are very GUI/point-and-clicky. Those things definitely have their place but I prefer keyboard control where it makes sense, and for me programming in Flutter is one of those situations.&lt;/p&gt;
&lt;p&gt;A lot of what Android Studio does behind the scenes is automatically editing text files and running shell commands such as &lt;code&gt;flutter run&lt;/code&gt;, &lt;code&gt;flutter build&lt;/code&gt; and so on. If you&amp;rsquo;re comfortable with the terminal these commands are fairly simple to run manually.&lt;/p&gt;
&lt;p&gt;As an IDE Android Studio also helps with stuff like syntax highlighting, code completion, refactoring etc. If you&amp;rsquo;re into Vim it can be set up to give you these pleasantries. I&amp;rsquo;m sure there is stuff Android Studio can do that Vim can&amp;rsquo;t, but whatever it is I&amp;rsquo;m not missing it and I feel good when I use Vim.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve set up a couple of systems with this Flutter dev environment recently and hit some stumbling blocks. They weren&amp;rsquo;t too hard to resolve but I wanted to write up the process for future reference and to help anybody else in a similar situation.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Vanilla JS</title>
      <link>https://mm-dev.rocks/posts/vanilla-js/</link>
      <pubDate>Fri, 05 Apr 2024 12:18:03 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/vanilla-js/</guid>
      <description>&lt;h2 id=&#34;toolchain&#34;&gt;Toolchain&lt;/h2&gt;
&lt;p&gt;I enjoy using plain/vanilla JS where possible. For my own projects I try to avoid the sprawl and long build times of NPM.&lt;/p&gt;
&lt;p&gt;I do like to split my code up into separate modules though, and to be able to benefit from bundling/minification etc, for which I use &lt;em&gt;esbuild&lt;/em&gt;. I also want to be able to use &lt;em&gt;SCSS&lt;/em&gt; and &lt;em&gt;JSDoc&lt;/em&gt; for type annotations. So I do allow myself some minimal tooling (the cone and Flake).&lt;/p&gt;
&lt;p&gt;My setup looks like this&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;esbuild---download-a-build&#34;&gt;esbuild - &lt;a href = &#34;https://esbuild.github.io/getting-started/#download-a-build&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Download a build&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;JS bundler&lt;br&gt;
&lt;em&gt;Combine separate modules into a single JS file, minifying/compressing if required&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Tree shaker&lt;br&gt;
&lt;em&gt;Avoid bloat by making sure only those modules/functions which are used get added&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use esbuild for most JS projects, so I installed a standalone build which can be run from anywhere &amp;mdash; but it can also be installed using npm or other methods.&lt;/p&gt;
&lt;h3 id=&#34;sass---how-to-install-sass&#34;&gt;SASS - &lt;a href = &#34;https://sass-lang.com/install&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;How to Install SASS&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compiler and bundler&lt;br&gt;
&lt;em&gt;Converts SASS/SCSS files into CSS&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;jsdoc---documentation&#34;&gt;JSDoc - &lt;a href = &#34;https://jsdoc.app/&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Documentation&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Automated documentation creation&lt;br&gt;
&lt;em&gt;HTML docs for your methods, classes and variables will be created based on your code comments&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Type annotations&lt;br&gt;
&lt;em&gt;Comments in your code can tell JSDoc which data types your code expects&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Type annotations you provide (in specially-formatted comments) will be used to automatically create detailed documentation for your project.&lt;/p&gt;
&lt;p&gt;Docs are created as HTML files, with lots of clickable cross-references. The files can be styled based on a templating system and CSS styling.&lt;/p&gt;
&lt;p&gt;Lots of modern editors/IDEs will also use your type annotations to provide type hints and draw attention to potential problems eg if you try to pass an argument of the wrong type you&amp;rsquo;ll get a warning.&lt;/p&gt;
&lt;h3 id=&#34;example-of-project-setup-using-tmuxvim&#34;&gt;Example of Project Setup Using Tmux/Vim&lt;/h3&gt;
&lt;p&gt;I usually write a simple bash script for most projects. I&amp;rsquo;ll run this script when I want to start a session of working on a specific project.&lt;/p&gt;
&lt;p&gt;Below is an example build script (for &lt;a href = &#34;https://mm-dev.rocks/posts/pipe-dream-web-game/&#34; title = &#34;Pipe Dream&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;my &amp;lsquo;Pipe Dream&amp;rsquo; game&lt;/a&gt;) which does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enters the project directory&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;tmux&lt;/code&gt; to open a few window panes/splits:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;esbuild&lt;/strong&gt; watching for changes to JS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SASS&lt;/strong&gt; watching for changes to CSS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSDoc&lt;/strong&gt; watching the &lt;code&gt;src&lt;/code&gt; directory (in reality I&amp;rsquo;d often skip this and run it manually on-demand, as it can be slow)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;git&lt;/strong&gt; status, pane left open for commits etc&lt;/li&gt;
&lt;li&gt;A simple &lt;strong&gt;Python server&lt;/strong&gt; so I can test the app in a browser&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Opens a &lt;strong&gt;vim&lt;/strong&gt; session with the relevant source files ready for editing&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Open a JS project using esbuild, SASS and vim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;work_dir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;/pipe-dream/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;tmux&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    new-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;esbuild src/main.js --outfile=www/js/pipe-dream.js --target=es6 --bundle --minify --sourcemap --global-name=PIPEDREAM --format=iife --watch&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    split-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sass --watch src/scss/:www/css/&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    split-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;jsdoc src/ -c jsdoc.config&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    split-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;git status; bash -i&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    split-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;python -m http.server --directory www/&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;select&lt;/span&gt;-layout even-vertical &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    new-window -c &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$work_dir&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vim -S vim.Session&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;vim-configuration&#34;&gt;Vim Configuration&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m one of those Vim people. People say its codebase is bloated but in use it always feels crisp and fast to me. Because of the way you manipulate text objects and leap around the page it somehow feels efficient on low-powered/slow devices, and works particularly well with &lt;a href = &#34;https://mm-dev.rocks/posts/oled-and-eink-4-life/intro/&#34; title = &#34;OLED and E-Ink&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;e-ink devices&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some people argue that they&amp;rsquo;re faster while using Vim than they are in other code editors. I&amp;rsquo;m not sure if I&amp;rsquo;m faster (I might be), but I&amp;rsquo;m from the school of thought that if your bottleneck when writing code is your typing speed, that might not be a good thing.&lt;/p&gt;
&lt;p&gt;More importantly for me, I like the way Vim makes you think about text, as beautifully described in this classic stackoverflow answer &amp;lsquo;&lt;a href = &#34;https://stackoverflow.com/questions/1218390/what-is-your-most-productive-shortcut-with-vim/1220118#1220118&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Your problem with Vim is that you don&amp;rsquo;t grok vi&lt;/a&gt;&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t like my coding environment to be too noisy or intrusive, but there are some powerful IDE features available nowadays and I don&amp;rsquo;t want to cut off my nose to spite my face.&lt;/p&gt;
&lt;p&gt;Below is some info on some Vim plugins I use to help with JS development.&lt;/p&gt;
&lt;h3 id=&#34;coc-nvim---code-of-conquer-project-repo&#34;&gt;coc-nvim - &lt;a href = &#34;https://github.com/neoclide/coc.nvim&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Code of Conquer project repo&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Although the &amp;rsquo;nvim&amp;rsquo; stands for Neovim (the popular Vim fork), COC also works very well in modern versions of normal Vim. This plugin allows VSCode-type IDE features, being based on the &lt;a href = &#34;https://en.wikipedia.org/wiki/Language_Server_Protocol&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Language Server Protocol&lt;/a&gt; standard.&lt;/p&gt;
&lt;p&gt;Very simply, a language server is a tool which understands a specific language, and can be used by your editor/IDE to analyse and give feedback on your code as you write it. It can do things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;li&gt;Code completion&lt;/li&gt;
&lt;li&gt;Draw attention to errors and give warnings about code&lt;/li&gt;
&lt;li&gt;Help when refactoring code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;COC isn&amp;rsquo;t a language server itself but it allows you to install and maintain whichever servers you need for the languages you use.&lt;/p&gt;
&lt;p&gt;For example the language server I use for JS is &lt;a href = &#34;https://github.com/neoclide/coc-tsserver&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;coc-tsserver&lt;/a&gt;. The &amp;rsquo;ts&amp;rsquo; stands for TypeScript but it works very well with standard JS too. Along with the benefits mentioned above, this language server allows you to use type-checking, like TypeScript but without the compilation step. It also provides documentation and hints on using standard built-in JS methods.&lt;/p&gt;
&lt;p&gt;You annotate your code by providing special comments in &lt;em&gt;JSDoc&lt;/em&gt; syntax. When these comments/annotations are present, COC and the language server give you lots of hints while writing code, and warn you if you try to provide arguments of the wrong type.&lt;/p&gt;
&lt;p&gt;Here is an example (from the &lt;a href = &#34;https://jsdoc.app/howto-es2015-classes&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;official docs&lt;/a&gt;) showing what the &lt;em&gt;JSDoc&lt;/em&gt; syntax looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-JavaScript&#34; data-lang=&#34;JavaScript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/** Class representing a point. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Point&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * Create a point.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @param {number} x - The x value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @param {number} y - The y value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;constructor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * Get the x value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @return {number} The x value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;getX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * Get the y value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @return {number} The y value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;getY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * Convert a string containing two comma-separated numbers into a point.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @param {string} str - The string containing two comma-separated numbers.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     * @return {Point} A Point object.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;     */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fromString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Sometimes the help is a little noisy though&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I love the functionality, but for me it&amp;rsquo;s a bit over-eager, eg if I&amp;rsquo;m half-way through typing a word I don&amp;rsquo;t need a popup telling me the word doesn&amp;rsquo;t exist.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;coc-nvim&lt;/em&gt; does also provide a small symbol at the start of each line where it detects an error or wants to warn about something. So I like to leave the symbol visible, but hide the info popups by default. I add a keyboard shortcut so I can show/hide the explanation of the error/warning when I want to.&lt;/p&gt;
&lt;p&gt;To stop the popups:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-JSON&#34; data-lang=&#34;JSON&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// In ~/.vim/coc-settings.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;diagnostic.enableMessage&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;jump&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To add the show/hide keyboard shortcuts to Vim:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-VimL&#34; data-lang=&#34;VimL&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;&amp;#34; In ~/.vimrc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;nmap&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;silent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gh&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;nmap&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;silent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;gl&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Plug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;coc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;diagnostic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;prettier&#34;&gt;Prettier&lt;/h3&gt;
&lt;p&gt;This &lt;a href = &#34;https://prettier.io/&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;opinionated code formatter&lt;/a&gt; formats your code according to some fairly strict rules and has few configurable options (ie it&amp;rsquo;s their way or the highway).&lt;/p&gt;
&lt;p&gt;I think most people find at least some of the rules disagreeable, but the point of this kind of tool is that it does a &amp;lsquo;decent, not perfect&amp;rsquo; job, but provides a standard for formatting and removes the need for discussing, disagreement and wasted time.&lt;/p&gt;
&lt;p&gt;I found it a little annoying at first but then got over myself and prefer now to use it whenever possible.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The Bad Parts</title>
      <link>https://mm-dev.rocks/posts/android-as-a-dev-environment/the-bad-parts/</link>
      <pubDate>Fri, 05 Apr 2024 11:44:43 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/android-as-a-dev-environment/the-bad-parts/</guid>
      <description>&lt;h3 id=&#34;the-low-memory-killer-daemon---official-docs&#34;&gt;The Low Memory Killer Daemon - &lt;a href = &#34;https://source.android.com/docs/core/perf/lmkd&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Official Docs&lt;/a&gt;.&lt;/h3&gt;
&lt;p&gt;This feature of modern Android versions kills tasks (/apps) when it thinks they are causing memory-related performance problems. It can feel pretty heavy-handed, with apps abruptly closing at seemingly random intervals.&lt;/p&gt;
&lt;p&gt;In practice this can irritate but I&amp;rsquo;ve never lost any work because of it. The most noticeable occurrence is when &lt;em&gt;Termux:X11&lt;/em&gt; closes &amp;mdash; my Linux desktop suddenly shuts down! Sounds terrible But actually my Vim buffers are constantly auto-saved, my browser tabs are stored&amp;hellip; I just have to restart the session, then &lt;em&gt;Tmux&lt;/em&gt;, then maybe a couple of other items. I&amp;rsquo;m back up and running in 1-2 minutes, and this problem might occur once or twice per week at the most.&lt;/p&gt;
&lt;p&gt;There are various ways to tweak the daemon though, search for terms like &amp;lsquo;disable android oom killer&amp;rsquo;, &amp;rsquo;tweak low memory killer daemon android&amp;rsquo; etc.&lt;/p&gt;
&lt;h3 id=&#34;missing-tools-for-arm-architecture&#34;&gt;Missing Tools for ARM Architecture&lt;/h3&gt;
&lt;p&gt;As the types of CPU in Android devices (usually ARM) are not the same as those used in laptops/desktops (usually X86), the standard desktop versions of software can&amp;rsquo;t be installed and compatible versions must be available (unless you want to compile them yourself).&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t as bad as it sounds as the package manager for whichever distro you use will automatically pull in the correct version for your CPU architecture. Some software might be missing though.&lt;/p&gt;
&lt;p&gt;A couple of specific gaps in the system affect me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Garmin Monkey C&lt;br&gt;
&lt;em&gt;Garmin apps are written in their own language &amp;lsquo;Monkey C&amp;rsquo;, which has to use their own Java-based compiler and device simulator. As far as I can tell this isn&amp;rsquo;t happening on ARM. It was hard enough to get it working on Linux and Vim as they presume Windows/VSCode in their tutorials, so once I achieved that I didn&amp;rsquo;t take it any further.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Flutter cross-compilation&lt;br&gt;
&lt;em&gt;The situation with Flutter is strange. Flutter is used to make multi-platform apps, so the same code can output apps for Linux, Android, Windows etc. I can build a Linux (ARM64) binary on my Android Ubuntu&amp;hellip; and I can build an Android binary on my (normal, X86 desktop) Linux. But I can&amp;rsquo;t build an Android binary from Android. Apparently people were able to do this on older versions of Flutter, so it seems like Google (who control Flutter) intentionally stopped supporting it.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;fingers-crossed&#34;&gt;Fingers crossed!&lt;/h3&gt;
&lt;p&gt;Mine is a niche use-case and I understand that I can&amp;rsquo;t expect organisations to support such a tiny minority as ARM Linux. Apple&amp;rsquo;s M1/M2/M3 ARM chips are doing very well, which is great if you&amp;rsquo;re into that but I don&amp;rsquo;t enjoy their ecosystem.&lt;/p&gt;
&lt;p&gt;So for now I need to hang on to my X86 desktop. But I hope ARM continues to gain recognition as more than a mobile phone CPU and can be used for more development tasks in future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Software</title>
      <link>https://mm-dev.rocks/posts/android-as-a-dev-environment/software/</link>
      <pubDate>Fri, 05 Apr 2024 11:44:41 +0100</pubDate>
      <guid>https://mm-dev.rocks/posts/android-as-a-dev-environment/software/</guid>
      <description>&lt;p&gt;&lt;em&gt;Although this is all in relation to working on Android, the software I use is generally the same as if I was on a Linux desktop. That&amp;rsquo;s kind of the point, nowadays I can use almost the same environment on Android as I can on my desktop.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;termux&#34;&gt;Termux&lt;/h3&gt;
&lt;p&gt;&lt;a href = &#34;https://termux.dev/en/&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Termux&lt;/a&gt; is a brilliant free terminal app and Linux environment for Android. It has most of the Linux commands I need and I can install &lt;em&gt;git&lt;/em&gt;, &lt;em&gt;Vim&lt;/em&gt;, &lt;em&gt;Tmux&lt;/em&gt;, &lt;em&gt;mutt&lt;/em&gt;, &lt;em&gt;ImageMagick&lt;/em&gt;  and the majority of the terminal software I like to use. For certain jobs such as scripting, SSH sessions and writing, this is all I need.&lt;/p&gt;
&lt;p&gt;Termux can run non-terminal, graphical apps too, but you won&amp;rsquo;t be able to see them. That&amp;rsquo;s what the next app is for.&lt;/p&gt;
&lt;h3 id=&#34;termuxx11&#34;&gt;Termux:X11&lt;/h3&gt;
&lt;p&gt;&lt;a href = &#34;https://github.com/termux/termux-x11&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;This amazingly useful app&lt;/a&gt; describes itself as being in early development, but I&amp;rsquo;ve been daily-driving it for months without significant issues.&lt;/p&gt;
&lt;p&gt;Termux:X11 is an X Server for Termux. This allows you to install graphical Linux apps, as long as they are available for your system architecture (ie AArch64 &amp;mdash; or ARM64 as it&amp;rsquo;s known &amp;mdash; for most modern Android devices).&lt;/p&gt;
&lt;p&gt;This means I can run, directly on my tablet:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Desktop &lt;em&gt;Firefox&lt;/em&gt; (so, full developer tools)&lt;/li&gt;
&lt;li&gt;Desktop &lt;em&gt;Chromium&lt;/em&gt; (this was quite hard to get installed and isn&amp;rsquo;t the absolute latest version but is still very useful for development)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Krita&lt;/em&gt;/&lt;em&gt;Inkscape&lt;/em&gt;/&lt;em&gt;GIMP&lt;/em&gt; for image processing&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Thunar&lt;/em&gt; file manager&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Audacity&lt;/em&gt; (using &lt;em&gt;PulseAudio&lt;/em&gt; over the network to pipe the audio up to Android by using the devices own IP address&amp;hellip; I&amp;rsquo;m sure this creates some delay/latency but I&amp;rsquo;ve not noticed it in practice and for my typical usage of minor adjustments to audio files it works well)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;proot-distro&#34;&gt;PRoot Distro&lt;/h3&gt;
&lt;p&gt;This is a &amp;lsquo;container environment manager&amp;rsquo; and allows you to easily install, uninstall, backup and restore Linux distributions, alongside/on-top-of Android, sharing the kernel.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s really simple to use, eg installing Debian Linux is a matter of opening &lt;em&gt;Termux&lt;/em&gt; and entering:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;proot-distro install debian
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then for a shell login:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;proot-distro login debian
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;PRoot Distro &lt;a href = &#34;https://github.com/termux/proot-distro&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;provides a nice choice of distros&lt;/a&gt; including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alpine Linux (edge)&lt;/li&gt;
&lt;li&gt;Arch Linux ARM&lt;/li&gt;
&lt;li&gt;Artix Linux (AArch64 only)&lt;/li&gt;
&lt;li&gt;Debian (stable)&lt;/li&gt;
&lt;li&gt;Fedora 38 (AArch64 only)&lt;/li&gt;
&lt;li&gt;Manjaro (AArch64 only)&lt;/li&gt;
&lt;li&gt;OpenSUSE (Tumbleweed)&lt;/li&gt;
&lt;li&gt;Pardus (yirmibir)&lt;/li&gt;
&lt;li&gt;Ubuntu (23.10)&lt;/li&gt;
&lt;li&gt;Void Linux&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can install as many distros as you want and swap between them easily. Each distro just sits in a directory on the Android device. Using the backup tools the entire system can be bundled up as a single archive file and moved over to another Android device.&lt;/p&gt;
&lt;h2 id=&#34;window-management&#34;&gt;Window Management&lt;/h2&gt;
&lt;p&gt;I believe that the best user interface (actually, interface of any kind) is one that I don&amp;rsquo;t even notice exists. It doesn&amp;rsquo;t shout at me, it doesn&amp;rsquo;t wow me with animations and eye-candy. It allows me to get to the tools I need to get the job done and stay immersed in the task. It is at peace with itself enough to take a back seat and not demand attention. It is, conceptually, transparent.&lt;/p&gt;
&lt;p&gt;A lot of people like the gestural UI featured in &amp;lsquo;Minority Report&amp;rsquo;. I like the film, and the scene with Tom Cruise manipulating the UI is well produced and fun to watch. But as a UI it&amp;rsquo;s terrible! Hugely inefficient with all those big sweeping hand gestures, it&amp;rsquo;s not quick or practical. I don&amp;rsquo;t want to have to perform interpretive dance to use my computer (nor watch my computer doing little performances when I&amp;rsquo;m trying to get stuff done).&lt;/p&gt;
&lt;p&gt;I found similar sentiment in this &lt;a href = &#34;https://daringfireball.net/2024/01/the_vision_pro&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Daring Fireball article about the Apple Vision Pro&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;To me the Macintosh has always felt more like a place than a thing. Not a place I go physically, but a place my mind goes intellectually. When I’m working or playing and in the flow, it has always felt like MacOS is where I am. I’m in the Mac.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Interruptions — say, the doorbell or my phone ringing — are momentarily disorienting when I’m in the flow on the Mac, because I’m pulled out of that world and into the physical one.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I am nearly exactly like this too, except I don&amp;rsquo;t want to feel like I&amp;rsquo;m &amp;ldquo;in the Linux&amp;rdquo; (and definitely not &amp;ldquo;in the Mac&amp;rdquo; or &amp;ldquo;in Windows&amp;rdquo;!). I don&amp;rsquo;t want to be aware of that layer of abstraction at all. I don&amp;rsquo;t mind feeling that I&amp;rsquo;m &amp;ldquo;in Vim&amp;rdquo;, but really I want to be &amp;ldquo;in the code&amp;rdquo; that I&amp;rsquo;m editing. I specifically don&amp;rsquo;t want to feel the manicured claw of a corporate behemoth like Apple or Microsoft on my shoulder&amp;hellip; but that&amp;rsquo;s just me.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d rather forget that my OS(/window manager) exists. It&amp;rsquo;s a facilitator, not an end in itself.&lt;/p&gt;
&lt;h3 id=&#34;dwm-tiling-window-manager&#34;&gt;DWM: Tiling Window Manager&lt;/h3&gt;
&lt;p&gt;I used to prefer larger screens and multiple monitors. I knew about the concept of workspaces but they sounded annoying and fiddly. It took me a long time to give them a chance and it happened accidentally, as a side-effect of trying a tiling window manager.&lt;/p&gt;
&lt;p&gt;Very briefly, a tiling window manager organises your windows into tiles, meaning instead of having oddly-sized overlapping windows floating around making a confusing mess of your screen and using space inefficiently, your screen splits into fractions, each being filled by an app. If you have too many apps on the screen they can go onto other screens, or &amp;lsquo;workspaces&amp;rsquo;. Personally I tend to run most apps fullscreen most of the time, switching between them with keyboard shortcuts.&lt;/p&gt;
&lt;p&gt;I started with &lt;a href = &#34;https://i3wm.org/&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;i3 Window Manager&lt;/a&gt;, which is a really nice piece of software. After a few years of using it though I realised I didn&amp;rsquo;t use most of its features, so landed on the very minimal &lt;a href = &#34;https://dwm.suckless.org/&#34; target = &#34;_blank&#34; rel = &#34;nofollow noopener noreferrer&#34;&gt;Suckless Tools DWM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With workspaces, each app can have its own screen and can be accessed instantly via a keyboard shortcut. With familiarity this becomes a chord in muscle memory, a hand-shape to mash at keyboard. I have habits for where I keep each app, so eg my terminal is in workspace 1 so &lt;code&gt;[Alt]+[1]&lt;/code&gt; puts me in the terminal. &lt;code&gt;[Alt]+[9]&lt;/code&gt; puts me in FireFox and so on.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve &lt;code&gt;[Alt]+[Tab]&lt;/code&gt;bed through apps in the past. Workspaces are similar except you know the keyboard chord will take you directly to the app you want, you don&amp;rsquo;t have to play &amp;lsquo;stop the magical app carousel at the right time&amp;rsquo;&amp;hellip; which may be a drawback for some I guess, as carousels can be fun.&lt;/p&gt;
&lt;p&gt;We can only focus on one thing at a time, that&amp;rsquo;s how attention works. I can see some uses for multiple screens eg if you have to monitor lots of things, like real-time charts or meters. In that case your peripheral vision is good at detecting change/motion so you can make use of all the space. But personally I&amp;rsquo;m completely over large/multiple displays. In my circumstances, they waste power, waste space, and are just not necessary.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
