23. lokakuu 2012, 19:54

WebOodi-aikataulut orgiin

Itä-Suomen yliopiston weboodissa alkaa olla aika usein kurssi-infot hyvässä kunnossa, ja nyt on myös joensuulaisille olemassa tuota lukkaria, joka on hyvä ratkaisu. No, olisi, jos matematiikat saisi kanssa listoille. Ja valintani on muutenkin org-mode, joten sen kanssa on mentävä. Vaihteeksi uutta Python-koodinpätkää: oodista kopypastettuja aikatauluja org-aikaleimoiksi.

Syöte on tämänlaista:

29.10.-17.12.12
    ma 16.00-18.00 
31.10.-19.12.12
    ke 08.00-10.00 
01.11.12
    to 08.00-10.00 
09.11.12
    pe 10.00-12.00 

Eli joko on yksittäisiä aikoja tai on isompia välejä, joiden ajat toistuvat viikottain. Org-mode ottaa vastaan kuitenkin vain tämänlaisia aikaleimoja:

<2012-10-15 Mon 16:00-18:00>
<2012-10-29 Mon 16:00-18:00 +1w>

Eli yksittäisiä päiviä, joilla on mahdollisesti kellonaika. Org osaa tehdä noita toistuvia aikoja (jälkimmäisessä +1w viittaa viikottaiseen tapahtumaan).

Pythonin kanssa taistoon

Ensin puntaroin tekeväni tämän Elispillä, koska kuitenkin org-ympäristö on ainut, jossa tätä tarvitsee. Ajattelin, että elispin aika ja paikka on joskus myöhemmin. Arkkitehtuuri sovellukselleni on tyypillinen:

  • lue tiedostosta tai standardi-inputista rivit ylös
  • (lukee tosin kaiken kerralla koska laiskat tietorakenteet eivät pythonissa loista)
  • rivit annetaan delegointifunktiolle, joka päättää, onko rivipari aikajakso vai yksittäinen päivä:
    • jos jakso, niin pura pythonin päivämäärätyökaluilla jakso joukoksi yksittäisiä päiviä, ja passaa seuraavalle:
    • jos päivä, niin käännä se erinäisten kikkastelujen jälkeen org-aikaleimaksi.

Joitain otteita koodista voisi kaiketi antaa. Sisään mennään tämännäköisellä hirvityksellä. Pythonin fileinput on loistava, vaikka se vaatiikin kaksi C-d:tä lopettaakseen.

if __name__ == '__main__':
    import fileinput
    inputd = [line.strip() for line in fileinput.input() if line.strip() != '']
    finished = [do_line(date, time)
                for date, time
                in zip(inputd[::2], inputd[1::2])]
    print '\n'.join(finished)

Funktio do_line toimii delegoijana. Mennäänpä nyt päivämääriin. Tämä funktio do_date hoitaa yksittäistapauksen. Toinen apufunktio, toDate, on ollut jo käytössä delegaatissa (ankkatyyliin jos saadaan parsintapoikkeus niin tulkitaan teksti intervalliksi), joten do_date saa datan puoliksi python-olioina ja toinen puoli on tekstiä.

def toDate(string):
    """ %d.%m.%y -> DateTime. """
    return datetime.datetime.strptime(string, "%d.%m.%y")
def do_date(date, time):
    """ convert one date, time pair to org """
    return "<" + date.strftime("%Y-%m-%d") + " " + runtime(time) + ">"

Tekstipuoli käännetään runtime-funktiolla, joka on vain merkkijonokäpistelyä. Viikonpäivät suomesta englantiin ja semmoista. Intervalli oli hieman kiinnostavampi. Sen saa palautettua yksittäisiksi päivämääriksi verraten helposti datetime.timedelta -luokan voimin:

def do_intervalled_line(interval, time):
    """ interval is of form "%d.%m.-%d.%m.%y". """
    begin, end = interval.split('-')
    # 'begin' may get the same year as end... I smell trouble
    begin = begin + end.split('.')[-1]
    begin = toDate(begin)
    end = toDate(end)
    acc = []
    week = datetime.timedelta(days=7)
    while begin <= end:
        acc.append(do_date(begin, time))
        begin = begin + week
    return acc

Ilmassa on pientä hakkailua, joka tuskin kestää lähempää tarkastelua. Homma lähti kuitenkin ensipolkaisulla käyntiin, joka on aina iloinen yllätys.

Jatkokehittelyä

Tässä yhden hengen katselmoinnissa tosin huomasin, että listoja pitää vielä vähän tasata: testisyötteeni oli kaikki intervalleja ja saattaa paukkua, jos syötteessä on seassa yksittäisiä päiviä. Tai ainakin siltä vähän näyttäisi.

Koodi käyttöön

Vimissä on tyylikäs !-komento, jolle voi ‘putkittaa’ tekstivalinnan, ja putken päästä tuleva tavara korvaa valinnan. Esimerkiksi !sort tekee valinnalle sitä, miltä kuulostaakin. Emacsin vastaavaa en heti hoksannutkaan, mutta onneksi Evil hoiti homman kotiin. Googlailujen jälkeen selvisi, että Emacsin oma tapa on C-u M-|. Saapa olla jatkossakin.

Emacsista toimintakuva (kun kirjoitan tätä blogiviestintapaista):

Hassusti se tuo muotoilut kopioidessaan. Kiva sinänsä blogia tehtaillessaan, mutta jossain vaiheessa tuon on hajottava johonkin. Onhan?

Seuraavalla kerralla voisin kirjoittaa org-agendan ja conkyn yhteensulautumista, jolla korvasin Rainlendarin kokonaan. Koodi ei siellä ole niin nättiä, että…

Tageja: , ,

---
---

---

Aiheen vierestä