List of diary entries in all languages.

So I'm writing an IMAP client for Emacs. The main reason is that I want an email client works as if by osmosis, like the one on my phone—whenever it has a connection, messages magically enter a local cache, where they stay available even if the connection is lost. There are many ways to achieve that with existing Emacs email clients, possibly augmented with external tools, but I want one that works with minimal setup, and requires nothing but Emacs itself.

The first problem encountered when writing an IMAP client is parsing what the server is sending. There are two IMAP parsers in the Emacs source tree already (imap.el and nnimap.el), both fairly closely tied to their respective clients, and both synchronous—they block Emacs while they are waiting for data from the server. I want to address both of those points: my IMAP client is going to have a reusable asynchronous parser module.

Obviously, the first step in figuring out how to parse the protocol is to read the IMAP RFC. Naturally, you'd skip ahead to the section "Formal syntax", which defines in ABNF what various messages should look like: a sequence number followed by one of a few keywords followed by a quoted string or an atom, etc etc. That's where I started, adding a special case for each command response into my parser code.

But then I thought that this wasn't the right way to do it. The parser module wouldn't be independent of the module that uses it, since the calling module might want to use an extension that the parser module doesn't know about yet. Also, I would constantly need to come up with sensible data structures to represent the responses with.

So I decided to create a parser that would be able to parse IMAP responses with as little knowledge as possible about what those responses should look like. It turns out that most of IMAP consists of atoms, strings and lists. I figured that I should be able to parse everything following these simple rules:

  • If it starts with a double quote, parse it as a quoted string.
  • If it starts with a ( or [, descend, parse recursively and return it as a list.
  • Otherwise, treat it as an atom, read until the next space character or closing ) or ], and return it as a string.

For example, this LIST response:

* LIST (\HasNoChildren) "." INBOX

gets parsed to this:

("*" "LIST" ("\\HasNoChildren") "." "INBOX")

This mostly worked. One exception is that if the second word of a line is one of OK, NO, BAD, BYE or PREAUTH, then the rest of the line (described by resp-text in the RFC) is free-form human-readable text, optionally preceded by a resp-text-code. For example, this is part of a response to a SELECT command from the Dovecot server:

* OK [UNSEEN 6] First unseen.
* OK [UIDVALIDITY 1381959933] UIDs valid
* OK [UIDNEXT 10] Predicted next UID
1 OK [READ-WRITE] Select completed (0.003 secs).

There is no reason why this free-form text couldn't contain unbalanced parentheses or anything else that might confuse a parser, and besides it doesn't make sense to split the text into words anyway. So that's a special case for the parser, and gets parsed to this:

("*" :ok :code "UNSEEN"      :data "6"          :text "First unseen.")
("*" :ok :code "UIDVALIDITY" :data "1381959933" :text "UIDs valid")
("*" :ok :code "UIDNEXT"     :data "10"         :text "Predicted next UID")
("1" :ok :code "READ-WRITE"  :data nil          :text "Select completed (0.003 secs).")

Then there is BODY, which when given as a fetch or message attribute is followed immediately by an opening square bracket, e.g. BODY[]. I decided to treat it as if there were a space between BODY and the bracket, and return them as two elements, the string "BODY" and the list of items parsed inside the brackets.

And all of this applies in principle to every single line, except that a physical line can end with a byte count in curly braces (e.g. {42}), which means that the following bytes are literal data to be treated as part of the current logical line. Fortunately, this is independent from the parsing itself, so I have a function that splits the data by logical lines and passes everything to the parse function.

So far, my little client is able to select a mailbox, search for unread messages and fetch the messages, and my parser is sufficient for all of that.

Posted Sat 03 May 2014 03:47:00 AM BST

Emacs 24 introduced the possibility to open TLS network connections using the GnuTLS library directly, instead of using a command line tool as a wrapper. This is especially interesting for those who are stuck using Emacs on Windows, as the command line tools can be rather brittle on that platform.

However, there are some steps that need to be performed in order to get native GnuTLS to work. This page attempts to describe them.

