Zatmění

Korporace milují Eclipse. Je to přesně ten druh softwaru, kterému nedokáží odolat: důkladně architektovaná Java, rozšiřitelná, legitimizovaná všemi ostatními, kdo ji používají, distribuují a zvelebují. A přitom je všechno to potěšení zadarmo!

Ale: Eclipse nejzářnějším příkladem, toho, jak vývoj softwaru upadl do jakéhosi podivného stavu, kdy jsou náklady na vývoj minimalizovány za cenu brutálního nárůstu nákladů uživatelů. Místo toho, aby na moderním hardwaru běžely aplikace rychleji a rychleji… čekáme. Čekáme až se spustí, až provedou operaci, až se ukončí.

A co jsme udělali, když obědy zdarma skončily, a frekvence procesorů přestaly růst? Ó, ne, nechytili jsme se za nos a nezačali optimalizovat, zjednodušovat, zrychlovat. To by bylo… zpátečnické. Protože principem naší společnosti je růst. Dokud software a jeho nároky rostou, je svět v pořádku. Jakmile se začnou zmenšovat, je něco špatně.

A tak jsme začali růst jinak. Začali jsme přidávat jádra, paměť, a tak dále. To je správná cesta. V tom je to opravdové falické uspokojení.

A ano, i já jsem vinen. Lepil jsem na sebe jednu abstrakci za druhou a lebedil si, jak sofistikovaný jsem, jak krásně mi to… roste. Bez ohledu na to, že na banální aplikaci potřebuji gigabajt paměti a čtyři jádra procesoru.

Ale když se tak dívám na Eclipse, říkám si, že všechno má své meze. Že bychom se možná měli zastavit a zamyslet se nad tím, jestli něco neděláme špatně. Ne že bychom snad měli všechno zahodit a začít znova. To je delší a dražší cesta ke stejnému stavu v jakém jsme dnes.

Ale možná bychom si měli pokaždé, než přidáme další úroveň indirekce, zkusit spustit Eclipse, abychom věděli kam až věci mohou dojít.

Dilema

Někdy je to prostě potřeba udělat. Myslím vykašlat se na to, co by člověk dělat měl a dělat to, co dělat chce. Zejména pokud jde o volný čas.

Takže co bych dělat měl, je programovat Lithium. Co dělat chci, je psát další interaktivní povídky. Dokonce to zašlo tak daleko, že jsem Twee plugin do svého fantastického editoru doplnil diagramovacím oknem, kde se mohu kochat strukturou povídky tak nějak vizuálně.

Chtělo by se mi říct, že nutkání dělat to, co bych měl, místo toho co chci (což je jistě svaté právo každého středostavovského obyvatele rozvinutých — nebo jen mírně zaostalých — zemí), pochází od mých zvrácených hodnot. Že jaksi chci být nechutně bohatý z nechutně vysokých prodejů hry na appstorech (99 centů za kus), a kašlu na to, že to, co napíšu možná přivede jednoho, nebo dokonce dva lidi k zamyšlení. Ale jako obvykle to není tak jednoduché.

Důvodů proč bych chtěl mít svůj malý krámek s hrami je několik a možnost přivydělat si není zdaleka na prvním místě (i když samozřejmě by se mi líbilo mít v záloze malý soukromý podnik, který by mě mohl uživit až mi bude kolem šedesáti, budu mít před sebou ještě tak patnáct let na trhu práce ale už mě nikdo nebude chtít zaměstnat, protože budu starý). Hlavní je, jako obvykle, prestiž. Vytasit na někoho mobilní telefon a ukázat mu blikající obrazovku a říct, “Hle, toto jsem stvořil”, je určitě víc kewl, než “Tady, můžeš dvě tři hodiny strávit čtením interaktivního existenciálního dramatu”, že ano.

Tahle prestiž, to je věc.

Problém je v tom, že jsem momentálně tak trochu ve stavu, kdy touha po prestiži je válcována touhou něco sdělit, a nejrychlejší způsob, jak v tomto směru selhat, je napsat interaktivní povídku.

