<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Z Space Blog - SQLite</title><link href="https://zlg.space/blog/" rel="alternate"/><link href="https://zlg.space/blog/feeds/t/sqlite.atom.xml" rel="self"/><id>https://zlg.space/blog/</id><updated>2025-09-25T00:46:00-07:00</updated><entry><title>Say hello to vgstash!</title><link href="https://zlg.space/blog/say-hello-to-vgstash.html" rel="alternate"/><published>2016-05-22T22:27:00-07:00</published><updated>2025-09-25T00:46:00-07:00</updated><author><name>zlg</name></author><id>tag:zlg.space,2016-05-22:/blog/say-hello-to-vgstash.html</id><summary type="html">&lt;p&gt;Today, I'm announcing the release of &lt;a href="https://git.zlg.space/vgstash"&gt;&lt;code&gt;vgstash&lt;/code&gt;&lt;/a&gt;, a command line program
that keeps track of your game collection and progress in a small SQLite
database. I'm happy to finally bring this to fruition. The story of its
inception follows.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Today, I'm announcing the release of &lt;a href="https://git.zlg.space/vgstash"&gt;&lt;code&gt;vgstash&lt;/code&gt;&lt;/a&gt;, a command line program
that keeps track of your game collection and progress in a small SQLite
database. I'm happy to finally bring this to fruition. The story of its
inception follows.&lt;/p&gt;


&lt;h1&gt;Inspiration&lt;/h1&gt;
&lt;p&gt;I was having a conversation on IRC about Python, lamenting my lack of project
ideas to learn the language better. During the conversation, I mentioned a game
manager I wanted to make, but I was hesitant to begin working on it until I
was sure I'd accounted for all semantic use cases. One person said, "What's
important to you about this tool?" That was the tipping point that got the ol'
gears turning. Why did I have this idea in the first place?&lt;/p&gt;
&lt;p&gt;I wanted a good way to manage my games without relying on an outside entity. Did
I care about it being a website? Not really; the mechanism didn't matter too
much to me as long as it worked. Did I really care if other people used it? Was
I interested in launching a website, building interest and engaging with the
public about it? Not really; socialization's never been my strong point, and I
wasn't ready for the consequences of gaining popularity: expectations, feature
requests, and considerable time to refine it.&lt;/p&gt;
&lt;p&gt;However, I strongly believe in the mantra of libre software: scratching your own
itch. So I identified the itch ("I need a game manager") and felt Python was a
great fit for it, since it comes with an SQLite3 module out of the box, a good
argument parsing module, and lots of options for data serialization. At that
point, the hard work was already done for me: &lt;em&gt;scope&lt;/em&gt;.&lt;/p&gt;
&lt;h1&gt;Implementation&lt;/h1&gt;
&lt;p&gt;Determining the scope of your project is important. It allows you to form
opinions on the data format it should rely on, which will help forge the path
for your implementation. This distinction is important; many programmers
approach it from a skeleton, a design document, or ad hoc. Some projects work
really well for that. Projects that deal with data storage and manipulation
(that is, most of them) should care very much about their data format. If you
nail the format, the rest of the code pretty much writes itself.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vgstash&lt;/code&gt;'s data format is as simple as I could make it without losing important
features. Nailing down this narrowed scope was almost liberating. My idea of
a game manager went from a grandiose Gordian knot of complexity to a command
line tool that plays nicely with others. &lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;1&lt;/a&gt;&lt;/sup&gt; Because of this, I got a number
of features for free: simple searching (thanks to &lt;code&gt;grep&lt;/code&gt;), text manipulation
(&lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;cut&lt;/code&gt;, and friends), and data serialization (pyyaml). This cut the
amount of time necessary to write the program, and it still supports everything
I aimed for. This simplicity assists in code maintenance; vgstash is nowhere
near complete or "correct", but it's important to do 80% of the job decently
than obsess over 100% perfection. Releasing a project and gaining attention
gives it momentum, and an incentive to continue development.&lt;/p&gt;
&lt;h1&gt;Usage&lt;/h1&gt;
&lt;p&gt;The documentation is still a bit rough for now. It works a lot like &lt;code&gt;git&lt;/code&gt; in
some ways. Here's a scenario (output is after a &lt;code&gt;&amp;gt;&lt;/code&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# I just picked up a game, let&amp;#39;s add it to my collection!&lt;/span&gt;
&lt;span class="c1"&gt;# It&amp;#39;s Dark Souls for the PS3&lt;/span&gt;
&lt;span class="c1"&gt;# I own it now, but I&amp;#39;ve never played it so it&amp;#39;s [f]resh.&lt;/span&gt;
&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vgstash&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Dark Souls&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;PS3&lt;span class="w"&gt; &lt;/span&gt;y&lt;span class="w"&gt; &lt;/span&gt;f
&lt;/span&gt;&lt;span class="c1"&gt;# &amp;gt; Added Dark Souls for PS3. You own it and it&amp;#39;s fresh.&lt;/span&gt;