Get a GnuTLS-enabled Emacs

The Windows binaries available for download from the GNU site are compiled against GnuTLS, but if you compile your own Emacs, see the file nt/INSTALL in the Emacs source distribution for instructions.

Find the GnuTLS DLLs

The first google hit for "emacs gnutls windows" is this page. It says:

There's one way to find out if GnuTLS is available, by calling gnutls-available-p. This is a little bit trickier on the W32 (Windows) platform, but if you have the GnuTLS DLLs (available from http://sourceforge.net/projects/ezwinports/files/ thanks to Eli Zaretskii) in the same directory as Emacs, you should be OK.

On that page, I found:

gnutls-3.0.9-w32-bin.zip    2012-01-02  7.2 MB

Extract the GnuTLS DLLs

I first naïvely tried opening the zip file in Explorer and copying the files from there, but that does nothing—it neither copies the files nor displays any error message. You need to extract the zip file, and then copy all DLL files to the bin directory where your Emacs is installed, probably somewhere like C:\Program Files (x86)\emacs-24.3\bin.

Restart Emacs and try it

At this point, if you restart Emacs and type:

M-: (gnutls-available-p) RET

you should see t in the echo area, which means that Emacs can find the GnuTLS libraries.

Configure trust files

However, if you try to open a TLS connection, it will fail complaining that certificate validation failed. This happens because GnuTLS needs to have a set of CA certificates to verify the certificates of the servers it connects to. It looks for CA certificates in the locations specified in the variable gnutls-trustfiles, but none of the default values work out of the box on Windows.

I'm not aware of any way to make GnuTLS use any certificates that come with the Windows system, so you need to get a certificate bundle from elsewhere. The cURL project provides such a bundle that you can download. Download the cacert.pem file to a suitable location, and point gnutls-trustfiles to it with customize-option. Note that the file name is passed unexpanded to GnuTLS, so you cannot use ~ as a shorthand for your home directory; use the full absolute file name instead.

See if it works

Paste the following piece of code into the *scratch* buffer:

(condition-case e
    (delete-process
     (gnutls-negotiate
      :process (open-network-stream "test" nil "www.google.com" 443)
      :hostname "www.google.com"
      :verify-error t))
  (error e))

Then put point at the end and hit C-j. If nil gets inserted into the buffer, then the certificate could be verified, and your setup appears to be working.

Otherwise, you'll see an error like:

(error "Certificate validation failed www.google.com, verification code 66")

If so, a good place to start debugging is setting the variable gnutls-log-level to a value greater than 0.

Emacs 24 introduced the possibility to open TLS network connections using the GnuTLS library directly, instead of using a command line tool as a wrapper. This is especially interesting for those who are stuck using Emacs on Windows, as the command line tools can be rather brittle on that platform. However, there are some steps that need to be performed in order to get native GnuTLS to work. This page attempts to describe them.

Posted Sat 26 Apr 2014 01:01:11 AM BST

In Emacs 23 or later, you can use M-x proced to get a list of running processes. You can sort and filter them in various ways, the most common end goal being to quickly find and kill certain processes in my experience.

However, Proced currently doesn't work on OSX. I just spent a few minutes figuring out why, so I hope writing this could save someone else some effort.

Proced is not based on command line tools such as ps, but uses Emacs Lisp functions implemented in C to get the list of processes (list-system-processes) and to get process attributes (process-attributes). list-system-processes works on OSX, but process-attributes does not. sysdep.c contains a few different implementations guarded by #ifdefs, and this is the one chosen for OSX:

Lisp_Object
system_process_attributes (Lisp_Object pid)
{
  return Qnil;
}

In March 2010, this was discussed on the macosx-emacs mailing list, and a patch giving parts of the needed information yielded a screenshot, but it seems that it wasn't finished, nor merged into Emacs.

Update: I got bored and wrote a patch for it. It basically works, but there are some things that it currently doesn't retrieve, notably memory and CPU usage, and command line arguments.

Emacs' process editor (proced) works on many operating systems, but not OSX. Here is why.