Takže jsem naostřil textový editor, nakoupil čaje, naklikal playlist a pouštím se do toho.

Jen na částečný úvazek, samozřejmě, protože, dělat to, co člověk chce, místo toho, co by měl, je značně změkčilé.

Using Twine/twee without Python installation

Because it seems, that I’ll be writing another Twine/twee interactive fiction in not so distant future, I realized, that there is one thing I’m bothered about twee: I don’t like the act of installing Python and twee. While I have my scripts, this kind of integration of twee and Naracea is still sort of cumbersome. Thus I decided to do something about it.

And because twee is just couple of Python scripts, and I have IronPython integrated in Naracea already, I decided to try how these two things work together. And it seems they work just fine. What twee needs is Python standard library, which I didn’t include into my Python scripting plugin before, but adding support for it was matter of one or two hours.

And after couple tests, I’ve found out that twee indeed works with IronPython, and my test story is built properly.

Thus I took my scripts and converted them into plugin, which can be just unzipped to Naracea installation directory, and you get twee support nicely integrated directly into the editor without need to install either Python or twee itself.

Installed plugin adds two buttons to ribbon Document tab:

Build builds the story (and opens result in default browser), Tweenify sets up the document so it better fits twee coding needs (it mainly sets syntax highlighting and spellchecking based on current branch settings).

At this point the plugin is kind of rough, because I’m not sure whether someone else would find it useful, and for my needs it is good enough. However if you have any improvements requests or suggestions, let me know via Naracea issue tracker.

So if this sounds interesting, you can find the plugin and short installation instructions at Naracea’s plugin page (if you are using .zip package, see also PyScript section of the page for details on Python standard library installation).

Writing Twee code with Naracea

Recently I’ve written short interactive story (in Czech, of course) using twee (while I like idea of Twine’s user interface, I’m text/code person, so I prefer to use twee). I used my own text editor Naracea, because, obviously, it fits all of my needs, and it integrates with twee quite nicely (as I will show below).

Naracea supports branching, which can be used either to branch text to different versions inside of single file, or it can base multiple branches on initial state of the first branch and thus create multiple “notebooks” inside of one document. When writing story, I was experimenting with this for a while, and after couple of passages I realized, that keeping everything in single branch (or single text file), leads to horrible mess which I’m not able to manage.

So I’ve split whole story to multiple branches (around sixty when it was done) with most branches having only one passage in it.

That was nice and all, but there were two problems. One is necessity to setup each branch manually when it was created. I didn’t foresee this as a problem when I was using the editor for usual things like writing blog posts etc., but here it quickly became a major pain point. Fortunately all settings in Naracea are hierarchical, so when branch doesn’t define e.g. spell checker language, it will look in document’s settings (and then in global application settings).

Recently I added plugin model and possibility to script Naracea with IronPython, so it was quite easy to write little script to handle the problem:

import clr
# Get some types we need to use
clr.AddReference("Common")
clr.AddReference("Core")
from Naracea.Common import ( Settings )
from Naracea.Core.Spellcheck import ( DictionaryDescriptor )
from System import ( Exception )  

# Check whether a document is open and active.
document = PluginHost.Application.ActiveDocument  
if document == None:
	raise Exception("No document")

# Get spellcheck language from current branch. This way we don't need to import any further types.
# Just set spelling language on one branch from app UI.
currentSpellingLanguage = document.ActiveBranch.Settings.Get[DictionaryDescriptor](Settings.SpellcheckLanguage)
print currentSpellingLanguage.DictionaryName

# Now apply settings on document level.
# Since settings are hierarchical, when nothing is set on branch, document value is used.
# We set spellchecker, export format + extension and syntax highlighter.
document.Settings.Set(Settings.SpellcheckLanguage, currentSpellingLanguage)
document.Settings.Set(Settings.BranchAutoExportFormat, "TXT")
document.Settings.Set(Settings.BranchAutoExportExtension, ".tw")
document.Settings.Set(Settings.ViewTextEditorSyntaxHighlighting, "Twee")

