<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Z Space Blog - Programming</title><link href="https://zlg.space/blog/" rel="alternate"/><link href="https://zlg.space/blog/feeds/t/programming.atom.xml" rel="self"/><id>https://zlg.space/blog/</id><updated>2023-03-16T20:02:00-07:00</updated><entry><title>Why I learned C "Category-0" Style</title><link href="https://zlg.space/blog/why-i-learned-c-category-0-style.html" rel="alternate"/><published>2023-03-16T20:02:00-07:00</published><updated>2023-03-16T20:02:00-07:00</updated><author><name>zlg</name></author><id>tag:zlg.space,2023-03-16:/blog/why-i-learned-c-category-0-style.html</id><summary type="html">&lt;p&gt;I've been asked a few times over the years why I chose to learn C with the
colloquially-known "K&amp;amp;R C Bible", and specifically the &lt;a href="https://clc-wiki.net/wiki/K%26R2_solutions:Ancillary:Category_numbers"&gt;&lt;em&gt;Category-0&lt;/em&gt;&lt;/a&gt;
style, coined on USENET back in the day.&lt;/p&gt;
&lt;p&gt;For those unfamiliar, I'm talking about &lt;em&gt;The C Programming Language, 2nd Ed.&lt;/em&gt;,
by Brian Kernighan and Dennis Ritchie, the creators of the language. In it are
a series of exercises that the reader can work on to build their knowledge of
C through actually building something with it. On &lt;code&gt;comp.lang.c&lt;/code&gt;, people would
share their solutions to exercises in this book. After a while, they coined
different categories of solutions, to refer to their robustness and complexity.&lt;/p&gt;
&lt;p&gt;Category-0 is solving each exercise &lt;em&gt;using only the knowledge the book gives 
you, up to that point&lt;/em&gt;. In other words, it's to approach it as a complete newbie 
and see what you can put together using only the stuff you've learned in the 
book.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I've been asked a few times over the years why I chose to learn C with the
colloquially-known "K&amp;amp;R C Bible", and specifically the &lt;a href="https://clc-wiki.net/wiki/K%26R2_solutions:Ancillary:Category_numbers"&gt;&lt;em&gt;Category-0&lt;/em&gt;&lt;/a&gt;
style, coined on USENET back in the day.&lt;/p&gt;
&lt;p&gt;For those unfamiliar, I'm talking about &lt;em&gt;The C Programming Language, 2nd Ed.&lt;/em&gt;,
by Brian Kernighan and Dennis Ritchie, the creators of the language. In it are
a series of exercises that the reader can work on to build their knowledge of
C through actually building something with it. On &lt;code&gt;comp.lang.c&lt;/code&gt;, people would
share their solutions to exercises in this book. After a while, they coined
different categories of solutions, to refer to their robustness and complexity.&lt;/p&gt;
&lt;p&gt;Category-0 is solving each exercise &lt;em&gt;using only the knowledge the book gives 
you, up to that point&lt;/em&gt;. In other words, it's to approach it as a complete newbie 
and see what you can put together using only the stuff you've learned in the 
book.&lt;/p&gt;


&lt;p&gt;I had considerable difficulty learning C at first, due mostly to its 
similarities to C++, the challenge of finding good advice and practice, etc. I 
settled on the K&amp;amp;R because it was written by the original language authors. By 
choosing my reference on that criteria, I was certain to find a book that was 
more accurate than most, at minimum.&lt;/p&gt;
&lt;p&gt;After buying my copy and eventually discovering the
&lt;a href="https://clc-wiki.net/wiki/"&gt;clc-wiki&lt;/a&gt;, I started grinding out &lt;a href="https://git.zlg.space/knr"&gt;my own K&amp;amp;R
solutions&lt;/a&gt;. As you can see via the commit log on the
repository, it was a very slow advancement due to real life interfering. But I
did eventually complete it, so that's cool, right?&lt;/p&gt;
&lt;p&gt;Similarly, I have a copy of &lt;em&gt;Programming in Lua&lt;/em&gt;, by Roberto Ierusalimschy, one
of the language's authors, and it's also a wonderful resource in teaching me
Lua. I've heard Stroustrup's C++ books are great for learning. I would buy a
similar reference for Python by Guido van Rossum, but Python is a large beast
that evolves quickly via PEPs and its online docs are superb, so I'm not sure 
what the value of it would be.&lt;/p&gt;
&lt;p&gt;If you're into C, feel free to give it a look. Patches and constructive feedback
are both welcome. There are plans to make a "modern C standard" version of the 
solutions as well, to illustrate the difference between "good code for learning" 
and "the way you should actually build this".&lt;/p&gt;</content><category term="Software"/><category term="C"/><category term="Category-0"/><category term="Programming"/></entry><entry><title>Easy diffing with Vim</title><link href="https://zlg.space/blog/easy-diffing-with-vim.html" rel="alternate"/><published>2018-10-13T00:00:00-07:00</published><updated>2018-12-06T00:00:00-08:00</updated><author><name>zlg</name></author><id>tag:zlg.space,2018-10-13:/blog/easy-diffing-with-vim.html</id><summary type="html">&lt;p&gt;Vim has good support for showing the differences between two (or three) files
with either the &lt;code&gt;vimdiff&lt;/code&gt; command or setting up a diff session manually.
This often requires opening the files in their own window panes, then using
&lt;code&gt;:diffthis&lt;/code&gt; in all the relevant files. If you're in the middle of an editing
session, stopping to set up this diff session can cause you to lose focus. I
wrote a function in my &lt;code&gt;vimrc&lt;/code&gt; that automates this process, so the user can 
focus on making decisions instead of building their UI or some other 
flow-breaking process.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Vim has good support for showing the differences between two (or three) files
with either the &lt;code&gt;vimdiff&lt;/code&gt; command or setting up a diff session manually.
This often requires opening the files in their own window panes, then using
&lt;code&gt;:diffthis&lt;/code&gt; in all the relevant files. If you're in the middle of an editing
session, stopping to set up this diff session can cause you to lose focus. I
wrote a function in my &lt;code&gt;vimrc&lt;/code&gt; that automates this process, so the user can 
focus on making decisions instead of building their UI or some other 
flow-breaking process.&lt;/p&gt;