Posted Tue 03 Sep 2013 01:51:13 PM BST

In Erlang, if a prōses iz runing cōd frm modyul a wen modyul a iz rēlōdd, it duznt get outomaticli upgrādd tu th nyu vurjhn. Th ōld vurjhn ov th cōd iz kept az long az eni prōses iz yuzing it, nd th prōses iz sed tu b runing "ōld cōd".

Hauever, ōnli won ōld vurjhn iz kept, so if th prōses duznt swich tu th nyu vurjhn bifor th modyul iz rēlōdd fr a secnd tīm, th prōses wil b cild bī th cōd survr. This can b cnfyuzing, az thr iz oftn no trās ov th prōses dīng, nd ēvn if thr iz, yu ōnli get tu nō that th prōses woz cild, but not y.

Wīl chāzing daun a problm rilātd tu this, Ī cām up with this pach tu th cōd survr:

diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 00ad923..c4d5fd6 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1414,6 +1414,7 @@ do_purge(Mod0) ->
 do_purge([P|Ps], Mod, Purged) ->
     case erlang:check_process_code(P, Mod) of
    true ->
+       catch info_msg("Killing ~p for old code from ~p", [P, Mod]),
        Ref = erlang:monitor(process, P),
        exit(P, kill),
        receive

That led mē strāt tu th modyul that woz bēng rēlōdd, nd let mē fix th problm bī enshoring that th prōses swichd tu nyu cōd.

This pach iz probubli not sūtbl fr inclūjhn in th ofishl Erlang/OTP sorsiz, but Ī hōp it can b yusfl wen diveluping.

Hau can yu nō wen th cōd survr cils yur prōses, nd y?

Posted Tue 20 Aug 2013 12:55:49 PM BST

In Erlang, if a process is running code from module a when module a is reloaded, it doesn't get automatically upgraded to the new version. The old version of the code is kept as long as any process is using it, and the process is said to be running "old code".

However, only one old version is kept, so if the process doesn't switch to the new version before the module is reloaded for a second time, the process will be killed by the code server. This can be confusing, as there is often no trace of the process dying, and even if there is, you only get to know that the process was killed, but not why.

While chasing down a problem related to this, I came up with this patch to the code server:

diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl
index 00ad923..c4d5fd6 100644
--- a/lib/kernel/src/code_server.erl
+++ b/lib/kernel/src/code_server.erl
@@ -1414,6 +1414,7 @@ do_purge(Mod0) ->
 do_purge([P|Ps], Mod, Purged) ->
     case erlang:check_process_code(P, Mod) of
    true ->
+       catch info_msg("Killing ~p for old code from ~p", [P, Mod]),
        Ref = erlang:monitor(process, P),
        exit(P, kill),
        receive

That led me straight to the module that was being reloaded, and let me fix the problem by ensuring that the process switched to new code.

This patch is probably not suitable for inclusion in the official Erlang/OTP sources, but I hope it can be useful when developing.

How can you know when the code server kills your process, and why?

Posted Tue 20 Aug 2013 12:55:27 PM BST

So I was dusting off an old Windows XP machine, applying security updates for the last few years, when suddenly I found that the machine would crash with a BSOD a few minutes after boot. The BSOD said that a DRIVER_IRQL_NOT_LESS_OR_EQUAL error had occured in w22nt51.sys. Googling that lead to this article, which revealed that this is a problem in the driver for the Intel 2200BG wireless network card.