# If there are existing branches in document, setup their exporting.
for branch in document.Branches:
	branch.Settings.Set(Settings.BranchAutoExportFormat, "TXT");
	branch.Settings.Set(Settings.BranchAutoExportExtension, ".tw");
	branch.Editor.Settings.Set(Settings.ViewTextEditorSyntaxHighlighting, "Twee");

Now I just setup one branch and run the script propagate settings to document (and all existing branches). (Also remember to close and open document again to see the changes, because I wasn’t planning things like this when I was writing those parts of Naracea — I’ll fix this in some future release.)

Nice.

The second problem was, that when all source text was kept in single branch, I was able to setup autoexport for a branch and get whole twee file (and then run the twee from command line to process it into HTML), now I have tens of branches which need to be merged.

So I created another script to fix this issue:

# CLR is needed
import clr   
# Some references to assemblies
clr.AddReference("Plugin")
clr.AddReference("System.Threading")

# Import classes we are going to use
from System.Threading import ( AutoResetEvent )
from System.Diagnostics import ( Process, ProcessStartInfo )   
from System.IO import ( Path )   
from System import ( Exception )    
from Naracea.Plugin.Messages import ( BranchShiftingFinished )

# No document? Report error
if PluginHost.Application.ActiveDocument == None:  
     raise Exception("No document open.")

# Here will be the merged story text
mergedText = ""

# We need to iteratre over all branches, get their text and add it to the mergedText variable.
# However some branches might not be activated yet (Naracea lazy loads branches to save 
# memory and improve file opening times), so we need to ensure they are all active before 
# getting text out of them.
document = PluginHost.Application.ActiveDocument  
activeBranch = document.ActiveBranch
# We will sync on this event
waitEvent = AutoResetEvent(False)
# Subscribe for message signalling branch was successfully initialized
PluginHost.Bus.Subscribe[BranchShiftingFinished](lambda msg: waitEvent.Set());
# Iterate all branches
for branch in document.Branches:
	if not branch.IsActivated:
		# Branch is not active, we need to activate it by setting it as active branch
		document.ActiveBranch = branch
		# And now we need to wait till branch is initialized
		waitEvent.WaitOne();
	
	# It is safe to get text now
	mergedText += branch.Editor.Text + "\n\n"

# Restore last active branch
document.ActiveBranch = activeBranch

# Log merged text to console if you need it
# print mergedText

# Now we prepare save path
# File might not be saved yet, and we will use temp path in such case
sourcePath = PluginHost.Application.ActiveDocument.Filename  
if sourcePath != None:  
     sourcePath = Path.GetDirectoryName(sourcePath)       
else:  
     sourcePath = Path.GetTempPath()  
       
# Exported file name building happens here
branchExportFilename = "tweenExport.tw"  
sourceFile = Path.Combine(sourcePath, branchExportFilename)
print sourceFile

# Open file and save text as UTF8
outFile = open(sourceFile, "w")
outFile.write(mergedText.encode('utf8'))
outFile.close()

# Now generate target filename 
targetFile = Path.Combine(sourcePath, Path.GetFileNameWithoutExtension(sourceFile)) + ".html"   
print targetFile   
  
# Following calls twee and executes conversion
compiler = Process()   
compiler.StartInfo.FileName = "cmd"   
compiler.StartInfo.WorkingDirectory = sourcePath   
compiler.StartInfo.Arguments = "/c c:\\devtools\\python27\\python.exe c:\\devtools\\twee\\twee -t sugarcane \"{0}\" > \"{1}\"".format(sourceFile, targetFile)   
compiler.StartInfo.UseShellExecute = False   
compiler.StartInfo.CreateNoWindow = True  
compiler.StartInfo.RedirectStandardOutput = True 
compiler.Start()   
output = compiler.StandardOutput.ReadToEnd()   
compiler.WaitForExit()   
print output 

# Open converted HTML file in default browser
Process.Start(ProcessStartInfo(targetFile))   

This will merge all branches in one text, save it to disk, call twee to generate HTML and open exported file in default web browser.

I guess this makes Naracea nice alternative for developing Twine/twee stories on Windows:

Twee code