&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;quot; Function: BufDiff&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; Author: zlg &amp;lt;zlg+viml@zlg.space&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; Date: 2018-10-12&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; License: GNU GPL, version 3 &amp;lt;https://gnu.org/licenses/gpl-3.0.html&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; Description: Open a new tab page with two or three buffers and enter diff mode.&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; Long Description:&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; BufDiff accepts two or three buffer arguments and opens a new tab page to&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; work with them in diff mode. This ensures that your existing window and&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; buffer layout is preserved while providing an easy way to enter a diff&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; session. The arguments can be any argument that can also be passed to&lt;/span&gt;
&lt;span class="c"&gt;&amp;quot; the &amp;quot;:buffer&amp;quot; Ex-command, including partial filenames (if quoted).&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt; BufDiff&lt;span class="p"&gt;(&lt;/span&gt;buf1&lt;span class="p"&gt;,&lt;/span&gt; buf2&lt;span class="p"&gt;,&lt;/span&gt; ...&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; fname &lt;span class="p"&gt;=&lt;/span&gt; substitute&lt;span class="p"&gt;(&lt;/span&gt;expand&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;sfile&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;^function &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;a&lt;/span&gt;:&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        echohl ErrorMsg
        &lt;span class="k"&gt;echomsg&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;:fname . &lt;span class="s2"&gt;&amp;quot;: This function accepts a maximum of three arguments.&amp;quot;&lt;/span&gt;
        echohl None
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;

&lt;span class="c"&gt;    &amp;quot; Check for a third buffer, which will default to zero if not present&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;a&lt;/span&gt;:buf3 &lt;span class="p"&gt;=&lt;/span&gt; get&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;bufexists&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:buf1&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;bufexists&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:buf2&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="p"&gt;!&lt;/span&gt;bufexists&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;a&lt;/span&gt;:buf3&lt;span class="p"&gt;))&lt;/span&gt;
        echohl ErrorMsg
        &lt;span class="k"&gt;echomsg&lt;/span&gt; &lt;span class="k"&gt;l&lt;/span&gt;:fname . &lt;span class="s2"&gt;&amp;quot;: One or more buffer number(s) not found!&amp;quot;&lt;/span&gt;
        echohl None
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;tabnew&lt;/span&gt;
        exe &lt;span class="s2"&gt;&amp;quot;:buffer &amp;quot;&lt;/span&gt; . &lt;span class="k"&gt;a&lt;/span&gt;:buf1
        &lt;span class="k"&gt;diffthis&lt;/span&gt;
        &lt;span class="k"&gt;vsplit&lt;/span&gt;
        exe &lt;span class="s2"&gt;&amp;quot;:buffer &amp;quot;&lt;/span&gt; . &lt;span class="k"&gt;a&lt;/span&gt;:buf2
        &lt;span class="k"&gt;diffthis&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;a&lt;/span&gt;:buf3
            &lt;span class="k"&gt;vsplit&lt;/span&gt;
            exe &lt;span class="s2"&gt;&amp;quot;:buffer &amp;quot;&lt;/span&gt; . &lt;span class="k"&gt;a&lt;/span&gt;:buf3
            &lt;span class="k"&gt;diffthis&lt;/span&gt;
        &lt;span class="k"&gt;endif&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;endif&lt;/span&gt;
&lt;span class="k"&gt;endfunction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;BufDiff()&lt;/code&gt; allows me to reference two or three open buffers and put them into
a separate diff session via a tab page. When I'm done working with the diff
session, I can &lt;code&gt;:tabc&lt;/code&gt; to close the tabpage and my original session (from the
prior tabpage) is still intact, ready for me to continue work.&lt;/p&gt;
&lt;p&gt;Using it is simple. Let's say you invoke vim with &lt;code&gt;vim foo.txt bar.txt&lt;/code&gt;.
You'll end up in Vim with the contents of &lt;code&gt;foo.txt&lt;/code&gt; (or an empty buffer ready
for writing to said file), with &lt;code&gt;bar.txt&lt;/code&gt; in a second buffer. If I do &lt;code&gt;:call
BufDiff(1,2)&lt;/code&gt;, the new tabpage will come up and compare the two files. I could
also use &lt;code&gt;:call BufDiff("foo", "bar")&lt;/code&gt;, since the arguments get sent to the
&lt;code&gt;:buffer&lt;/code&gt; Ex-command.&lt;/p&gt;
&lt;p&gt;The primary limitation of &lt;code&gt;BufDiff&lt;/code&gt; is you need the files you want to compare
to be present in the buffer list already. Many people begin working on their
projects with a one-liner that opens all the relevant source files, so it's a
limitation that I think is bearable.&lt;/p&gt;
&lt;p&gt;If you use this function, let me know how it worked out for you! Improvements 
and suggestions are also welcome.&lt;/p&gt;
&lt;p&gt;Shoutout to tockitj from Freenode's &lt;code&gt;#vim&lt;/code&gt; channel for the inspiration.&lt;/p&gt;</content><category term="Software"/><category term="Vim"/><category term="Programming"/></entry></feed>