﻿<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text" xml:lang="en">Fast Trip</title>
  <link type="application/atom+xml" href="https://d.moonfire.us/tags/fast-trip/atom.xml" rel="self" />
  <link type="text/html" href="https://d.moonfire.us/tags/fast-trip/" rel="alternate" />
  <updated>2026-07-16T17:32:05Z</updated>
  <id>https://d.moonfire.us/tags/fast-trip/</id>
  <author>
    <name>D. Moonfire</name>
  </author>
  <rights>Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</rights>
  <entry>
    <title>generator-mfgames-writing v0.3.2</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2021/07/31/generator-mfgames-writing/" />
    <updated>2021-07-31T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2021/07/31/generator-mfgames-writing/</id>
    <category term="programming" scheme="https://d.moonfire.us/categories/" label="Programming" />
    <category term="asdf" scheme="https://d.moonfire.us/tags/" label="asdf" />
    <category term="generator-mfgames-writing" scheme="https://d.moonfire.us/tags/" label="generator-mfgames-writing" />
    <category term="commitlint-gitlab-ci" scheme="https://d.moonfire.us/tags/" label="commitlint-gitlab-ci" />
    <category term="gitlab" scheme="https://d.moonfire.us/tags/" label="Gitlab" />
    <category term="semantic-release" scheme="https://d.moonfire.us/tags/" label="semantic-release" />
    <category term="conventional-commits" scheme="https://d.moonfire.us/tags/" label="Conventional Commits" />
    <category term="commitlint" scheme="https://d.moonfire.us/tags/" label="commitlint" />
    <category term="husky" scheme="https://d.moonfire.us/tags/" label="Husky" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <summary type="html">Today, I finished putting the final touches on additional features for `generator-mfgames-writing`, my scaffolding generator for Yeoman that lets me set up writing projects quickly.