Broken network drivers usually lead to chicken-and-egg problems, and that article suggests a way around that, but fortunately I had an Ethernet cable at hand and was not entirely dependent on wireless network. (The cable was in my "give away or throw away" bag, so I'm grateful for my laziness and will reconsider some of the items in it.)

So I solved this by the following steps:

  • Boot into "Safe mode" (without networking).
  • Deactivate the wireless network card in the "System" section of the control panel, to stop the crashes.
  • Boot into "Safe mode with networking" (though a normal boot would probably have been sufficient at this point) and connect the Ethernet cable.
  • Download the new driver from the Intel Download Center.
  • Install the driver.
  • Reboot, to make sure the old driver is not in use (not sure if necessary).
  • Reactive the device in the control panel.

And it works!

So why am I subjecting myself to Windows XP again? Simply because the firmware upgrade tool for my HTC phone requires Windows. Also, now I have the opportunity to test whether my Emacs-based Jabber client works well with Windows. (One of these days…)

Posted Mon 08 Jul 2013 12:14:40 AM BST

Mi komencis scivoli, kial restas tiel multe da monato je la fino de la mono.

Mi ja havas la konteltirojn de la banko, do mi povus rigardi ilin kaj mem sumigi kion mi pagis al kiu, sed tiun laboron la komputilo devus fari por mi, ĉu ne? Pasintjare mi komencis por tio uzi hledger. Tio kio plej logis min al ĝi estis ke ĝi konservas transakciojn en teksta dosiero. Tia dosiero estas facile redaktebla per ajna tekstoredaktilo, kaj se pro iu kialo mi ne plu povus uzi tiun programon, mi ĉiukaze povus legi miajn datumojn.

Iel mi devas enmeti la datumojn en la programon. Mia banko permesas elŝuti konteltirojn en "CSV-formato" (datumeroj disigitaj per komoj). hledger havas funkcion por legi transakciojn el CSV-dosiero, dividi la transakciojn en kategoriojn (ekz. manĝo, lupago, transporto ktp) surbaze de la priskriba teksto kaj dosiero kun reguloj, kaj krei tekstan dosieron laŭ la formato de hledger. La procedo estis la jena:

  1. Elŝuti dosierojn de la banka retejo. Estas po unu dosiero por ĉiu konto (kuranta konto, ŝparkonto, kreditkarto). Por la kuranta konto kaj la ŝparkonto mi povas elekti ajnan periodon ene de la lastaj tri monatoj, sed por la kreditkarto mi povas elekti nur laŭ pagperiodo (t.e. ekde la mezo de unu monato ĝis la mezo de la sekva).
  2. Alinomi la dosierojn. La nomoj de la elŝutitaj dosieroj konsistas el la elŝutodato (ne la dato(j) de la elektita periodo) kaj la kontonumero, sed tiutempe hledger postulis ke la CSV-dosieroj havu nomon kun sama komenco kiel la dosiero kun kategorireguloj, do mi devis permane ŝanĝi la nomon de la dosieroj.
  3. Transformi la dosierojn al hledger-formato.
  4. Enmeti la transformitajn transakciojn en la ĝeneralajn dosierojn, kiuj enhavas transakciojn el pasintaj periodoj. Necesas atenti ke neniu transakcio aperu dufoje en la ĝenerala dosiero. Tio povus okazi se mi malprecize elektis la elŝutperiodojn.

Tiu procedo ja estas komplika, kaj enhavas permanajn paŝojn kiuj estas tedaj kaj erariĝemaj, do mi ekserĉis alian programon por spuri spezojn.

(Se vi ne deziras legi pri la diversaj programoj kiujn mi provis, tuj saltu al la konkludo.)

Gnucash

En pli frua epoko mi uzis Gnucash. Tiam mi konservis paperajn kvitancojn, permane entajpis ilin en Gnucash, kaj de temp' al tempo bilancis komparante al la banka konteltiro. Ĉi-foje mi tamen deziras sistemon pli aŭtomatan.

Gnucash povas importi QIF-dosierojn (kiajn mi ankaŭ povas elŝuti de la banko). Tamen estis pli malfacile enkategoriigi transakciojn: dum la importado, mi povis doni kategorion al ĉiu unuopa transakcio, kaj supozeble Gnucash iom post iom lernas kiel enkategoriigi transakciojn, sed mankis al mi la definitivaj reguloj de hledger: ekzemple transakcioj pri monmaŝinaj elprenoj aperas en la konteltiroj kun la teksto "CASH" sekvata de la adreso de la monmaŝino, kaj sekve mi volus ke ĉiuj transakcioj kun tia priskribo aperu en unu kategorio, sed en Gnucash mi ŝajne devus fidi la lernemon de la programo.

Post la importado, mi elserĉis ĉiujn transakciojn kun tia priskribo, kaj ekhavis liston. En tiu listo mi provis samtempe ŝanĝi la kategorion de ĉiuj transakcioj, sed tio ne eblis — en Gnucash entute ne eblas ŝanĝi pli ol unu transakcion per unu paŝo, kio estas granda malavantaĝo kompare al la situacio en hledger.

Do mi decidis provi aliajn programojn antaŭ ol findecidi kion uzi.

Skrooge

Mi instalis Skrooge kaj donis al ĝi miajn QIF-dosierojn. Skrooge ŝajnis pli promesplena rilate al aŭtomatigo. Ĝi permesas krei regulojn, kun kondiĉoj kaj agoj, kiuj aŭtomate aplikiĝas al transakcioj. Tio estas farata per grafika interfaco, kaj postulas sufiĉe multe da musklakado, sed ĉar sufiĉas tion fari unu fojon, mi imagas ke ne estas tiom terure. (En hledger, mi ofte aldonis novajn regulojn kiam aperis transakcio ne kovrata de jam ekzistanta regulo.)

Resume, la programo ŝajnis sufiĉe taŭga. La interfaco estas plena je funkcioj, por kiujn lerni oni ŝajne bezonas multe da tempo, sed principe tio estas bona afero.

Ekaperis grava manko nur kiam mi faris duan importadon. La programo aŭtomate metas transakciojn en konton kun nomo de la importata dosiero, do mi jam ŝanĝis la nomojn de la kontoj al senchavaj nomoj. Tamen, je la dua importado mi denove havis kontojn kun nurciferaj nomoj, kaj mi tute ne povis trovi manieron movi la transakciojn al jam ekzistantaj dosieroj. Tiu nefleksebleco ĝenis min, do mi daŭrigis mian serĉadon.

KMyMoney

Venis la vico de KMyMoney. Ĝi sen plendoj importis miajn QIF-dosierojn, sed kiom ajn mi serĉis, mi ne sukcesis krei kategoriajn regulojn por importataj transakcioj. Verŝajne la programo ne celas mian uzostilon, sed tiun de malpli pigraj homoj kiuj mem entajpas siajn transakciojn, kaj poste elŝutas konteltiron por certigi ke la banko konsentas kun ili.

Reen al hledger

La rezulto de mia esplorado konfuzis min. Mi volis foriri de mia antaŭa sistemo pro tio, ke ĝi estas tro komplika kaj postulas tro da permana traktado — ĝi aspektas kiel sistemo farita de "nerdo" por "nerdo". Tiuj ecoj igis ĝin tro malfacile uzebla por ke mi havu la emon daŭre enmeti novajn konteltirojn. Mi ankaŭ tion timis, ke mia sistemo eble estis tro ligita al la komputilo en kiu ĝi rulis, tiel ke estus malfacile movi ĝin al alia komputilo se bezonatus. Tial mi serĉis programon celatan al pli vasta celgrupo, sed tio kion mi trovis ne kontentigis min.

Do mi decidis resti ĉe hledger, kaj pliefikigi mian uzon de ĝi:

  • Mi kreis skripton kiu alinomas elŝutitajn dosierojn laŭ la datoj de la entenataj transakcioj. Tiel mi povas facile konservi sinsekvajn konteltirojn en unu dosierujo, kaj per unu rigardo vidi kiujn konteltirojn mi havas kaj kiujn ne.
  • Mi kreis skripton kiu konvertas la elŝutitajn dosierojn al dosieroj laŭ la formato de hledger. (hledger intertempe jam permesas ke la elŝutita konteltirdosiero kaj la regulardosiero havu diversajn nomojn.)
  • Mi kreis skripton kiu kreas dosieron kiu referencas ĉiujn konteltirojn en la dosierujo, tiel ke mi ne plu bezonas mem kunglui la sinsekvajn konteltirojn.

Ankoraŭ la alinomado estas iom malglata; necesas permane alinomi la elŝutitan konteltirdosieron, kaj poste permane ruligi la alinomadan skripton. Mi tamen esperas ke la ĝisnunaj faciligoj povos venki mian pigrecon kaj inspiri min daŭre elŝuti kaj enkategoriigi transakciojn, tiel ke mi havos ĉiujn haveblajn informojn pri kien iris la mono.

Mi komencis scivoli, kial restas tiel multe da monato je la fino de la mono, kaj entreprenis esploron pri librotenaj programoj…

Posted Sun 25 Nov 2012 10:48:04 PM GMT

De temp' al tempo mi vidis ĉe Guglo serĉrezultojn apud kiuj aperas la nomo kaj foto de la aŭtoro. Tio ekinteresis min pro du kialoj. Unue, mi interesiĝas pri kiel komputiloj (ĉi-kaze la serĉilo de Guglo) "legas" retpaĝojn, eltiras el amaso de teksto informojn por uzi en struktura maniero. Iusence la komputilo "komprenas" simplan paĝon de teksto, kvankam tio principe devus postuli veran inteligentecon. Due — pro vanteco, kompreneble.

Mi esploris pri kiel igi mian retejon aperi en serĉrezultoj kun mia nomo kaj foto, kaj rapide trovis ke tiu funkcio estas forte ligita al profiloj ĉe Google+. Tio iom malemigis min pri la afero. Mi efektive tie, sed ne tre ŝatas kiel Guglo+ insistas pri "veraj nomoj", kaj malmulte uzis la servon.

Do, tio devigis min pensi pri la prezo de vanteco ☺

Mi eklegis paĝon ĉe "Retejestraj iloj" de Guglo kiu priskribas kiel fari. Ĝi proponas du opciojn: unue, konekti retpoŝtadreson ĉe la domajno de la retejo kaj mencii la nomon de la aŭtoro en ĉiu paĝo — mi provis tion, sed ne sukcesis igi la testilon rekoni mian nomon — due, krei ligilon al mia profilo ĉe Google+ en ĉiu paĝo kiu aperu kun nomo kaj bildo en serĉrezultoj.

La dua opcio ja kontraŭus la ĝenerale minimumisman aspekton de mia retejo, do mi kreis tian ligilon nur en la ĉefpaĝo. Kaj kelkajn tagojn poste aperis sukceso:

Do, mi ricevis mian vantaĵon, kaj Guglo ricevis ligilon al sia profilservilo. Kiu venkis?…

Mi esploris pri kiel igi mian retejon aperi en serĉrezultoj kun mia nomo kaj foto…

Posted Sun 07 Oct 2012 05:47:03 PM BST

Iuj homoj ŝatas legi sian retpoŝton en Emakso. Kompreneble, Emakso inkluzivas ne nur unu sed du retpoŝtlegilojn, el kiuj la plej funkciriĉa estas Gnus. Uzante Gnus vi povas elekti inter pluraj diversaj formatoj por konservi retpoŝton en la loka disko. Eble vi volas uzi offlineimap por elŝuti retpoŝton el IMAP-servilo, kaj ĉar offlineimap uzas la formaton Maildir, vi eble imagus ke la modulo nnmaildir estas ĝuste tio kion vi serĉas.

Tamen, jam estas dokumentite ke ekzistas kelkaj problemoj pri nnmaildir. Precipe, nnmaildir kaj offlineimap ne konsentas pri kiel marki mesaĝon legita. Normale, offlineimap intersamigas tiajn markojn inter la servilo kaj via loka mesaĝujo, tiel ke mesaĝo kiun vi legis en unu loko fine estos markita kiel legita ankaŭ en la alia loko, sed ĉi-kaze ni malbonsortas; oni devus marki malnovajn mesaĝojn legitaj en ambaŭ lokoj, kio pli-malpli sensencigas la intersamigadon de offlineimap.

Alveninte al tiu punkto, plej multaj homoj rezignas pri nnmaildir kaj instalas en sian komputilon Dovecot, malgranda IMAP-servilo, igas ĝin servi la Maildir-dosierujon per IMAP, kaj konektas Gnus al ĝi per la modulo nnimap. Tio estas tre racia solvo, kaj verŝajne la plej sendolora.

Kompreneble, per tia solvo oni maltrafas ŝancon atingi eternan famon per skribado de kodo, do mi ekfosis en nnmaildir.el. Mi trovis ke ĝi ne atentas tion kion diras la specifo de Maildir pri mesaĝomarkoj, sed konservas markojn laŭ formato propra al Gnus en la Maildir-dosierujo. Tiu formato restos bezonata, ĉar ne ĉiuj markoj, kiujn uzas Gnus, estas prezenteblaj per Maildir-markoj, sed la plej gravaj ("legita", "respondita" kaj "atentenda") povas esti konservitaj en parto de la dosiernomoj de la mesaĝoj. Mi verkis flikaĵon kaj afiŝis ĝin en la cimraporto pri tiu ĉi funkcio. Ekde 2012-09-05 ĝi estas inkluzivita en la ĉefa branĉo de Gnus, kaj la ŝanĝo aperis en GNU Emacs 24.3.

Do, jen ĝi, preta por testado. Ŝajne estas iuj problemetoj, tiel ke ĝi iam ne markas mesaĝon legita kvankam ĝi devus, sed ĝis nun ĝi ŝajne ne kutimas manĝi ies retpoŝton.

Ne sufiĉe rapida

Restas pliaj farindaĵoj pri nnmaildir; ĝis nun miaj ŝanĝoj nur celis korektan funkciadon, do la sekva paŝo estas igi ĝin rapida. Ĝi funkcias sufiĉe bone por retpoŝtujoj kun miloj da mesaĝoj, sed kiam temas pri dekmiloj startado de Gnus longe daŭras. (La logika solvo por tio estas neniam eliri el Gnus, sed…) Mi ankoraŭ ne tute certas pri ĉio ĉi, sed mi pudris informmesaĝojn sur la kodon kaj ĝis nun ili sugestas ke la plejparto de la tempo uziĝas en nnmaildir--grp-add-art. Se mi ĝuste legas tiun kodon, ĝi ŝajne enmetas ĉiun artikolon, unu post alia, en laŭordan liston nomatan nlist. Evidente, en la plej malbona kazo tio havas kvadratan tempokomplikecon. Miaj pensoj ĉi-momente estas jenaj:

  • Ĉu tio ĉi bezonas esti laŭorda listo? (Aliaj partoj de la kodo faras operaciojn je laŭvicaj partoj de tiu ĉi listo, sed eble ni povus uzi arbon aŭ ion tian…)
  • Ĉu ni vere bezonas teni ĉion ĉi en la memoro? Temas pri datumoj pri ĉiu mesaĝo en la dosierujo; plej verŝajne ni la plejmulton neniam uzos.

Jen la nuna stato. Mi plu laboros pri tio ĉi, dum liberaj tempoj.

nnmaildir, la realigo de Maildir en Gnus, ne konsentas kun offlineimap pri kiel aspektas legita mesaĝo. Mi provas ripari tion, kaj ankaŭ aliajn problemojn pri nnmaildir.

Posted Thu 13 Sep 2012 09:51:25 AM BST

De kiu vi lernis Esperanton? Kaj de kiu lernis tiu persono Esperanton? Kaj de kiu…

Mi ekhavis ideon, ke estus interese "spuri" kiel scio de Esperanto iris tra homoj dum la historio, kaj tiel krei kvazaŭ parencaran arbon. Kompreneble ekzistas malklaraj kazoj — mi mem eklernis Esperanton per letera kurso enretigita; ĉu en tiu kazo oni konsideru la verkinton de tiu letera kurso mia "instruisto", aŭ ĉu mi estas "memlerninta"? Kaj tiel plu.

Ĉu iu simila esploro jam ekzistas?

De kiu vi lernis Esperanton? Kaj de kiu lernis tiu persono Esperanton? Kaj de kiu…

Posted Tue 28 Aug 2012 01:08:43 AM BST