&lt;span class="c1"&gt;# Show me a list of my games!&lt;/span&gt;
&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vgstash&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/span&gt;
&lt;span class="c1"&gt;# Okay I got a nice table, which ones have I beaten?&lt;/span&gt;
&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vgstash&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;beaten
&lt;/span&gt;
&lt;span class="c1"&gt;# Nice, nice. Well, I just beat Dark Souls. What now?&lt;/span&gt;
&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vgstash&lt;span class="w"&gt; &lt;/span&gt;list&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Dark Souls&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;span class="c1"&gt;# &amp;gt; 45&lt;/span&gt;

&lt;span class="c1"&gt;# That gave me the game&amp;#39;s ID... Let&amp;#39;s update it&lt;/span&gt;
&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;vgstash&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;45&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;progress&lt;span class="w"&gt; &lt;/span&gt;b
&lt;/span&gt;&lt;span class="c1"&gt;# &amp;gt; Dark Souls on PS3 is now marked beaten.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may notice that updating is a two-step process. You have to know the ID of
the game in order to update it. That's a ripe case for automation. vgstash was
designed to allow for that. In fact, I wrote a tentative shell script (found in
the repository) that will help you interactively update a game. Just give it an
argument to pass to &lt;code&gt;grep&lt;/code&gt; and it takes care of the rest.&lt;/p&gt;
&lt;h1&gt;Philosophy&lt;/h1&gt;
&lt;p&gt;Command line programs often use similar interfaces, and play nicely with piping.
Piping allows the user to bring out the full capability of the *nix environment
by treating programs as filters for text streams. It means programs are smaller
and more dedicated to a task. vgstash just stores your game collection and gives
you a set of commands to work with it. Other features (searching, interactively
updating, fancy interfaces, etc) should be handled by other programs, so users
can build and/or use scripting to their advantage. This phenomenon is known as
the UNIX philosophy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;"Do one thing, and do it well."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That said, vgstash and any helper scripts in question are considered
experimental quality, so treat them accordingly.&lt;/p&gt;
&lt;p&gt;I'm extremely happy to have built this tool and hope that others find it useful,
too. Patches, comments, and suggestions are welcome.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2022-09-04 UPDATE:&lt;/strong&gt; VGStash's CLI syntax has changed somewhat since the
announcement, and is available via PyPI! Visit the &lt;a href="https://pypi.org/project/vgstash"&gt;VGStash PyPI Project
Page&lt;/a&gt; for the latest release information.&lt;/p&gt;
&lt;p&gt;I have done some rudimentary testing on Windows and it appears to work in a
Command Prompt on Windows 7. I am in need of Windows-based testers, for cmd.eme,
PowerShell, MinGW, and/or WSL2. OS X users shouldn't have any issues interfacing
with VGStash, as long as pip's install path is somewhere in &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Well, ideally anyway. :)&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="Software"/><category term="Python"/><category term="Video Games"/><category term="Command Line"/><category term="SQLite"/></entry></feed>