</summary>
    <content type="html">&lt;p&gt;Related to process of writing from &lt;a href="/blog/2021/07/27/commitlint-gitlab-ci/"&gt;a few days ago&lt;/a&gt;, I've been working on another tool that I find myself using fairly often: &lt;a href="https://yeoman.io/"&gt;Yeoman&lt;/a&gt;. This is a scaffolding tool, which basically means it asks a few questions and then sets up a project. In my case, it does a lot of the drudge work of creating a writing project and getting it ready for &lt;a href="https://gitlab.com/"&gt;Gitlab's CI&lt;/a&gt; which I also use heavily (and why I wrote &lt;code&gt;commitlint-gitlab-ci&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Like many of the writing tools, this is based on Javascript (but not Typescript this time).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;$ sudo npm install -g yo generator-mfgames-writing
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing it does is ask a number of questions about the project. I'll use &lt;a href="https://fedran.com/nor-curse-be-found/"&gt;Nor Curse Be Found&lt;/a&gt;, my Beauty and the Beast sequel, as an example.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;$ mkdir nor-curse-be-found
$ cd nor-curse-be-found
$ yo mfgames-writing
? The title for your novel or story: (Nor Curse Be Found)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All of my writing projects have a unique &amp;ldquo;slug&amp;rdquo; to describe them. This is used for the website's URL, such as &lt;a href="https://fedran.com/nor-curse-be-found"&gt;https://fedran.com/nor-curse-be-found&lt;/a&gt;, and also the name of the output (&lt;code&gt;dmoonfire-nor-curse-be-found-0.0.1.epub&lt;/code&gt;). I use a library to pull out the current directory's name and try to make a reasonable title out of it. I can change the title to something more accurate, maybe with apostrophes or possessives, but generally I keep the slug pretty even. In this case, the parenthetical item is the suggested output, so I can just hit return.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? The title for your novel or story: Nor Curse Be Found
? The slug based on the title: (nor-curse-be-found)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just in case the directory doesn't match the directory, I use a library to take that given title and create a slug out of it. One of the biggest things, my &lt;a href="http://www.sectorgeneral.com/shortstories/fasttrip.html"&gt;Fast Trip&lt;/a&gt; rule, is that I don't want to tell someone how to work. That is why I called this semi-opinionated in that there are a lot of options but the default is how &lt;em&gt;I&lt;/em&gt; work.&lt;/p&gt;
&lt;p&gt;There is also a question about bylines, but then we start to get into the technical bits.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? The title for your novel or story: Nor Curse Be Found
? The slug based on the title: nor-curse-be-found
? Author's name or byline: D. Moonfire
? Do you want to create the Git repository? (Y/n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This came from some years ago, but I do one story per repository, more so if I think the story has a possibility of being a bigger piece (which many of mine are), I want to track the versions independently, or I might be sending to an editor or submitting it somewhere (not likely these days, I self-censor a lot there). Since this is so common, I put it in as part of the questions.&lt;/p&gt;
&lt;p&gt;I have a slowly evolving set of practices when it comes to writing processes. One of the first ones is setting up a Git repository. This always starts with configuring &lt;a href="https://typicode.github.io/husky/#/"&gt;husky&lt;/a&gt;, &lt;a href="https://www.conventionalcommits.org/en/"&gt;semantic-release&lt;/a&gt;, &lt;a href="https://www.conventionalcommits.org/en/"&gt;conventional-commits&lt;/a&gt;, and &lt;a href="https://commitlint.js.org/#/"&gt;commitlint&lt;/a&gt;. (I'm working on updating my &lt;a href="https://www.npmjs.com/package/generator-mfgames-writing"&gt;Yeoman generator&lt;/a&gt; to make this a lot easier, but that will be later this week.)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Do you want to create the Git repository? Yes
? Any command to run after `git init`? set-moonfire-git-user
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also write for a number of different projects (and bylines) which means I don't always use the same Gitlab login or even email. To faciliate this, I do &lt;em&gt;not&lt;/em&gt; have a global &lt;code&gt;user.name&lt;/code&gt; and &lt;code&gt;user.email&lt;/code&gt; set up in Git so it blows up if I try to make a commit without setting a local one. Since that is tedious, I write a bunch of scripts that set the user information and SSH keys (&lt;code&gt;set-moonfire-git-user&lt;/code&gt; for writing, &lt;code&gt;set-mfgames-git-user&lt;/code&gt; for programming for example) and I want to call them before I do that first commit. If I just hit return to have a blank, then nothing extra will happen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Any command to run after `git init`? set-moonfire-git-user
? Do you want to create the initial commit? Yes
? Do you want to create the initial Git tag? Yes
? What version do you want to start? 0.0.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, the initial commit is a messy one and a philosophical difference between me and the Semantic Release folks. They have &lt;a href="https://github.com/semantic-release/semantic-release/blob/caribou/docs/support/FAQ.md#can-i-set-the-initial-release-version-of-my-package-to-001"&gt;their reasons&lt;/a&gt; to hard-code the value to &amp;ldquo;1.0.0&amp;rdquo; but I'm specifically start this process &lt;em&gt;before&lt;/em&gt; a release, so I feel it should be &amp;ldquo;0.0.1&amp;rdquo; because I want that tracking as soon as possible.&lt;/p&gt;
&lt;p&gt;Since I don't have the ability to set it via a configuration file, I get around it by creating the initial commit and then allowing it to be tagged so it can be pushed up and get the starting version I want.&lt;/p&gt;
&lt;p&gt;This is also because I tag versions I give to editors, beta readers, and even my writing group (when I went to it). The tagged version also shows up on the various Fedran pages and mainly it shows progression as I write.&lt;/p&gt;
&lt;p&gt;So, &lt;em&gt;Fast Trip&lt;/em&gt; so I jump through a few hoops. It should also be clear why I needed that command to run after &lt;code&gt;git init&lt;/code&gt; to set my user, otherwise this part would blow up with a &amp;ldquo;user not set&amp;rdquo; message.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? What version do you want to start? 0.0.1
? Which package manager do you use? (Use arrow keys)
❯ NPM
  Yarn
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moving away from Git and into the build process, the first question is package management. I have a love/hate relationships with &lt;code&gt;npm&lt;/code&gt;. The command works great, but I've been struggling with it (more on than off lately) so I've been using &lt;a href="https://yarnpkg.com/"&gt;yarn&lt;/a&gt; fairly heavily in the last year or so. But, with Yeoman I can give both so the user can use up or down keys to select and hit return to choose. Once they do, the menu goes away and is replaced with the choice.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Which package manager do you use? Yarn
? Do you want to use semantic releases? Yes
? Do you want to use conventional commits? Yes
? Do you want to use Husky? Yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next three are to set up the common functionality I use with releases. They set up &lt;a href="https://semantic-release.gitbook.io/semantic-release/"&gt;semantic-release&lt;/a&gt;, &lt;a href="https://www.conventionalcommits.org/en/"&gt;conventional commits&lt;/a&gt;, &lt;a href="https://commitlint.js.org/#/"&gt;commitlint&lt;/a&gt;, and &lt;a href="https://typicode.github.io/husky/#/"&gt;Husky&lt;/a&gt; which I use to make sure all the commit messages are clean. These four program have been a stable in most of my development lately, for coding and writing, for Typescript and even C#.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Do you want to use Husky? Yes
? Do you want to use CI/CD? Yes
? Do you use Gitlab for your CI/CD? Yes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can't say enough for Gitlab's CI. Whenever I push up code to the server, it runs the entire publication process. Assuming it works, it then produces a zip archive with EPUB, MOBI, PDF, and other formats without me doing anything else. Every single time. With sematic releases and the rest, each one has a unique version so I don't have &amp;ldquo;final&amp;rdquo;, &amp;ldquo;final-2&amp;rdquo;, &amp;ldquo;final-2a&amp;rdquo;, etc. Just a clean version number that shows up everywhere, starting at 0.0.1.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Do you use Gitlab for your CI/CD? Yes
? Do you use asdf? No
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is another tool I use, &lt;a href="https://github.com/asdf-vm/asdf"&gt;asdf&lt;/a&gt;. This was also something that pretty much started last year, but one of the goals of &lt;a href="https://gitlab.com/mfgames-writing/mfgames-writing-js/"&gt;mfgames-writing&lt;/a&gt; was to be able to produce consistent output of novels even years later. Well, what I didn't realize is how much the Node ecosystem would change and Node 15 doesn't exactly run Node 8 packages very well due to deprecations and changing libraries.&lt;/p&gt;
&lt;p&gt;This is where &lt;code&gt;asdf&lt;/code&gt; comes in. It puts a small file (&lt;code&gt;.tool-versions&lt;/code&gt;) which says which version of Node, Yarn, C#, Python, whatever and will automatically change to those versions when I &lt;code&gt;cd&lt;/code&gt; into the directory. It basically rolls in all the functionality of &lt;code&gt;nvm&lt;/code&gt;, &lt;code&gt;virtualenv&lt;/code&gt;, and a bunch of other localized version libraries into one. Since I write and work across many languages, having one tool to manage that is easier for me. So, saying &amp;ldquo;yes&amp;rdquo; to the question copies that &lt;code&gt;.tool-versions&lt;/code&gt; into the resulting directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Do you use asdf? Yes
? Which formats do you want to use? (Press &amp;lt;space&amp;gt; to select, &amp;lt;a&amp;gt; to toggle all, &amp;lt;i&amp;gt; to invert selection)
❯◉ PDF
 ◉ EPUB
 ◯ DOCX
 ◯ HTML
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this next question, we are out of the build section and into the formats. Basically, this just queries which types of files will be written out. The directions are pretty clear, but basically this will determine which of the format libraries are included.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? Which formats do you want to use? PDF, EPUB, DOCX, HTML
? The name of the theme package to use: (@mfgames-writing/clean-theme)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I only have three themes right now, two are &amp;ldquo;generic&amp;rdquo; and one I prefer just for Fedran stories (but obviously don't prevent anyone from using it). Later, I hope to have more themes, but basically the choices are &lt;code&gt;@mfgames-writing/clean-theme&lt;/code&gt; and &lt;code&gt;@mfgames-writing/greekil-theme&lt;/code&gt; (a Gentium-based theme).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;? The name of the theme package to use: @mfgames-writing/clean-theme
Creating initial Git repository
Initialized empty Git repository in fedran/nor-curse-be-found/.git/
Running custom Git command


I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.


   create package.json
    force ../../../.yo-rc-global.json
    force .yo-rc.json
   create release.config.js
   create commitlint.config.js
   create .husky/commit-msg
   create .gitlab-ci.yml
   create .tool-versions
   create publication.yaml
   create yarn.lock
   create README.md
   create .gitignore
   create chapters/chapter-01.md

Changes to package.json were detected.

Running yarn install for you to install the required dependencies.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that, it just producing a wall of tell as it creates all the files, hooks up everything, and basically gets my entire project ready, including a sample first chapter, a really basic &lt;code&gt;README.md&lt;/code&gt;, and a Git repository ready to push.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;$ ls -a
.                     .git            node_modules       README.md
..                    .gitignore      package.json       release.config.js
chapters              .gitlab-ci.yml  package-lock.json  .yo-rc.json
commitlint.config.js  .husky          publication.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Right off the bat, I can build the files and see the output.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;$ yarn build:pdf
... lots of output
$ ls *.pdf
nor-curse-be-found-0.0.1.pdf
$ yarn build
... huge amounts of output
$ ls nor-curse-be-found*
nor-curse-be-found-0.0.1.docx  nor-curse-be-found-0.0.1.epub
nor-curse-be-found-0.0.1.html  nor-curse-be-found-0.0.1.pdf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'm also ready to push up to Gitlab.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;$ git remote add origin git@gitlab.com:fedran/nor-curse-be-found.git
$ git push --tags
$ git push -u origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hopping over to Gitlab, I can see it building immediately.&lt;/p&gt;
&lt;p&gt;&lt;img src="./initial-push.png" height="256" style="margin-top:1em;" alt="Initial CI Run" /&gt;&lt;/p&gt;
&lt;p&gt;As soon as it is done, it uploads the output as an artifact.&lt;/p&gt;
&lt;p&gt;&lt;img src="./gitlab-log.png" height="256" style="margin-top:1em;" alt="End of Log" /&gt;&lt;/p&gt;
&lt;p&gt;I can then click on the browse (or download) button on the right.&lt;/p&gt;
&lt;p&gt;&lt;img src="./gitlab-download.png" height="256" style="margin-top:1em;" alt="Browse and Download Buttons" /&gt;&lt;/p&gt;
&lt;p&gt;Browsing lets me see a list of all the outputs that I've added.&lt;/p&gt;
&lt;p&gt;&lt;img src="./gitlab-browse.png" height="256" style="margin-top:1em;" alt="Browse Artifacts" /&gt;&lt;/p&gt;
&lt;p&gt;And I can even click on the PDF to preview it.&lt;/p&gt;
&lt;p&gt;&lt;img src="./gitlab-pdf.png" height="256" style="margin-top:1em;" alt="View PDF" /&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The End After Three Hundred Weeks</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2021/03/17/three-hundred-weeks/" />
    <updated>2021-03-17T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2021/03/17/three-hundred-weeks/</id>
    <category term="writing" scheme="https://d.moonfire.us/categories/" label="Writing" />
    <category term="fedran" scheme="https://d.moonfire.us/tags/" label="Fedran" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <category term="derecho-2020" scheme="https://d.moonfire.us/tags/" label="Derecho 2020" />
    <category term="300-weeks" scheme="https://d.moonfire.us/tags/" label="300 Weeks" />
    <summary type="html">Six years ago, I started posting weekly chapters. As of this week, I have been doing that for three hundred consecutive weeks. It is also time for me to stop.
</summary>
    <content type="html">&lt;p&gt;Just under two years ago, I posted about how I had been posting weekly chapters for &lt;a href="/blog/2019/04/19/two-hundred-weeks/"&gt;two hundred consecutive weeks&lt;/a&gt;. Since then, I've managed to do it for another hundred weeks which puts me up to six years of posting (mostly) consistently. There were two instances where I missed a week but I caught up and returned quickly. Overall, I can say three hundred weeks of posting with a straight face and still feel like I wasn't lying.&lt;/p&gt;
&lt;p&gt;I had a lot of hopes in 2019. Things were looking positive and I was writing strong. I found a new community and they were throwing thumbs up at me. Then 2020 hit and things started to get a little less rosy. I don't need to say what happened, but my household has been in relative isolation since March and then we got hit by the derecho in August. They still haven't finished fixing the roof or repairing the hole in the side of my house before the snow came.&lt;/p&gt;
&lt;p&gt;(Unlike my normal rule of limiting negative posts, this one talks about depression.)&lt;/p&gt;
&lt;h1&gt;Skill and Perceptions&lt;/h1&gt;
&lt;p&gt;Somewhere in September, I started to get a feeling that everything I was writing was &amp;ldquo;wrong&amp;rdquo;. I can't tell how it was wrong, only that I wasn't capable of fixing it because I couldn't tell what I was missing. It didn't take long to realized was in a slump probably related to the skill/perception curve (&lt;a href="https://auriee.tumblr.com/post/139955231381/how-to-improve-understanding-knowledge-skill"&gt;source&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src="./skill-perception.jpg" height="256" style="margin-top:1em;" alt="Skill/Perception Curve" /&gt;&lt;/p&gt;
&lt;p&gt;I'm just left of frowning face, a point where I know something is wrong but my skills and abilities aren't enough to identify the problem. I've had this feeling before, where I know there is something wrong, but I've never had a situation where I had no clue how to improve my writing.&lt;/p&gt;
&lt;p&gt;This discomfort with my writing continued to grow, sapping my creativity.&lt;/p&gt;
&lt;h1&gt;Flight of the Scions&lt;/h1&gt;
&lt;p&gt;In October 2020, I also had &lt;a href="https://fedran.com/flight-of-the-scions/"&gt;Flight of the Scions&lt;/a&gt; edited. When I didn't get the enthusiasm I was hoping for the piece, that pretty much sent me down a spiral and the growing sense that I was missing something turned into a full-blown loathing. I haven't integrated the edits for that novel because of it&amp;hellip; because I feel like I can never do the piece justice.&lt;/p&gt;
&lt;h1&gt;Plague&lt;/h1&gt;
&lt;p&gt;In November, I got sick.&lt;/p&gt;
&lt;h1&gt;End of the Year&lt;/h1&gt;
&lt;p&gt;In mid-December, I still wasn't able to identify what was wrong with my writing. I was writing. I was still passionate about &lt;a href="https://fedran.com/allegro/"&gt;Allegro&lt;/a&gt; but every word that got down on the page felt alien, twisted and foul.&lt;/p&gt;
&lt;p&gt;That was also the point I realized that I can't just push myself past it. There weren't enough words because I just spent months not liking my words but unable to find the epiphany that would help me through the roadblock.&lt;/p&gt;
&lt;h1&gt;NaNoWriMo&lt;/h1&gt;
&lt;p&gt;Something has to change if I want to keep getting better at my writing. I've written a lot, I've grown as a writer and as a person. More importantly, I want to graduate from an &amp;ldquo;okay&amp;rdquo; writer to a &amp;ldquo;good&amp;rdquo; writer. This requires me to figure out what I'm missing.&lt;/p&gt;
&lt;p&gt;While I thought about it, I looked at what writing weekly was giving me. At the beginning, much like &lt;a href="https://en.wikipedia.org/wiki/National_Novel_Writing_Month"&gt;NaNoWriMo&lt;/a&gt;, it was about &amp;ldquo;can I do it&amp;rdquo;. Six years of writing says I can. I also will admit, my writing has significantly improved in the six years of steady writing and I'm a much stronger creator than ever.&lt;/p&gt;
&lt;p&gt;But I don't think I've improved much in the last year. I think I have reached the top of this mesa with my skill by just forcing out more words. I need something more deliberate, which also means less grinding out words and more of trying things to shuffle things up and expand in a new direction.&lt;/p&gt;
&lt;p&gt;I said the same thing about NaNoWriMo. I was able to do it, but the month of writing wasn't really the challenge. For me, it was more about getting the word count, but I already know I can write fifty thousand words in four days. I've done it, more than once. I even published the results of one of those experiences.&lt;/p&gt;
&lt;p&gt;NaNoWriMo came down to word count, which is a metric that I love to use but it also a useless one for me. It slides under the &lt;a href="https://en.wikipedia.org/wiki/Goodhart%27s_law"&gt;Goodhart's Law&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When a measure becomes a target, it ceases to be a good measure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Word counts, including minimum words a day or reaching a certain number, isn't helping me because I just work toward the target. With NaNoWriMo, I find that I can't easily write past 50k words even if the story needs it. A word count in a day becomes a chore.&lt;/p&gt;
&lt;p&gt;Same with writing time.&lt;/p&gt;
&lt;p&gt;Using likes and reviews is also difficult because I'm an okay writer, not a good one. The volume of what I write means folks stop reading it, or they realize I'm not a good writer. I'm not sure without feedback, so I'm going to say they don't work because I can't measure anything.&lt;/p&gt;
&lt;h1&gt;Burnout&lt;/h1&gt;
&lt;p&gt;To be honest, much of this feels like burnout also. I've gone through two major burnouts in my life and I think the weekly chapters are beginning to strip those screws bare again. That just gives more credence to the idea of stopping my weekly chapters.&lt;/p&gt;
&lt;p&gt;Burnout also leads to depression and a feeling of worthlessness that never goes away. That's been hanging around me since I was seventeen but it got really bad since August. Every time I stumbled into the &amp;ldquo;never write out of your lane,&amp;rdquo; I realized I had created a world that would require me to venture out and I shouldn't have. Every time I got a rejection, I knew I wasn't that good of a writer. Every time I tried to convince someone to read my work and they just&amp;hellip; gave up, it just reinforced that.&lt;/p&gt;
&lt;p&gt;So the logical response, to avoid upsetting everyone, was to consider giving up. Not because of a &amp;ldquo;if I can't write that, then I should stop writing&amp;rdquo; but more of a realization that I'm not really that important and there are far better people out there that need the space more than me.&lt;/p&gt;
&lt;p&gt;I've been struggling with this for months. I think one of the reasons I have have only made a single submission in the last four years is because of that. (I was rejected, of course.) There are &amp;ldquo;own voices&amp;rdquo; that need to be said more than what I do. I can't do much beyond boosting others, but not trying to draw attention to myself is one of those. This is something I've been considering for months.&lt;/p&gt;
&lt;p&gt;Because of that, I'm having trouble wanting to draw attention to myself. My weekly chapters were a single post around six in the morning once a week and I consider that excessive. When I finished my last book, it was a second posting in a week and nothing more. I don't know if I can, or want, to go beyond that. I haven't asked for a table at ICON for the same reason. I haven't paid for advertisement either.&lt;/p&gt;
&lt;h1&gt;Mr. Tanner&lt;/h1&gt;
&lt;p&gt;I'm not going to stop writing. I don't think I can stop writing. It brings me so much joy and I love creating stories. I just don't know who I'm writing for anymore. In many ways, the final lyrics of Harry Chaplin's &amp;ldquo;&lt;a href="https://www.youtube.com/watch?v=upZB5VlbC6o"&gt;Mr. Tanner&lt;/a&gt;&amp;rdquo; have been speaking to me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Music was his life, it was not his livelihood&lt;br /&gt;
And it made him feel so happy and it made him feel so good&lt;br /&gt;
And he sang from his heart and he sang from his soul&lt;br /&gt;
He did not know how well he sang; It just made him whole&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Much like James White's &lt;a href="https://www.sectorgeneral.com/shortstories/fasttrip.html"&gt;Fast Trip&lt;/a&gt;, &amp;ldquo;Mr. Tanner&amp;rdquo; has become a sign of the last year or so.&lt;/p&gt;
&lt;h1&gt;What's Next&lt;/h1&gt;
&lt;p&gt;I don't know.&lt;/p&gt;
&lt;p&gt;Right now, I'm focusing on finishing projects and not writing anything new. That includes a side piece, &lt;em&gt;Flight of the Scions&lt;/em&gt; (hopefully for August), and &lt;a href="https://fedran.com/second-hand-dresses/"&gt;Second-Hand Dresses&lt;/a&gt; for November.&lt;/p&gt;
&lt;p&gt;If I do write something new, I want to finish &lt;em&gt;Allegro&lt;/em&gt; because I'm almost near the end. I also had a vague idea of sending it to the inspiration of the novel, but then I made Linsan a demisexual with lesbian tendencies and I probably overstepped my bounds. I will release the chapters for public reading as I go because I started that way and I feel that is a social contract I'm not willing to&lt;/p&gt;
&lt;p&gt;I honestly don't know about new stories or novels. I like the occasional up-vote on various channels. To be honest, very few folks are actually reading it. When they do, it's in a surge and then they wander off. I have two fans on Patron but only one speaks up; I can't thank either of them enough for the encouragement.&lt;/p&gt;
&lt;p&gt;If this is burnout, then I need time to recover. I need adventures and to work on other things.&lt;/p&gt;
&lt;p&gt;There is always a fear that I just started the process of giving up on writing, but I can't honestly tell at this moment. It's possible, but that is life. It changes, it evolves. I've been writing fiction, in some form, for at least forty years. I can't imagine just stopping cold, but then again, I wasn't planning on getting married, having children, and having a hole punched in the side of my house.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Author Intrusion - I've Been Here Before</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2019/04/30/author-intrusion/" />
    <updated>2019-04-30T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2019/04/30/author-intrusion/</id>
    <category term="writing" scheme="https://d.moonfire.us/categories/" label="Writing" />
    <category term="fedran" scheme="https://d.moonfire.us/tags/" label="Fedran" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <summary type="html">When it comes to projects that I probably will never finish, Author Intrusion is probably right up there. Most of the time, it is because I keep restarting because I learned significant lessons. This last week was one of those cases.
</summary>
    <content type="html">&lt;p&gt;When it comes to projects that I probably will never finish, &lt;a href="/tags/author-intrusion/"&gt;Author Intrusion&lt;/a&gt; is probably right up there. Most of the time, it is because I keep restarting because I learned significant lessons. This last week was one of those cases.&lt;/p&gt;
&lt;p&gt;Author Intrusion is also one of those projects that I keep coming back because I &lt;em&gt;know&lt;/em&gt; it can help me but it requires a lot of effort to turn what I think I need into something that is useful. One might say that is obvious from the sheer number of times I restarted development but it is a moving target even from the beginning.&lt;/p&gt;
&lt;p&gt;There are a lot of reasons for the various restarts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can't handle my 25k word penultimate chapter on a project:
&lt;ul&gt;
&lt;li&gt;... in a reasonable time.&lt;/li&gt;
&lt;li&gt;... or with reasonable memory concerns.&lt;/li&gt;
&lt;li&gt;... or without grinding my entire system to a halt.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Can't handle my 600k word epic:
&lt;ul&gt;
&lt;li&gt;... in a reasonable time, overloading my memory, and stopping my machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Couldn't figure out how to determine parts of speech correctly.&lt;/li&gt;
&lt;li&gt;I tried to:
&lt;ul&gt;
&lt;li&gt;... write an entire text editor.&lt;/li&gt;
&lt;li&gt;... okay, just the text control.&lt;/li&gt;
&lt;li&gt;... okay, just load single chapters.&lt;/li&gt;
&lt;li&gt;... okay, just a CLI to parse the files.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is over eight years of struggling with this tool.&lt;/p&gt;
&lt;h1&gt;Expectations&lt;/h1&gt;
&lt;p&gt;Part of the problem is I'm thinking too grandly. I always had that problem when I can't code, silence is probably the worse things for my plots and my projects. I think I've managed to winnow down the list to a more obtainable set of goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work with YAML + Markdown, my preferred format.&lt;/li&gt;
&lt;li&gt;Analyze the chapters of the book at:
&lt;ul&gt;
&lt;li&gt;Identify problem words.&lt;/li&gt;
&lt;li&gt;Identify clustered echo words.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Get me a good count of words for the chapters:
&lt;ul&gt;
&lt;li&gt;... for the entire book.&lt;/li&gt;
&lt;li&gt;... for a range of chapters.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Identify sentences:
&lt;ul&gt;
&lt;li&gt;... that start with the same pattern.&lt;/li&gt;
&lt;li&gt;... have the same number of words.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Identify concurrent paragraphs that start with the same word.&lt;/li&gt;
&lt;li&gt;Identify overuses of gerunds (a category of &lt;code&gt;-ing&lt;/code&gt; words).&lt;/li&gt;
&lt;li&gt;Identify overuses/clusters of &amp;ldquo;to be&amp;rdquo; verbs.&lt;/li&gt;
&lt;li&gt;Allow me to insert a chapter easily.&lt;/li&gt;
&lt;li&gt;Identify present tense outside of dialog.&lt;/li&gt;
&lt;li&gt;Integrate with &lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt; as a language service.&lt;/li&gt;
&lt;li&gt;Work on Windows and Linux.&lt;/li&gt;
&lt;li&gt;Handle custom spelling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay&amp;hellip; that isn't that much of a shorter list. Even so, it will take a while to even get close to it despite these features being 90% of what I use tools to do today.&lt;/p&gt;
&lt;h1&gt;The Last Failure&lt;/h1&gt;
&lt;p&gt;The last version used &lt;a href="https://en.wikipedia.org/wiki/XPath"&gt;XPath&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/XSLT"&gt;XSLT&lt;/a&gt;. I figured it was a good way of framing the ideas, however I started getting bogged down in making it &lt;em&gt;flexible&lt;/em&gt; because I hate the idea of opinionated systems and didn't want to force others to work the way I work (blame James White's &lt;em&gt;Fast Trip&lt;/em&gt; for that).&lt;/p&gt;
&lt;p&gt;Also, it struggled with the large files and projects.&lt;/p&gt;
&lt;p&gt;When I encounter a problem, sometimes it is good to think of it in a different way. This might require retooling it, starting over (I did that with RPG games a lot as a kid too), or trying to come around the problem a different way.&lt;/p&gt;
&lt;h1&gt;Rust Language&lt;/h1&gt;
&lt;p&gt;I decided to spend a week trying another iteration of Author Intrusion. This time, I used it as a learning experience for an entirely different (and new to me) language: &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;. Rust is a pretty low-level language but has much of the packaging and niceties of C# (my primary language). Since I knew the initial versions of Author Intrusion so well (I have restarted over ten times), it was old territory that would make it easier to map the language into something I already knew.&lt;/p&gt;
&lt;p&gt;Overall, Rust is fairly pleasant to use but there are places where I struggled a lot with it conceptually. I've worked in object-oriented languages for the last twenty years, Rust has some OO-like support but I had to change how I was working to use it. Also I still haven't groked the &amp;ldquo;borrow&amp;rdquo; concepts enough, so sometimes I just revert to randomly adding and removing &lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt; in hopes of figuring it out.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In other words, I beat on it like a black obelisk.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The tooling with Rust is considerably poorer than C#. Not being able to refactor easily definitely ate up significant time in the last week. Also my laptop hates working with Rust, it gets burning hot after only an hour of coding&amp;hellip; which was good because I put it down until everything cooled off.&lt;/p&gt;
&lt;p&gt;That said, I've been pretty happy with the results so far so I'm hoping to keep it going with this variant instead of the previous ones, at least to see if I can get closer to my end goals.&lt;/p&gt;
&lt;h1&gt;Running the Tool&lt;/h1&gt;
&lt;p&gt;So, if you are interested in checking it out with this post, head over the the &lt;a href="https://gitlab.com/author-intrusion/author-intrusion-rust"&gt;GitLab repository&lt;/a&gt; and clone it. I'm using &lt;code&gt;rustup&lt;/code&gt; for my installation with the nightly builds, so the following should work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ git clone https://gitlab.com/author-intrusion/author-intrusion-rust
$ cd author-intrusion-rust
$ ./run-000 chapter list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On Linux, I create an alias to run it from anywhere:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ alias author-intrusion=&amp;quot;cargo run --quiet --&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unless noted, I'll also run all of these examples from the &lt;code&gt;./examples/000-simple-project&lt;/code&gt; directory.&lt;/p&gt;
&lt;h1&gt;Project Files&lt;/h1&gt;
&lt;p&gt;Like before, everything hangs off a &lt;code&gt;author-intrusion.aipry&lt;/code&gt; project file. This tells the system where the root of the project is located (I love being able to use &lt;code&gt;npm&lt;/code&gt; and &lt;code&gt;gulp&lt;/code&gt; from sub-directories) and how the project is organized.&lt;/p&gt;
&lt;p&gt;The project file is a YAML file. There are two examples in the &lt;code&gt;./examples/&lt;/code&gt; folder in the source code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: First Example Project
content:
  pattern: chapters/chapter-??.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;name&lt;/code&gt; is just there because I like to have something.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;content&lt;/code&gt; chapter says how the project is organized for the actual content. Now, in my case, I almost universally use &lt;code&gt;chapter&lt;/code&gt; for my files but I've been switching from &lt;code&gt;chapter-01.markdown&lt;/code&gt; to &lt;code&gt;chapter-01.md&lt;/code&gt;. Someone might prefer a different approach (like the &lt;code&gt;src&lt;/code&gt; directory or eventually a chapter/scene approach).&lt;/p&gt;
&lt;h1&gt;File List&lt;/h1&gt;
&lt;p&gt;With that, we have the basic ability to list chapters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion chapter list
chapters/chapter-01.md 1 Chapter One  9
chapters/chapter-02.md 2 Chapter Two 11
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This shows off some of the cool things it can do already. The first column is the relative path in project. This is the same as adding &lt;code&gt;-f file.rel_path&lt;/code&gt; to the command.&lt;/p&gt;
&lt;p&gt;The second column is the chapter number which is parsed from the file (&lt;code&gt;chapter-01.md&lt;/code&gt; -&amp;gt; &lt;code&gt;01&lt;/code&gt; -&amp;gt; &lt;code&gt;1&lt;/code&gt;). This is the same as &lt;code&gt;-f file.num&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The third is pulled from the file itself in the front matter (the section between the &lt;code&gt;---&lt;/code&gt; lines). This uses &lt;a href="http://jmespath.org/"&gt;JMESPath&lt;/a&gt; for the queries that lets you do some really tool things. In this case, it is just a simple &lt;code&gt;-f title&lt;/code&gt; which pulls the &lt;code&gt;title:&lt;/code&gt; line from the files.&lt;/p&gt;
&lt;p&gt;Finally, the last column is the number of words inside the file or &lt;code&gt;-f count.words&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The reason I have these individual fields is because maybe I only want the word count in each chapter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion chapter list -f count.words
 9
11
$
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Using JMESPath&lt;/h1&gt;
&lt;p&gt;The JMESPath also lets me pull out more detailed information from the query. As I've shown in &lt;a href="https://gitlab.com/fedran/sand-and-blood/blob/master/chapters/chapter-01.markdown"&gt;sample chapters&lt;/a&gt;, I put a lot of information in the front matter to help me keep track of the book.&lt;/p&gt;
&lt;p&gt;A simple case is chapter 1 of the example file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Chapter One
locations:
  - Location A
  - Location B
---

This is chapter 1 for Anton.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, if I want to pull out the locations with the tool as a comma separated list, I can do the following.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion chapter list -f file.rel_path -f &amp;quot;locations[] | sort(@) | join(', ', @)&amp;quot;
chapters/chapter-01.md Location A, Location B
chapters/chapter-02.md
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks more impressive with the second example, which is the first nineteen chapters of &lt;a href="https://fedran.com/sand-and-blood/"&gt;Sand and Blood&lt;/a&gt;. I can use that to list all the characters who are present in each chapter besides the main character:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion chapter list -f file.rel_path -f &amp;quot;characters.secondary[] | sort(@) | join(', ', @)&amp;quot; | head -n 3
chapters/chapter-01.markdown Hyonèku
chapters/chapter-02.markdown Gemènyo, Somiryòki, Tejíko
chapters/chapter-03.markdown Desòchu, Gemènyo, Hyonèku, Mapábyo, Opōgyo, Panédo
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is also Unicode-friendly, which is important to me since I'm fond of constructed languages and have a number of them for my world.&lt;/p&gt;
&lt;h2&gt;Defining Field Aliases&lt;/h2&gt;
&lt;p&gt;Now, that can get really wordy, so I added the ability to save those fields in the project file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Sand and Blood by D. Moonfire
content:
  pattern: chapters/chapter-??.markdown
query:
  fields:
    characters.secondary:
      jmes: characters.secondary[] | sort(@) | join(', ', @)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That way, they can be easily used as an aliased field:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion chapter list -f file.rel_path -f characters.secondary
chapters/chapter-01.markdown Hyonèku
chapters/chapter-02.markdown Gemènyo, Somiryòki, Tejíko
chapters/chapter-03.markdown Desòchu, Gemènyo, Hyonèku, Mapábyo, Opōgyo, Panédo
$
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Analysis&lt;/h1&gt;
&lt;p&gt;The other part I managed to get done this week is the basic version of checking. Using &lt;em&gt;Sand and Blood&lt;/em&gt; as an example, I have a problem with an overuse of &amp;ldquo;sigh&amp;rdquo; and &amp;ldquo;sighed&amp;rdquo;. I can use the tool to highlight when I start to use it too much.&lt;/p&gt;
&lt;p&gt;To do that, I first define a check in the project file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Sand and Blood by D. Moonfire
content:
  pattern: chapters/chapter-??.markdown
checks:
  - overused_pattern:
      # The `(?i)` makes this case insensitive.
      pattern: &amp;quot;^(?i)(sigh|sighed)$&amp;quot;
      err: 0.002
      warn: 0.001
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;err&lt;/code&gt; and &lt;code&gt;warn&lt;/code&gt; are ratios in the file. So, &lt;code&gt;0.002&lt;/code&gt; means if more than 0.2% of the chapter is sighing, then just flag them as errors.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ author-intrusion check
chapters/chapter-01.markdown:100:17: warning: found overused word &amp;quot;sighed&amp;quot;
chapters/chapter-01.markdown:140:11: warning: found overused word &amp;quot;sighed&amp;quot;
chapters/chapter-02.markdown:92:230: warning: found overused word &amp;quot;sighed&amp;quot;
chapters/chapter-02.markdown:120:48: warning: found overused word &amp;quot;sigh&amp;quot;
chapters/chapter-02.markdown:214:8: warning: found overused word &amp;quot;sigh&amp;quot;
$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The message is formatted so most tools like Atom or Emacs will move you the line and first character of the word being reported. And they can highlight the lines as yellow or red depending on the &lt;code&gt;warning&lt;/code&gt; or &lt;code&gt;error&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Additional Problems&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;sighing&amp;rdquo; problem was also mirrored by a &amp;ldquo;nodding&amp;rdquo; one. So, once I identify that word as a problem, I can add it to the file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;checks:
  - overused_pattern:
      # The `(?i)` makes this case insensitive.
      pattern: &amp;quot;^(?i)(sigh|sighed)$&amp;quot;
      err: 0.002
      warn: 0.001
  - overused_pattern:
      pattern: &amp;quot;^(?i)(nod|nodded)$&amp;quot;
      err: 0.002
      warn: 0.001
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then it highlights each one as either a warning (under 0.2%) or error (0.2% or higher).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Side note, I'm probably going to rename it to &lt;code&gt;overused_word&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;Speed&lt;/h1&gt;
&lt;p&gt;The biggest test is how fast this thing is. I don't have a lot done, but I had it process almost three million words in all the chapters I've written in the last twenty years in about twelve seconds. Doing actual English checking (overused words, patterns) will take longer, but twelve seconds is a promising start.&lt;/p&gt;
&lt;p&gt;Obviously, it will get slower once I put the various checks in, but this is better than the previous iteration at an hour to handle two million words.&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;So that is how much I got going in a week with a language I just started learning a week ago Saturday. I'm pretty happy with the results and in the process, I found a lot of places that I was over-engineering the code. While I don't know if I'll ever be &amp;ldquo;done&amp;rdquo; with this, I think this is currently my best viable approach and it already has something I can use for this coming week when I work on &lt;a href="https://fedran.com/raging-alone/"&gt;Raging Alone&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Author Intrusion v0.9.0</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2018/06/26/author-intrusion-0.9.0/" />
    <updated>2018-06-26T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2018/06/26/author-intrusion-0.9.0/</id>
    <category term="programming" scheme="https://d.moonfire.us/categories/" label="Programming" />
    <category term="author-intrusion" scheme="https://d.moonfire.us/tags/" label="Author Intrusion" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <category term="project-layout" scheme="https://d.moonfire.us/tags/" label="Project Layout" />
    <summary type="html">After a few weeks of work, the current rewrite of Author Intrusion got to a stopping point. This has the minimum functionality to detect echo works but it has a long way to go.
</summary>
    <content type="html">&lt;p&gt;After a few weeks of work, the current rewrite of Author Intrusion got to a stopping point. This has the &lt;strong&gt;barest&lt;/strong&gt; minimum functionality to detect echo words but it has a &lt;strong&gt;long&lt;/strong&gt; way to go. Depressingly long way, but I need to let it settle a little before I jump back into it.&lt;/p&gt;
&lt;p&gt;I also want a little encouragement so I'm going to toot my own horn and show some progress.&lt;/p&gt;
&lt;h1&gt;Starting Over Again&lt;/h1&gt;
&lt;p&gt;I think this is the ninth attempt I've had to write &lt;span class="missing-link" data-path="/tags/author-intrusion"&gt;Author Intrusion&lt;/span&gt;. Each time, I've encountered various walls where my ideas didn't have the performance or couldn't conceptually move beyond the proof of concept. Over the last eight years, I've learned a lot about writing this and each time I hope &amp;ldquo;this is it&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The current goal is to write a command-line interface (CLI) inspired by compilers (like GCC and TypeScript &lt;code&gt;tsc&lt;/code&gt;) and Git. Basically, have AI have a core set of function but don't worry about re-implementing a text editor (which was, in all honesty, one of my more common mistakes for previous versions).&lt;/p&gt;
&lt;p&gt;I spent a &lt;em&gt;lot&lt;/em&gt; of time trying to get a solid, cross-platform GUI for this. That includes various Gtk# and Electron implementations before I decided to switch to CLIs.&lt;/p&gt;
&lt;p&gt;For reference, this is some of my efforts five years ago:&lt;/p&gt;
&lt;img class="img-responsive post-img-link" src="/assets/2011/03/editor-screenshot.png" alt="Author Intrusion v0.1.0" /&gt;
&lt;img class="img-responsive post-img-link" src="/assets/2013/10/author-intrusion-0.4.0.png" alt="Author Intrusion v0.4.0" /&gt;
&lt;img class="img-responsive post-img-link" src="/assets/2013/11/author-intrusion-0.5.0-3.png" alt="Author Intrusion v0.5.0" /&gt;
&lt;p&gt;The &amp;ldquo;mmm&amp;rdquo; was a search and replace on one of my larger commissions to test performance. In this case, it was a 100k commissioned novel.&lt;/p&gt;
&lt;p&gt;There were a lot of attempts in there and I spent a lot of time trying to create an editor. While I was &amp;ldquo;fairly&amp;rdquo; successful, I think it made the project too big for one person to do. Each major iteration, I've been removing features trying to get to a core functionality while still honoring my core goals of helping me write.&lt;/p&gt;
&lt;h1&gt;Current Implementation&lt;/h1&gt;
&lt;p&gt;After the attempt to write it in Typescript, I decided this version is going to use .NET Core. The folks at Microsoft have done an amazing job of writing something that is fast and capable while running on both Windows and Linux (one of my requirements). It also is my core language, so I'm not struggling with learning and the tools like I was with Typescript. My primary environment is Visual Studio 2017 with &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt;, &lt;a href="http://www.jetbrains.com/rider/"&gt;Rider&lt;/a&gt;, or &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt;. While I use &lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;, global configuration options pretty much means my Atom setup is specifically for writing, not coding.&lt;/p&gt;
&lt;h1&gt;NuGet&lt;/h1&gt;
&lt;p&gt;However, after the Typescript implementation and later code, I realize that the approach &lt;code&gt;npm&lt;/code&gt; uses to manage packages is perfect for what I'm looking for. My struggles with various incarnations of &lt;a href="https://gitlab.com/mfgames-writing"&gt;MfGames Writing&lt;/a&gt; showed me that bitrot is a major problem while writing over years. The earlier incarnations of the build framework would evolve to handle new novels but then it would break older generation in the process. With &lt;code&gt;npm&lt;/code&gt;, I can have a specific version in one project, then the library could continue to evolve while still providing the ability to stay at an older version for those older works.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nuget.org/"&gt;NuGet&lt;/a&gt; has a number of C# libraries for writing a client that would give me the same thing. Various utilities, analyzers, and libraries can be packaged up as NuGet packages and then installed. If they evolve, the older version can remain behind and still work.&lt;/p&gt;
&lt;p&gt;This version has the basics of this in, I can install packages and have various functionality available for processing.&lt;/p&gt;
&lt;img class="img-responsive post-img-link" src="ai-plugins.gif" alt="4 screenshots of adding plugins to author intrusion" /&gt;
&lt;p&gt;This part is actually one of the neatest parts, I think. I'm using &lt;a href="https://autofac.org/"&gt;Autofac&lt;/a&gt;, a bit of reflection, and the NuGet libraries to install packages and then load assemblies from those packages without needing to pull them into a central location.&lt;/p&gt;
&lt;p&gt;As soon as the plugins load, the system rebuilds the plugins and injects functions. This can be various plugins, new XSLT functions, or anything else.&lt;/p&gt;
&lt;h1&gt;Layout Plugins&lt;/h1&gt;
&lt;p&gt;The above screenshot is an example of the layout plugin. It tags files in the project as to their purpose. I made a mistake earlier on this when I started doing grammar checking on notes. In this case, a plugin can indicate something as &amp;ldquo;content&amp;rdquo; (e.g., the novel or story) or &amp;ldquo;lookup&amp;rdquo; (notes) or something else.&lt;/p&gt;
&lt;p&gt;Right now, I'm only implementing my &amp;ldquo;standard&amp;rdquo; project layout that I've used for the last few projects. Eventually I'll write more but I'm trying to get end-to-end before fleshing out ideas as needed.&lt;/p&gt;
&lt;p&gt;A layout plugin is responsible for gathering metadata about a file so decisions can be made. Eventually this will go into the YAML header for the file. This means I'll be able to identify files that have a specific point of view with something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Chapter 1
pov: Dylan
swain: scene
---

It was a bright and depressingly sunny day....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The idea for this is to be able to list all chapters of a given POV and then arrange them chronologically while listing the location. Or tag a file as being a &lt;a href="https://en.wikipedia.org/wiki/Scene_and_sequel"&gt;scene or sequel&lt;/a&gt; so they are interspersed correctly.&lt;/p&gt;
&lt;h1&gt;Structure Plugins&lt;/h1&gt;
&lt;p&gt;A structure plugin basically figures out the structure of a file, such as figuring out if it is broken into paragraphs, sentences, and words. I didn't want to hard-code this because sentence splitting is hard and expensive plus my &lt;a href="https://fedran.com/sand-and-blood/chapter-01/"&gt;fantasy novels&lt;/a&gt; all have epigraphs. Those who like Scrivner may want to arrange it into scenes.&lt;/p&gt;
&lt;p&gt;Structure plugins are boring but critical.&lt;/p&gt;
&lt;h1&gt;Xpath&lt;/h1&gt;
&lt;p&gt;An important part of the structure is &lt;em&gt;not&lt;/em&gt; applying a structure to certain files. Lookup files don't need to know the individual words or paragraphs. To limit it, I'm using a &lt;code&gt;scope&lt;/code&gt; variable which is an Xpath into the project.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;project&amp;gt;
  &amp;lt;file path=&amp;quot;/chapters/chapter-01.md&amp;quot; class=&amp;quot;content&amp;quot; /&amp;gt;
  &amp;lt;file path=&amp;quot;/characters/dylan.md&amp;quot; class=&amp;quot;lookup&amp;quot; /&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means, using a path of &lt;code&gt;/content[is-content()]&lt;/code&gt; will select only the content files but not the lookup. Originally, I implemented this as a CSS-like library which I eventually realized I was going down a rabbit hole (I still broke apart the library for later if I need it).&lt;/p&gt;
&lt;p&gt;Again, C# has the ability to have defined XSLT functions so I wrote &lt;code&gt;is-content()&lt;/code&gt; (injected via Autofac) that does custom logic.&lt;/p&gt;
&lt;p&gt;As the various structure plugins operate (defined by the &lt;code&gt;author-intrusion.aipy&lt;/code&gt; file), it will extend the XML structure used for selections.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;project&amp;gt;
  &amp;lt;file path=&amp;quot;/chapters/chapter-01.md&amp;quot; class=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;para start=&amp;quot;0&amp;quot; length=&amp;quot;10&amp;quot; /&amp;gt;
    &amp;lt;para start=&amp;quot;11&amp;quot; length=&amp;quot;21&amp;quot; /&amp;gt;
  &amp;lt;/file&amp;gt;
  &amp;lt;file path=&amp;quot;/characters/dylan.md&amp;quot; class=&amp;quot;lookup&amp;quot; /&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;project&amp;gt;
  &amp;lt;file path=&amp;quot;/chapters/chapter-01.md&amp;quot; class=&amp;quot;content&amp;quot;&amp;gt;
    &amp;lt;para start=&amp;quot;0&amp;quot; length=&amp;quot;10&amp;quot;&amp;gt;
      &amp;lt;token start=&amp;quot;0&amp;quot; length=&amp;quot;3&amp;quot; /&amp;gt;
      &amp;lt;token start=&amp;quot;5&amp;quot; length=&amp;quot;4&amp;quot; /&amp;gt;
      &amp;lt;token start=&amp;quot;9&amp;quot; length=&amp;quot;1&amp;quot; /&amp;gt;
    &amp;lt;/para&amp;gt;
    &amp;lt;para start=&amp;quot;11&amp;quot; length=&amp;quot;21&amp;quot;&amp;gt;
      &amp;lt;token start=&amp;quot;11&amp;quot; length=&amp;quot;3&amp;quot; /&amp;gt;
      &amp;lt;token start=&amp;quot;16&amp;quot; length=&amp;quot;4&amp;quot; /&amp;gt;
      &amp;lt;token start=&amp;quot;20&amp;quot; length=&amp;quot;1&amp;quot; /&amp;gt;
    &amp;lt;/para&amp;gt;
  &amp;lt;/file&amp;gt;
  &amp;lt;file path=&amp;quot;/characters/dylan.md&amp;quot; class=&amp;quot;lookup&amp;quot; /&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is because of another previous mistake (yeah, I made a lot). Various implementations tried to normalize contents while writing. This meant it would correct double spaces after periods or adjust the text.&lt;/p&gt;
&lt;p&gt;That didn't work.&lt;/p&gt;
&lt;p&gt;I also couldn't break it down into a simple tree structure because English didn't fit well. So, this XML just goes into the original file to get the text.&lt;/p&gt;
&lt;h1&gt;Analysis Plugins&lt;/h1&gt;
&lt;p&gt;The entire reason to break apart a document into a structure is for the analysis. An analysis plugin, such as echo detection, uses the XML structure to gather information.&lt;/p&gt;
&lt;p&gt;All plugins are configured in the &lt;code&gt;author-intrusion.aipy&lt;/code&gt; (project file in YAML format).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;plugins:
  analysis:
  - plugin: EchoDetection
    key: echoes

    scope: content
    select: //token[length() &amp;gt; 3]

    compare: text()

    within: 20
    warning: 2
    error: 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;plugin&lt;/code&gt; attribute is the class to use the plugin. The key is just a label for Atom's linter in case someone uses multiple echo detections in a file.&lt;/p&gt;
&lt;p&gt;The second section is to figure out what is being detected. The &lt;code&gt;scope&lt;/code&gt; uses &lt;code&gt;content&lt;/code&gt; which is a shorthand for &lt;code&gt;/file[is-content()]&lt;/code&gt; or &lt;code&gt;/file[has-class(&amp;quot;content&amp;quot;)]&lt;/code&gt;. This breaks apart the search process. Using &lt;code&gt;/&lt;/code&gt; for the path would do echo detection across chapters (and require more memory and would be slower) while the file-level ones makes it more efficient by only comparing a single file against itself.&lt;/p&gt;
&lt;p&gt;For every scope, the &lt;code&gt;select&lt;/code&gt; figures out what is going to be compared. In this example, for every file, we select every word over three characters long (&lt;code&gt;//token[length() &amp;gt; 3]&lt;/code&gt;). If we had three chapters of a thousand words each, this is a different of a single list of three thousand items (&lt;code&gt;scope: /&lt;/code&gt;) verses three lists of a thousand each (&lt;code&gt;scope: //file[is-content()]&lt;/code&gt;), or three hundred paragraphs of ten words each (&lt;code&gt;scope: //file[is-content()]/para&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The third section is the &lt;code&gt;compare&lt;/code&gt;. This basically figures out what to compare. The &lt;code&gt;text()&lt;/code&gt; means the raw text of the file. However, functions to handle case-insensitivity, stemming (base words so &lt;code&gt;I jumped over the jumper&lt;/code&gt; would have two echoes), Soundex (to find similar-sounding words near each other), or whatever else I need.&lt;/p&gt;
&lt;p&gt;Finally, the echo detection has the rules for what is a detection. It basically counts how many identically entries (as determined by &lt;code&gt;compare&lt;/code&gt;) in each &lt;code&gt;select&lt;/code&gt;ed tag inside the &lt;code&gt;scope&lt;/code&gt; within &lt;code&gt;within&lt;/code&gt; entries. If that number is equal to or greater than &lt;code&gt;error&lt;/code&gt;, then it marks that &lt;code&gt;select&lt;/code&gt;ed element as an error.&lt;/p&gt;
&lt;p&gt;In the above example, the echo detection says &amp;ldquo;for every word in a file, look at the twenty surrounding words. If there are five or more, it's an error, otherwise if there is two more then it's a warning&amp;rdquo;.&lt;/p&gt;
&lt;img class="img-responsive post-img-link" src="ai-analyze.png" alt="Author Intrusion v0.9.0 analyze example" /&gt;
&lt;h1&gt;Functionality&lt;/h1&gt;
&lt;p&gt;This isn't even remotely polished at this point. The project is self contained in that building it will generate the correct data, it just isn't&amp;hellip; pretty.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dotnet run -v:q --no-build --no-restore --project src/AuthorIntrusion.Cli -- file-list -p &amp;quot;Examples/Sand and Blood&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eventually, it should be something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;aicli file lists
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is also a lot of missing functionality, using it probably requires me to understand, though I'd like to think it is pretty simple. Then again, I wrote it, of course it's simple.&lt;/p&gt;
&lt;h1&gt;Complexity&lt;/h1&gt;
&lt;p&gt;You may have noticed that the &lt;code&gt;author-intrusion.aipy&lt;/code&gt; file is somewhat complicated. This is actually intentional. There are a lot of tools for writers. I'm looking for something very specifically to help with flaws I'm aware of in my fiction, not a generic &amp;ldquo;one size fits all&amp;rdquo; application. Because of that, I need it to work for me instead of trying to inflict&lt;/p&gt;
&lt;p&gt;This desire to customize to the author is purely inspired by James White's &lt;a href="http://www.sectorgeneral.com/shortstories/fasttrip.html"&gt;Fast Trip&lt;/a&gt;. If you have a chance, consider reading it. It talks about modifying the environment the way you need to work, not the other way around.&lt;/p&gt;
&lt;p&gt;However, flexibility comes at a price: simplicity. I considered trying to make it easy, but I'm looking for something that looks for overuse of adverbs (technically correct) or gerunds. I want to be able to make sure a character only speaks in past tense or doesn't use a pronoun to identify themselves. One of the earlier ones I'm going to get done is looking for present tense outside of a quote. These are pie in the sky items, but I think possible.&lt;/p&gt;
&lt;p&gt;Later, if this gains traction (e.g., users besides me), someone may come up with a fancy GUI or configuration wizard to add common settings.&lt;/p&gt;
&lt;h1&gt;Development&lt;/h1&gt;
&lt;p&gt;Author Intrusion is currently being managed via its &lt;a href="https://gitlab.com/author-intrusion/author-intrusion-cil"&gt;Gitlab project&lt;/a&gt;. I'm not sure if it would be worthwhile for anyone to consider joining, but if you want to watch it, this would be the place.&lt;/p&gt;
&lt;p&gt;If you have questions, please don't hesitate to poke me on any &lt;a href="/contact/"&gt;social network I'm on&lt;/a&gt;. I always love to bounce ideas or talk about future place. The more I do, the more I can make it useful for everyone, not just myself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Giveaways, Patrons, Sorrow Rides a Fast Horse, and Sand and Bone 32</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2017/05/23/sand-and-bone-32/" />
    <updated>2017-05-23T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2017/05/23/sand-and-bone-32/</id>
    <category term="writing" scheme="https://d.moonfire.us/categories/" label="Writing" />
    <category term="fedran" scheme="https://d.moonfire.us/tags/" label="Fedran" />
    <category term="sand-and-bone" scheme="https://d.moonfire.us/tags/" label="Sand and Bone" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <summary type="html">A busy week as I reach the end of [Sand and Bone](https://fedran.com/sand-and-bone/) being serialzied on my website. There are giveaway, decisions, and a call for patrons. Not to mention a short chapter of Rutejìmo night time run.</summary>
    <content type="html">&lt;p&gt;A busy week as I reach the end of &lt;a href="https://fedran.com/sand-and-bone/"&gt;Sand and Bone&lt;/a&gt; being serialzied on my website. There are giveaway, decisions, and a call for patrons. Not to mention a short chapter of Rutejìmo night time run.&lt;/p&gt;
&lt;h1&gt;Goodreads and Second Run Reviews&lt;/h1&gt;
&lt;p&gt;I've started up a &lt;a href="https://www.goodreads.com/giveaway/show/238343-sand-and-bone"&gt;Goodreads&lt;/a&gt; giveaway for &lt;em&gt;Sand and Bone&lt;/em&gt;. There is also one on &lt;a href="http://www.secondrunreviews.com/2017/05/book-release-d-moonfire-sand-blood.html"&gt;Second Run Reviews&lt;/a&gt; for my spotlight there last week.&lt;/p&gt;
&lt;h1&gt;Patrons and Future Decisions&lt;/h1&gt;
&lt;p&gt;I'm at a crux in a few short weeks. I have two novels that are &amp;ldquo;almost&amp;rdquo; done and one of them is going to be the one that I'm going to be serializing after this one. This is one of the few benefits of being a patron, the ability to vote on my next project so here is the choice:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://fedran.com/flight-of-the-scions/"&gt;Flight of the Scions&lt;/a&gt;: A YA start for a four-book series about Kaneko, a young girl without any magic who is trying to prove herself to her earth knight father who dismisses her after he learns that she will never follow in his footsteps. During this time, a mercenary group attempts to kidnap her and only her ingenuity and creativity, along with her new friends, can save her from becoming a pawn. This has an adorable dog girl with elemental magic and a telepathic boy with raw information in his mind. It also has an eighty foot telepathic toad and the mercenaries' air ship. The end of this series dovetails into Sand and Bone. The above link has the first two chapters as sample.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://fedran.com/second-hand-dresses/"&gt;Second-Hand Dresses&lt;/a&gt;: A Regency-inspired high fantasy romance about a young woman who lost her chance at marriage after her debutante ball was interrupted by a duel going wrong. Nine years later, she is on the cusp of becoming a spinster when both men enter her life and throw it into chaos once again. This is a polyamorous and bisexual piece that is naughtier than my usual fare. This will be a stand-alone novel set in the same universe. The link has three sample chapters.&lt;/p&gt;
&lt;p&gt;The poll is both at the &lt;a href="https://www.patreon.com/posts/sand-and-bone-is-11286285"&gt;Patreon&lt;/a&gt; site and &lt;a href="http://discuss.moonfire.us/t/sand-and-bone-is-coming-to-an-end/2281/1"&gt;my forum&lt;/a&gt;. As a reminder, patrons (even the $1/month) can read all my novels including the WIP of the two above.&lt;/p&gt;
&lt;h1&gt;Sorrow Rides A Fast Horse&lt;/h1&gt;
&lt;p&gt;I've talked about Fast Trip by James White as one of the major stories that has influenced my life. This chapter is inspired by another one, Sorrow Rides a Fast Horse by Dorothy Gilman Butters. I remember reading this story in the Writing Workshop at Prospect High School back when I was a junior. For some reason, the events in the story really resonated by me.&lt;/p&gt;
&lt;p&gt;It is a shorter story, one that doesn't have action, but the looming despair of &amp;ldquo;Sorrow&amp;rdquo; chasing after the mother was a beautiful imagery. If I get around to it, you'll see that Sorrow is a horseman in one of potential future stories. It is the same images I saw all those years ago.&lt;/p&gt;
&lt;p&gt;How does this relate to the story? Well, death is riding after our protagonist and he knows it.&lt;/p&gt;
&lt;h1&gt;Sand and Bone 32: Limits&lt;/h1&gt;
&lt;p&gt;With poison flowing through his veins and death chasing after him, Rutejìmo is desperate to make it home before darkness when he loses all power. As the slowest of the runners, he knows he won't make it but he can't stop, not even for the night.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Read the chapter at &lt;a href="https://fedran.com/sand-and-bone/chapter-32/"&gt;https://fedran.com/sand-and-bone/chapter-32/&lt;/a&gt;. If you like it, please become a &lt;a href="https://fedran.com/patrons/"&gt;patron&lt;/a&gt; or review one of my previous books. Subscribers get access to all my novels, including the first book of my &lt;a href="https://fedran.com/flight-of-the-scions/"&gt;next series&lt;/a&gt; and my &lt;a href="https://fedran.com/second-hand-dresses/"&gt;high-society romance novel&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Author Intrusion status for May 1, 2017</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2017/05/01/author-intrusion/" />
    <updated>2017-05-01T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2017/05/01/author-intrusion/</id>
    <category term="programming" scheme="https://d.moonfire.us/categories/" label="Programming" />
    <category term="author-intrusion" scheme="https://d.moonfire.us/tags/" label="Author Intrusion" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <summary type="html">After a rough start of the previous week, I got a chance to really focus on [Author Intrusion](/tags/author-intrusion/) (AI). Despite the rather significant amount of check-ins and coding, I wasn't quite able to get to a really good "show off" point. Instead, this week ended up being a [black triangle](http://rampantgames.com/blog/?p=7745) (significant progress but nothing visible).</summary>
    <content type="html">&lt;p&gt;After a rough start of the previous week, I got a chance to really focus on &lt;a href="/tags/author-intrusion/"&gt;Author Intrusion&lt;/a&gt; (AI). Despite the rather significant amount of check-ins and coding, I wasn't quite able to get to a really good &amp;ldquo;show off&amp;rdquo; point. Instead, this week ended up being a &lt;a href="http://rampantgames.com/blog/?p=7745"&gt;black triangle&lt;/a&gt; (significant progress but nothing visible).&lt;/p&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I haven't really talked about AI for a while. The entire idea started in 2009 or so when I realized I had some major blindspots in my writing. At the time, it was an overuse of gerunds that was hanging over me but as my skill improves, the problems areas also shift around. My &lt;a href="http://noblepencr.org/"&gt;writing group&lt;/a&gt; has been a great help in tracking these down but I felt a lot of them were things that could be detected ahead of time; basically something that would let me file off the rough edges before someone spent the effort to correct them.&lt;/p&gt;
&lt;p&gt;To my surprise, the current offering of grammar checkers doesn't actually look for the same thing. They seem to review things sentence-by-sentence but I wanted something that looked at the entire document and looked for trouble areas. For example, using the same word repeatedly in a few paragraphs (echo words).&lt;/p&gt;
&lt;p&gt;At the same time, I'm a programmer. I use a wonderful program called &lt;a href="https://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; which has a lot of refactoring and analysis. There are times when I wanted to see every time a character shows up (name outside of dialog) or is talked about. I also rename characters (frequently) and suffer from the occasional search-and-replace bugs.&lt;/p&gt;
&lt;p&gt;That all lead to me want to create an IDE for writers, basically a Visual Studio and ReSharper that was geared toward authors.&lt;/p&gt;
&lt;p&gt;One of my major influences is a short story by James White called &lt;a href="http://www.sectorgeneral.com/shortstories/fasttrip.html"&gt;Fast Trip&lt;/a&gt;. I love that story because it comes down to &amp;ldquo;change the environment to succeed.&amp;rdquo; Well, that meant a couple of things for AI, it had to be flexible to work the way the &lt;em&gt;author&lt;/em&gt; wants and it needed to use the paradigm that I was comfortable with.&lt;/p&gt;
&lt;h1&gt;Iterations&lt;/h1&gt;
&lt;p&gt;I've worked on off-and-on for about eight years. I've tried a lot of iterations, gotten to a point, and then hit some conceptal problem that threw everything into disarray. Some of them were understandings on my part (you can't reformat text while writing), getting caught working on the wrong thing (I should reinvent the word processor), and a ton of other dead ends.&lt;/p&gt;
&lt;p&gt;This means that it isn't done until it is stable. So if you are not interested in alpha software, this might not be what you are looking for at this point.&lt;/p&gt;
&lt;p&gt;The current design goals is to create a separate, independent program that can be called by text editors. Inspired by &lt;a href="http://www.omnisharp.net/"&gt;OmniSharp&lt;/a&gt;, I figured it was better to create a program that did one thing well (analysis and refactor novels) and then create hooks that can talk to other editors like Emacs and &lt;a href="https://atom.io/"&gt;Atom&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm also using &lt;a href="https://gruntjs.com/"&gt;Grunt&lt;/a&gt; and &lt;a href="https://www.npmjs.com/"&gt;NPM&lt;/a&gt; from my own experiences. Some of the earlier implementations of AI were self-contained with all the plugins installed there. However, as I've been working on my &lt;a href="https://gitlab.com/mfgames-writing-js/"&gt;Javascript publishing framework&lt;/a&gt;, versioning is very important. I can't break the analysis of novels I wrote ten years ago just because the code has improved to handle the novels of today. NPM has a great way of handling that with the &lt;code&gt;package.json&lt;/code&gt; file that lists specific packages and versions, which can be installed and used. So, AI is done the same way, the system uses &lt;em&gt;specific&lt;/em&gt; versions of packages to ensure that it always produces the same data. If you upgrade the underlying packages, then you can deal with the changes and check in the results knowing it won't change tomorrow.&lt;/p&gt;
&lt;p&gt;I've written AI in a number of languages (Javascript, Typescript, C#, Pythong) along with different UIs. I've gotten lost in a lot of them. At the moment, my skills in C# are considerably more advanced than the others, but more importantly, the tools (ReSharper) make me a lot more effective. I don't want this to be a learning experience at this point because I have a lot of novels I need to write and I have to focus on either making fun tools (AI) or finish books.&lt;/p&gt;
&lt;p&gt;I don't want this to be an argument of language. I like C# and I'm good at it, so I'm using it.&lt;/p&gt;
&lt;h1&gt;Overall Status&lt;/h1&gt;
&lt;p&gt;It isn't there yet. I'm working for an end-to-end which means setting up the files and being able to run a program (&lt;code&gt;aicli&lt;/code&gt;) and have it produce an output that shows echo words (the first analysis I want to write and my current blindspot). What does work requires a relatively specific setup (not that bad, everything is contained inside the &lt;a href="https://gitlab.com/author-intrusion/author-intrusion-cil/"&gt;repository&lt;/a&gt;) and a bit of hand-holding.&lt;/p&gt;
&lt;p&gt;This is still in the &amp;ldquo;black triangle&amp;rdquo; point since the technical framework is set in place, I'm still combining them to produce something that looks cool.&lt;/p&gt;
&lt;p&gt;All of the examples are based on a subset of &lt;em&gt;Sand and Blood&lt;/em&gt; used for testing. It can be found &lt;a href="https://gitlab.com/author-intrusion/author-intrusion-cil/tree/drem-0.0.0/Examples/Sand%20and%20Blood"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Configuration&lt;/h1&gt;
&lt;p&gt;Like Grunt, there is a single file that controls how AI works with a project. I took inspiration from &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; and Atom in that every file isn't explictly added to the project. Instead, AI assumes that all files underneath the directory containing the &lt;code&gt;author-intrusion.yaml&lt;/code&gt; file is part of the project. If you add a chapter, the YAML file won't change but the system will pick it up.&lt;/p&gt;
&lt;p&gt;I used YAML because it is easy to use, doesn't require a lot of noise, and pretty much handles the relatively simplistic data. Also, unlike JSON, YAML can let you copy a section from one place to another which I consider to be pretty useful.&lt;/p&gt;
&lt;p&gt;I am trying to avoid changes a lot of files whenever you add a chapter, that's just noise in most cases. Related to that, AI will create a &lt;code&gt;.ai&lt;/code&gt; directory for its internal caches, that shouldn't be checked into source control at all.&lt;/p&gt;
&lt;p&gt;Eventually, &lt;code&gt;aicli&lt;/code&gt; will search for &lt;code&gt;author-intrusion.yaml&lt;/code&gt;. That way, like Grunt, it can be called anywhere inside the directory tree and it will &amp;ldquo;do the right thing&amp;rdquo; to produce consistent results. This is the same thing &lt;code&gt;git&lt;/code&gt; does among other CLI implementations.&lt;/p&gt;
&lt;p&gt;The basic &lt;code&gt;author-intrusion.yaml&lt;/code&gt; file is pretty simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;file:
    - plugin: AddClassFromPath
      match: chapters/*.markdown
      class: chapter
data:
	- plugin: AddClassFromData
	  select: file.chapter
	  class: pov-{pointOfView}
layout:
    - plugin: SplitLines
    - plugin: SplitParagraphs
    - plugin: OpenNlpSplitTokens
      select: para
    - plugin: WordTokenClassifier
analysis:
    - plugin: Echoes
      select: file.chapter token.word
      scope: token.word:within(10)
      threshold: { error: 5, warning: 2 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the example file from the link above, there is a lot more in the file either for documentation purposes or just to work out some concept or idea.&lt;/p&gt;
&lt;p&gt;There are four sections: &lt;code&gt;file&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;layout&lt;/code&gt;, and &lt;code&gt;analysis&lt;/code&gt;. These are various operations that are performed on each file to classify (&lt;code&gt;file&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt;), organize (&lt;code&gt;layout&lt;/code&gt;), and analyze (&lt;code&gt;analysis&lt;/code&gt;) the files.&lt;/p&gt;
&lt;h1&gt;Plugins&lt;/h1&gt;
&lt;p&gt;Most of the processes are based on the idea of a &amp;ldquo;plugin&amp;rdquo;. A plugin is a discrete class (typically in its own &lt;a href="https://www.nuget.org/"&gt;NuGet&lt;/a&gt; package) that is versioned and specific to the current project. They are identified by the &lt;code&gt;plugin&lt;/code&gt; property inside the list. A plugin can be used more than once.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
	  id: Words Within 10
      select: file.chapter token.word
      scope: token.word:within(10)
      threshold: { error: 5, warning: 2 }
    - plugin: Echoes
	  id: Sounds Alike
      select: file.chapter token.word
      scope: token.word:within(5)
	  compare: :root:attr(soundex)
      threshold: { error: 5, warning: 2 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In each case, the &lt;code&gt;plugin&lt;/code&gt; property of each plugin identifies which plugin to use. This is usually the base class but it means I'll have to have a registry to list which plugins do what. The reason for doing this is because if someone else writes a plugin (extends AI), they can push it up to NuGet (about that later) and everyone can use it. It doesn't require a release of the main code (assuming &lt;code&gt;AuthorIntrusion.Contracts&lt;/code&gt; remains the same).&lt;/p&gt;
&lt;p&gt;The rest of the properties are based on that plugin. There is a bit of interesting complexity in making this work (e.g., hack but I wrote it) but everything is type safe when it comes to coding.&lt;/p&gt;
&lt;h1&gt;Selectors&lt;/h1&gt;
&lt;p&gt;In the above examples, &lt;code&gt;select&lt;/code&gt; and &lt;code&gt;scope&lt;/code&gt; are based on CSS selectors. I couldn't find a library that did it generically, so I wrote one that just creates an abstract syntax tree of CSS selectors which is used by this library. Like most of the plugins, I'll break it into a separate project once AI gets stable.&lt;/p&gt;
&lt;p&gt;The advantage of using CSS, such as &lt;code&gt;file.chapter token.word&lt;/code&gt; or &lt;code&gt;:root&lt;/code&gt; is that many developers understand how CSS selectors works. Except for the specifics (pseudo-classes for example), how they chain together, how you combine them, those are known enough that I don't have to force someone to learn something new.&lt;/p&gt;
&lt;p&gt;I'm setting up the layout of a file (using the &lt;code&gt;layout&lt;/code&gt; plugins) to look like HTML. Those plugins create the tag/element structure that CSS uses.&lt;/p&gt;
&lt;p&gt;Right now, the following are implemented:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:first-child&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:last-child&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:nth-child&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:root&lt;/code&gt; is the top-level item being selected (usually the &lt;code&gt;file&lt;/code&gt; but can be something else)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also scoped pseudo-classes. These are used to get elements based on their relationship to another element. In every case so far, the &lt;code&gt;scope&lt;/code&gt; property is based on each element found in the &lt;code&gt;select&lt;/code&gt; of the plugin.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:before(x)&lt;/code&gt; finds the elements before the scope. It can be used like &lt;code&gt;token.word:before(5)&lt;/code&gt; to get the five words before the current one.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:after(x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:within(x)&lt;/code&gt; which is basically &lt;code&gt;:before(x)&lt;/code&gt; combined with &lt;code&gt;:after(x)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:self-&lt;/code&gt; versions of the three above.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:parent&lt;/code&gt; matches an item that is the parent of the scope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These scoped variables are used so we can control what we are looking for. For example, the echoes plugin may look to see if the same word has been used somewhere within ten words of the current one:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
      select: token.word
      scope: token.word:within(10)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It can also be used to make sure the same word isn't used at the beginning of the surrounding paragraphs:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
      select: para token.word:first-child
      scope: para:within(1) token.word:first-child
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a third category used for comparisons (used by the Echoes). These are where I hack the CSS system but basically let me define operations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:lower&lt;/code&gt; get a lowercase version of the text.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:attr(attribute-name)&lt;/code&gt; uses the value of the attribute instead of the text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This lets us analyze for something more than just the text. For example, words that sound the same:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
      select: token.word
      scope: token.word:within(10)
	  compare: :root:attr(soundex) # :attr() isn't done yet
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or ones that have the same base word:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
      select: token.word
      scope: token.word:within(10)
	  compare: :root:attr(stem)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A third example is if we are looking for too many sentences that start with the same pattern of parts of speech. This is to find where &amp;ldquo;bob did this&amp;rdquo;, &amp;ldquo;bob did that&amp;rdquo;, &amp;ldquo;mary did something&amp;rdquo;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;layout:
    - plugin: ClassifyElementRange # Not done yet
	  select: sent token.word:first-child
	  scope: sent:parent token.word:self-or-after(2)
	  tag: sent-leading
analysis:
    - plugin: Echoes
      select: sent-leading
      scope: sent-leading:within(5)
	  compare: :root:attr(pos)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;File Plugins&lt;/h1&gt;
&lt;p&gt;Now, how all those topics are used. The first set of plugins are simply based on the structure of the project. Every file has one automatic element, the &lt;code&gt;file&lt;/code&gt; which is the &lt;code&gt;html&lt;/code&gt; of the file. We can add classes and identifiers to that to limit how the rest of the code works.&lt;/p&gt;
&lt;p&gt;The biggest one is AddClassFromPath. You can use that to add the &lt;code&gt;chapter&lt;/code&gt; class to files in the &lt;code&gt;chapters&lt;/code&gt; directory. That way, the later selectors can use &lt;code&gt;file.chapter&lt;/code&gt; or &lt;code&gt;.chapter&lt;/code&gt; to limit processing (don't need to do grammar on your notes).&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;file:
    - plugin: AddClassFromPath
      match: chapters/*.markdown
      class: chapter
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Data Plugins&lt;/h1&gt;
&lt;p&gt;I write using Markdown with a YAML header. My chapters look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
availability: public
when: 1471/3/28 MTR
duration: 25 gm
date: 2012-02-18
title: Rutejìmo
locations:
  primary:
    - Shimusogo Valley
characters:
  primary:
    - Shimusogo Rutejìmo
  secondary:
    - Shimusogo Hyonèku
  referenced:
    - Funikogo Ganósho
    - Shimusogo Gemènyo
    - Shimusogo Chimípu
    - Shimusogo Yutsupazéso
concepts:
  referenced:
    - The Wait in the Valleys
purpose:
  - Introduce Rutejìmo
  - Introduce Hyonèku
  - Introduce naming conventions
  - Introduce formality rules
  - Introduce the basic rules of politeness
summary: &amp;gt;
  Rutejìmo was on top of the clan's shrine roof trying to sneak in and steal his grandfather's ashes. It was a teenage game, but also one to prove that he was capable of becoming an adult. He ended up falling off the roof.

  The shrine guard, Hyonèku, caught him before he hurt himself. After a few humiliating comments, he gave Rutejìmo a choice: tell the clan elder or tell his grandmother. Neither choice was good, but Rutejìmo decided to tell his grandmother.
---

&amp;gt; When a child is waiting to become an adult, they are subtly encouraged to prove themselves ready for the rites of passage. In public, however, they are to remain patient and respectful. --- Funikogo Ganóshyo, *The Wait in the Valleys*

Rutejìmo's heart slammed against his ribs as he held himself still. The cool desert wind blew across his face, teasing his short, dark hair. In the night, his brown skin was lost to the shadows, but he would be exposed if anyone shone a lantern toward the top of the small building. Fortunately, the shrine house was at the southern end of the Shimusogo Valley, the clan's ancestral home, and very few of the clan went there except for meetings and prayers.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given that, I would use a plugin to let me add identifiers and classes to files based on the YAML header (the bit between the &lt;code&gt;---&lt;/code&gt; lines). For example, the following would add a &lt;code&gt;pov-ShimusogoRutejìmo&lt;/code&gt; class to the file.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;data:
	- plugin: AddClassFromData # Not done
	  select: file.chapter
	  class: pov-{characters.primary}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There will be ways of manipulating it, but basically it lets you tag the chapter with &amp;ldquo;scene&amp;rdquo; or &amp;ldquo;sequel&amp;rdquo; if you follow the &lt;a href="http://amzn.to/2pBEypw"&gt;Techniques of the Selling Writer&lt;/a&gt; or want to identify if a chapter is combat or talking. It doesn't matter how you want to tag it, you can use any element in the data to filter or make decisions later. This will also be used for the querying to let you say &amp;ldquo;what chapters are from Rutejìmo's point of view&amp;rdquo; or &amp;ldquo;what scenes happen at night&amp;rdquo;. Eventually, I'll tie it into my culture library so you can also say &amp;ldquo;show me the chapters in chronological order&amp;rdquo;.&lt;/p&gt;
&lt;h1&gt;Layout Plugins&lt;/h1&gt;
&lt;p&gt;The bulk of my effort in the last two weeks has been in the layout. This is what carves up the contents of the file into something that can be selected via the CSS system. The default is only to have the &lt;code&gt;file&lt;/code&gt; element which contains everything.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;layout:
    - plugin: SplitLines
	  tag: line # implied
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above splits everything into &lt;code&gt;&amp;lt;line&amp;gt;&lt;/code&gt; elements. We need that for reporting line number errrors. Below, we have a plugin that splits things into paragraphs based on Markdown rules (a blank line separates a paragraph). Using the above examples, this is what lets us use the &lt;code&gt;para .word:first-child&lt;/code&gt; for selectors.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;layout:
    - plugin: SplitParagraphs
	  tag: para # implied
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It gets complicated when we start adding tokens. A token is a word or puncutation. I'm using &lt;a href="https://opennlp.apache.org/"&gt;OpenNLP&lt;/a&gt; to break apart the words at the moment. This splits up the contents of the paragraph (because of the &lt;code&gt;select: para&lt;/code&gt;) into tokens.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;layout:
    - plugin: OpenNlpSplitTokens
      select: para
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I have tokens, I can add the &lt;code&gt;word&lt;/code&gt; class to the actual words.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;layout:
    - plugin: WordTokenClassifier
	  class: word # implied
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Eventually, there will be a &lt;code&gt;OpenNlpSplitSentences&lt;/code&gt; plugin where you would split the paragraph into sentences and then split the sentences into tokens. That isn't done but we don't need it for the base. I will also eventually create a &lt;code&gt;ParagraphSentenceWord&lt;/code&gt; plugin that does most of this and makes it easier to add it as a single line.&lt;/p&gt;
&lt;p&gt;The end result is that we have an abstract tree that represents the file. Eventually there may be a lot more such as dialog identification, blockquotes and epigraphs, and whatever else makes sense.&lt;/p&gt;
&lt;p&gt;The main reason for the layout plugins is to make the selectors work for the analysis. It is also a complex bit of code that has to run in order unlike analysis which can be multi-threaded for a given file.&lt;/p&gt;
&lt;h1&gt;Analysis Plugins&lt;/h1&gt;
&lt;p&gt;Finally, the last bit. I'm not done with anything else, but the analysis plugin is the bit that finds errors and warnings. It is the parts that &amp;ldquo;does&amp;rdquo; something. In other words, the entire reason I'm writing this.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;analysis:
    - plugin: Echoes
      select: file.chapter token.word
      scope: token.word:within(10)
      threshold: { error: 5, warning: 2 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I'm working on this next, but I hope to have &lt;code&gt;aicli check&lt;/code&gt; produce an error like &lt;code&gt;gcc&lt;/code&gt; or a complier that gives a specific file and line number (via the &lt;code&gt;SplitLines&lt;/code&gt; plugin) that lists the errors. It will be the same thing Atom uses to highlight problems.&lt;/p&gt;
&lt;p&gt;Since analysis plugins only add/remove errors, they don't change the structure. This means they can use all the CPUs using worker processes to make it as efficient as possible. I'm also going to eventually have some optimizations put in (most elements are hashed so they can be cached).&lt;/p&gt;
&lt;h1&gt;Status and Plans&lt;/h1&gt;
&lt;p&gt;This last week, I've gotten the folllowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS selectors are working.&lt;/li&gt;
&lt;li&gt;CSS pseudo-classes working for scope to get ranges of words.&lt;/li&gt;
&lt;li&gt;CSS for doing transformations to make text lowercase before comparison.&lt;/li&gt;
&lt;li&gt;The basic layout plugins needed to break a file into lines, paragraphs, tokens, and words.&lt;/li&gt;
&lt;li&gt;A search path for plugins can find assemblies in a different directory.&lt;/li&gt;
&lt;li&gt;The starting code for using NuGet for packages is there.&lt;/li&gt;
&lt;li&gt;Echoes can find the words, just not report them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal is to get a simple echo words analysis done, basically looking for duplicates within ten words.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get &lt;code&gt;TextQuery&lt;/code&gt; to compare text between the select and the scope.&lt;/li&gt;
&lt;li&gt;Add warnings and errors (notices) to elements.&lt;/li&gt;
&lt;li&gt;Report the notices to the console for the &lt;code&gt;aicli check&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I really want to get this to the point it can be used. I think it will be benefical even with the basics for finding problem spots with my personal projects and can benefit others. I also think that once I get the end-to-end, additional functionality will be easily added for other needs.&lt;/p&gt;
&lt;h1&gt;Development&lt;/h1&gt;
&lt;p&gt;Development is currently on the &lt;a href="https://gitlab.com/author-intrusion/author-intrusion-cil"&gt;drem-0.0.0&lt;/a&gt; branch on Gitlab. I'm adding issue of secondary items while tagging them with expected complexity. While I don't expect anyone to contribute, if someone does get inspired the &lt;code&gt;simple&lt;/code&gt; and &lt;code&gt;trivial&lt;/code&gt; items are good starting points.&lt;/p&gt;
&lt;p&gt;I plan on adding notes for contributing &amp;ldquo;soon&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;So far, everything is MIT licensed but there will be other licenses already involved. OpenNLP is Apache licensed so I'll need to figure out how that interacts with MIT. Once I split the packages into individual files, it will probably be easier but for the time being, life is faster if I keep it as a single repository.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Author Intrusion 0.1.0 "James White"</title>
    <link rel="alternate" href="https://d.moonfire.us/blog/2013/07/01/author-intrusion-0-1-0-james-white/" />
    <updated>2013-07-01T05:00:00Z</updated>
    <id>https://d.moonfire.us/blog/2013/07/01/author-intrusion-0-1-0-james-white/</id>
    <category term="programming" scheme="https://d.moonfire.us/categories/" label="Programming" />
    <category term="author-intrusion" scheme="https://d.moonfire.us/tags/" label="Author Intrusion" />
    <category term="fast-trip" scheme="https://d.moonfire.us/tags/" label="Fast Trip" />
    <content type="html">&lt;p&gt;After five weeks, I finally got &lt;a href="http://mfgames.com/author-intrusion"&gt;Author Intrusion&lt;/a&gt; to a stopping point enough to make its first release. This is version 0.1.0 and is dedicated to &lt;a href="http://www.sectorgeneral.com/"&gt;James White&lt;/a&gt; since his story, Fast Trip, is actually what inspired me to create AI in the first place.&lt;/p&gt;
&lt;p&gt;This release is neither pretty nor smooth. It only has five menu items (all hard-coded of course), limited keyboard shortcuts, and configuration is done by editing the XML file and reloading (which it also doesn't support).&lt;/p&gt;
&lt;p&gt;The important part is that it works and I think it is stable enough to write a novella with. So, in the next few weeks, I'm going to write long piece with this and figure out what needs to be done. Along the way, I'm going to figure out what &lt;em&gt;really&lt;/em&gt; doesn't work. The ones I cannot live without, I'll fix for next month, otherwise I'll start getting them over time.&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h1&gt;Why release?&lt;/h1&gt;
&lt;p&gt;The biggest question I had was my decision to call this a release. In the end, it came down to building up a rhythm and also accountability. I've been working on Author Intrusion for three years now and never got anywhere. I would get to a certain point and just stop to work on other things. If I put it out as a release, I have something out there to help me focus on its development and still get some writing done.&lt;/p&gt;
&lt;p&gt;The other reason is that even a novel starts with a single word. First drafts are terrible things as is this. I never had the raw talent to be a decent writer or a programmer. Yes, I had a few advantages on the programming side, but mostly I got to where I am by steadily moving forward. If I want AI to work, I have to do the same thing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just keep swimming. -- Dori, &lt;em&gt;Finding Nemo&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;Links&lt;/h1&gt;
&lt;p&gt;I decided to create a &lt;a href="http://sourceforge.net/projects/authorintrusion/"&gt;SourceForge project&lt;/a&gt; for now, mainly for file distribution. I'll put it up on my &lt;a href="http://mfgames.com/author-intrusion/"&gt;own site&lt;/a&gt; also, but that's running a bit behind while I work on a few other things. Hopefully by the end of the week, I'll have more than just a plain page on the Moonfire Games site.&lt;/p&gt;
&lt;p&gt;There is only a MSI installer for Windows. For everything else, you'll need &lt;a href="https://github.com/dmoonfire/author-intrusion/"&gt;source code&lt;/a&gt;, a lot of luck, and probably a wide variety of curses to interpret what I've done. I went with WiX for the installer and it is built with every release which means I &lt;em&gt;should&lt;/em&gt; hopefully be able to catch errors early and often.&lt;/p&gt;
&lt;p&gt;Though, if you are looking for something remotely more capable than EDIT on DOS 3.1, you probably don't want to use this.&lt;/p&gt;
&lt;h1&gt;The final week&lt;/h1&gt;
&lt;p&gt;This last week was cleaning up code. I ended up doing a lot of reorganization and refactoring to smooth over some of the more heinous parts of the code. Projects that I thought should be combined got merged, then split, and then re-merged together. Right now, I think I have a good layout of projects for moving forward.&lt;/p&gt;
&lt;p&gt;I did end up creating a placeholder package for Gtk#, Mono.Cairo, and Mono.Posix because I needed to move those dependencies out of my code.&lt;/p&gt;
&lt;p&gt;Everything went smoothly right up to Saturday night. On Saturday, I realized I hadn't tested on Linux (one of my tenants of this project is to run on both Linux and Windows and eventually a Mac). It didn't go well. Libraries that I was pretty sure I tested ended up not working. I also did this project with the 4.5 framework instead of 3.5 which I tested earlier; this meant I needed the latest version of Mono (thanks &lt;a href="https://www.meebey.net/posts/mono_3.0_preview_debian_ubuntu_packages/"&gt;Meebey&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The biggest thing that didn't work was the inversion of control system I was using. &lt;a href="http://www.ninject.org"&gt;Ninject&lt;/a&gt;. It didn't work with any version of Mono. Well, the main one may have worked but the "by conventions" extension I was using didn't and I gave up. Since I already knew &lt;a href="http://docs.structuremap.net/"&gt;StructureMap&lt;/a&gt; worked, I switched over to that (only a single class) which worked beautifully. I spent a few more hours trying to get Ninject working but gave up.&lt;/p&gt;
&lt;p&gt;The other was the spell-checking system, &lt;a href="http://nhunspell.sourceforge.net/"&gt;NHunspell&lt;/a&gt;. This one I didn't check on Linux and it didn't work. It might be a minor thing, it may not. But, I tried to make the spelling framework simply enough I can drop in something else at a later date.&lt;/p&gt;
&lt;h1&gt;What's next?&lt;/h1&gt;
&lt;p&gt;There are quite a few things for the next month. The biggest is that I'm going to write something with it. Actually use the program and figure out what are the worse pain points. Those that block me, I'll fix in July. The others will be thrown on the &lt;a href="https://github.com/dmoonfire/author-intrusion/issues"&gt;issues list&lt;/a&gt; so I don't lose them.&lt;/p&gt;
&lt;p&gt;I also have a few more blog posts that I think would be helpful to write. Mostly thoughts I had in the last few weeks, some decisions I made, and general informational things that may help a Google search in the future.&lt;/p&gt;
</content>
  </entry>
</feed>
