Revision 4b4a373ca686431f09b1dd1125e6ac1f7dd26bb7 authored by David Gowers on 15 September 2010, 04:20:34 UTC, committed by David Gowers on 15 September 2010, 04:20:34 UTC
1 parent 0aab781
Raw File
jbofacki.py
#!/usr/bin/env python
# Accept lojban input, tab-complete words and -raf-si,
# feed jbofihe or camxes.
# Provide quick colorized word lookups,
# approximate gloss/notes/def search,
# lujvo analysis.
#
# Req: Python 2.5, readline. Also a valid makfa-cli database (run 'makfa update' to get one)
# or use the sample database provided.
#
# Works on Linux or Windows (other platforms may work but haven't been tested.).
#
# Bugs/Lacking aspects:
#
# XXX remove locking.
# XXX define a matches-displayer that shows word type (or class, in case of cmavo)
# XXX parentheses handling is incomplete in some circumstances
# XXX some python functions like sum, dict, etc show up in the completion list
# XXX colorize jbofihe (and camxes?) output
# XXX completion could be context sensitive (some way to prioritize terminators when a
#     scope is open?)
# XXX glosses should be completeable when the input string contains '/'
# XXX wildcards in search (shell style)
# XXX quoting in search (extract quoted sections first. disallow searching for '"' lerfu
# XXX independence from makfa (build our own DB)
# XXX conform to FDO standard for config location
# XXX configure via cmdline.
# XXX sort lujvo < gismu < cmavo
# XXX ignore everything after '#' to allow inline comments (still write the full input to log)
# XXX autopagically use matter for >N(N=20) results
# XXX ... except when redirections '>' are in a query.
# XXX test lujvo analysis more fully.
# XXX possibly SELMAHO? should produce also an item pointing at BPFK pages.
# XXX configurable DB location
#
#    la donri
#        ce'e
#    la samselpla pagbu .e le ve ciksi
#
#        pe'e je
#
#    la .tueis. ce la .tomoj. ce la aidalgol
#        ce'e
#    le darsi gasnu
#
#        pe'e je
#
#    la .djancak.
#        ce'e
#    le nu cipra ci'e la canko kei ku
#
# ckire fa mi
#
# ^ (one bridi, nicely formatted, with afterthought termsets.)


import os
import readline
import rlcompleter
import sys
import re

##### se cuxna
#
#
rolterciha = ''
notcyterciha = ''
camxes = ['java','-jar',os.path.expanduser ('~/lojban/lojban_peg_parser.jar')]
jbofihe = ['jbofihe','-x','-se']
fadyselcuha = jbofihe
jarco_tuha_le_sidju = True
na_skari = False
vinriha = 'less'
mipri_liste = []

#####
#
#

WINDOWS = False
import platform
if 'indows' in platform.system():
    WINDOWS = True


def tcidu_le_selcuha_vreji ():
    global rolterciha
    global notcyterciha
    global camxes
    global jbofihe
    global fadyselcuha
    global vinriha
    global jarco_tuha_le_sidju
    global na_skari
    global mipri_liste
    import ConfigParser
    from ConfigParser import DEFAULTSECT as NOHO
    ro_kraselcuha = {
      'logfile' : "~/jbofacki-log.rst",
      'notefile' : "~/jbofacki-notci.rst",
      'disable color' : 'no',
      'camxes path' : './lojban_peg_parser.jar',
      'camxes options' : '',
      'jbofihe path' : './jbofihe',
      'jbofihe options' : '-x -se',
      'default parser' : 'jbofihe',
      'show help at startup' : 'yes',
      'word type blacklist' : '',
      'pager' : 'less',
    }
    if not WINDOWS:
        ro_kraselcuha ['jbofihe path'] = 'jbofihe' # zmiku facki du'o la'e zoi .env. PATH .env.
        # pau xu galfi zoi .tercu'a. pager .tercu'a.
    tc = ConfigParser.ConfigParser (ro_kraselcuha)
    le_mohu_tcidu = tc.read (['./jbofacki.cfg', os.path.expanduser ('~/.jbofacki.cfg')])
    if len (le_mohu_tcidu) == 0:
        # co'a paroi vreji le selcuha
        if WINDOWS:
            vv = open ('./jbofacki.cfg','wb')
        else:
            vv = open (os.path.expanduser ('~/.jbofacki.cfg'), 'wb')
        tc.write(vv)
        vv.close()
    del le_mohu_tcidu
    rolterciha =  os.path.expanduser (tc.get (NOHO, 'logfile'))
    notcyterciha = os.path.expanduser (tc.get (NOHO, 'notefile'))
    na_skari = tc.getboolean ( NOHO, 'disable color')
    camxes = ['java', '-jar', os.path.expanduser (tc.get (NOHO, 'camxes path'))]
    if len (tc.get (NOHO, 'camxes options')) > 0:
        camxes.extend (tc.get (NOHO, 'camxes options').split (' '))
    jbofihe = [os.path.expanduser (tc.get (NOHO, 'jbofihe path'))]
    if len (tc.get (NOHO, 'jbofihe options')) > 0:
        jbofihe.extend (tc.get (NOHO, 'jbofihe options').split (' '))
    fadyselcuha = tc.get (NOHO, 'default parser')
    if fadyselcuha == 'jbofihe':
        fadyselcuha = jbofihe
    elif fadyselcuha == 'camxes':
        fadyselcuha = camxes
    else:
        raise ValueError ('%r as a choice of default parser is invalid' % fadyselcuha)
    jarco_tuha_le_sidju = tc.getboolean (NOHO, 'show help at startup')
    mipri_liste = tc.get (NOHO, 'word type blacklist')
    mipri_liste = mipri_liste.split(';')
    mipri_liste = [p for p in mipri_liste if p in ('cmene',
                                                   "fu'ivla",
                                                   'cmavo',
                                                   'experimental',
                                                   'experimental cmavo',
                                                   'experimental gismu',
                                                   'gismu',
                                                   'lujvo')]
    vinriha = [tc.get (NOHO, 'pager')]
    if WINDOWS:
        vv = open ('./jbofacki.cfg','wb')
    else:
        vv = open (os.path.expanduser ('~/.jbofacki.cfg'), 'wb')
    tc.write(vv)
    vv.close()



tcidu_le_selcuha_vreji ()

#####

# le krasi du zoi .python.
#
# > from pygments.console import codes
# > print codes
#
# .python.

codes = {'': '',
'yellow': '\x1b[33;01m',
'blink': '\x1b[05m',
'lightgray': '\x1b[37m',
'underline': '\x1b[04m',
'darkyellow': '\x1b[33m',
'blue': '\x1b[34;01m',
'darkblue': '\x1b[34m',
'faint': '\x1b[02m',
'fuchsia': '\x1b[35;01m',
'black': '\x1b[30m',
'white': '\x1b[01m',
'red': '\x1b[31;01m',
'brown': '\x1b[33m',
'turquoise': '\x1b[36;01m',
'bold': '\x1b[01m',
'darkred': '\x1b[31m',
'darkgreen': '\x1b[32m',
'reset': '\x1b[39;49;00m',
'standout': '\x1b[03m',
'darkteal': '\x1b[36;01m',
'darkgray': '\x1b[30;01m',
'overline': '\x1b[06m',
'purple': '\x1b[35m',
'green': '\x1b[32;01m',
'teal': '\x1b[36m',
'fuscia': '\x1b[35;01m'}

if WINDOWS:
    # cancel color codes on win; API calls are needed :|
    for k,v in dict(codes).items():
        codes[k] = ''

tersuhi_skari = codes['purple']
valsi_skari = codes['white']
klesi_skari = codes['darkgreen']
rafsi_skari = codes['teal']
tcita_skari = codes['brown']
cmavo_skari = codes['blue']
gismu_skari = codes['darkgreen']
lujvo_skari = codes['green']
jorne_skari = codes['darkgreen']
troci_skari = codes['red']
selmaho_skari = codes['darkred']
fuhivla_skari = codes['fuchsia']
pinka_skari = codes['darkgray']
xruti = codes['reset']

# cpacu le jorne la makfa
manri_jorne = {'A': ((14, 6),),
            'BAI': ((9, 6),),
            'BAhE': ((19, 11),),
            'BE': ((5, 7),),
            'BEI': ((5, 7),),
            'BEhO': ((5, 7),),
            'BIhE': ((18, 5),),
            'BIhI': ((14, 16),),
            'BO': ((5, 3), (15, 6), (18, 17),),
            'BOI': ((18, 6),),
            'BU': ((17, 4),),
            'BY': ((17, 2),),
            'CAI': ((13, 4),),
            'CAhA': ((10, 19),),
            'CEI': ((7, 5),),
            'CEhE': ((14, 11), (16, 7),),
            'CO': ((5, 8),),
            'COI': ((6, 11), (13, 14),),
            'CU': ((9, 2),),
            'CUhE': ((10, 24),),
            'DAhO': ((7, 13),),
            'DOI': ((13, 14),),
            'DOhU': ((13, 14),),
            'FA': ((9, 3),),
            'FAhA': ((10, 2),),
            'FAhO': ((19, 15),),
            'FEhE': ((10, 11),),
            'FEhU': ((9, 5),),
            'FIhO': ((9, 5),),
            'FOI': ((17, 6),),
            'FUhA': ((18, 16),),
            'FUhE': ((19, 8),),
            'FUhO': ((19, 8),),
            'GA': ((14, 5),),
            'GAhO': ((14, 16),),
            'GEhU': ((8, 3),),
            'GI': ((14, 5),),
            'GIhA': ((14, 3),),
            'GOI': ((8, 3),),
            'GOhA': ((7, 6),),
            'GUhA': ((14, 3),),
            'I': ((19, 2),),
            'JA': ((14, 3),),
            'JAI': ((9, 12),),
            'JOI': ((14, 14),),
            'JOhI': ((18, 15),),
            'KE': ((5, 5),),
            'KEI': ((11, 1),),
            'KEhE': ((5, 5),),
            'KI': ((10, 13),),
            'KOhA': ((7, 1),),
            'KU': ((6, 2), (10, 1),),
            'KUhE': ((18, 6),),
            'KUhO': ((8, 1),),
            'LA': ((6, 2),),
            'LAU': ((17, 14),),
            'LAhE': ((6, 10),),
            'LE': ((6, 2),),
            'LEhU': ((19, 9),),
            'LI': ((18, 5),),
            'LIhU': ((19, 9),),
            'LOhO': ((18, 17),),
            'LOhU': ((19, 9),),
            'LU': ((19, 9),),
            'LUhU': ((6, 10),),
            'MAI': ((18, 19), (19, 1),),
            'MAhO': ((18, 6),),
            'ME': ((5, 10), (18, 1),),
            'MEhU': ((5, 11),),
            'MOI': ((5, 11),),
            'MOhE': ((18, 18),),
            'MOhI': ((10, 8),),
            'NA': ((14, 3), (15, 7),),
            'NAI': ((14, 3), (15, 7),),
            'NAhE': ((15, 4),),
            'NAhU': ((18, 18),),
            'NIhE': ((18, 18),),
            'NIhO': ((19, 3),),
            'NOI': ((8, 1),),
            'NU': ((11, 1),),
            'NUhA': ((18, 19),),
            'NUhI': ((14, 11), (16, 7),),
            'NUhU': ((14, 11),),
            'PA': ((18, 2),),
            'PEhE': ((14, 11),),
            'PEhO': ((18, 6),),
            'PU': ((10, 4),),
            'RAhO': ((7, 6),),
            'ROI': ((10, 9),),
            'SA': ((19, 13),),
            'SE': ((5, 1), (9, 4),),
            'SEI': ((19, 12),),
            'SEhU': ((19, 12),),
            'SI': ((19, 13),),
            'SOI': ((7, 8),),
            'SU': ((19, 13),),
            'TAhE': ((10, 9),),
            'TEI': ((17, 6),),
            'TEhU': ((18, 15),),
            'TO': ((19, 12),),
            'TOI': ((19, 12),),
            'TUhE': ((19, 2),),
            'TUhU': ((19, 2),),
            'UI': ((13, 1),),
            'VA': ((10, 2),),
            'VAU': ((14, 9),),
            'VEI': ((18, 5),),
            'VEhA': ((10, 5),),
            'VEhO': ((19, 5),),
            'VIhA': ((10, 7),),
            'VUhO': ((8, 8),),
            'VUhU': ((18, 5),),
            'XI': ((18, 13),),
            'Y': ((19, 14),),
            'ZAhO': ((10, 10),),
            'ZEI': ((4, 6),),
            'ZEhA': ((10, 5),),
            'ZI': ((10, 4),),
            'ZIhE': ((8, 4),),
            'ZO': ((19, 10),),
            'ZOI': ((19, 10),),
            'ZOhU': ((16, 2), (19, 4),)}

# .ije cpacu le kuspe mulno datni la makfa

mulno_selmaho = {'BE': 'BEhO',
                 'PA': 'BOI',
                 'BY': 'BOI',
                 'COI': 'DOhU',
                 'DOI': 'DOhU',
                 'FIhO': 'FEhU',
                 'GOI': 'GEhU',
                 'NU': 'KEI',
                 'KE': 'KEhE',
                 'LE': 'KU',
                 'LA': 'KU',
                 'PEhO': 'KUhE',
                 'NOI': 'KUhO',
                 'LU': 'LIhU',
                 'LI': 'LOhO',
                 'LAhE': 'LUhU',
                 'NAhE+BO': 'LUhU',
                 'ME': 'MEhU',
                 'NUhI': 'NUhU',
                 'SEI': 'SEhU',
                 'SOI': 'SEhU',
                 'TO': 'TOI',
                 'TUhE': 'TUhU',
                 'VEI': 'VEhO'}

def facki_fi_lo_valsi (valsi):
    return [v in ro_valsi for v in valsi]

def galfi_le_porsi (valsi, se_porsi = 'cmene'):
    valsi = list (valsi)
    if se_porsi == 'cmene':
        valsi.sort()
    elif se_porsi == 'rafsi':
        valsi.sort(key = lambda v:"".join(valsi_datni['rafsi']))
    else:
        valsi.sort(key = lambda v:valsi_datni[se_porsi])
    return valsi

tersuhi_rex = re.compile ('([a-z][0-9])')
pinka_rex = re.compile ('([([][^\])]+[)\]])')
valsi_rex = re.compile ('(\{[a-z \']+\})')
se_ciska_rex = re.compile ('("[^"]+")')
selmaho_rex = re.compile ('([A-Zh]+)(\\.+)?([A-Zh]+)?') #cumki srera sera'a eg LU.. LI'U
selmaho_cfari_rex = re.compile ('([A-Zh]+)')
selmaho_pagbu_rex = re.compile ('([A-Zh]+)(\*)?([0-9a-z]+)?')
jorne_rex = re.compile('(http://dag.github.com/cll/[0-9/]+)')


def skagau (se_ciska, rex, skari):
    if not se_ciska:
        return ''
    return rex.sub (skari + '\\1' + xruti, se_ciska)

def klesi_skagau (klesi):
    klesi = klesi.replace ("experimental", troci_skari + "experimental" + xruti)
    klesi = klesi.replace ("lujvo", lujvo_skari + 'lujvo' + xruti)
    klesi = klesi.replace ("gismu", gismu_skari + 'gismu' + xruti)
    klesi = klesi.replace ("cmavo", cmavo_skari + 'cmavo' + xruti)
    klesi = klesi.replace ("fu'ivla", fuhivla_skari + "fu'ivla" + xruti)
    return klesi

def selmaho_skagau (selmaho):
    if not selmaho:
        return ''
    if '...' in selmaho:
        return "%s%s%s...%s%s%s" % (selmaho_skari, selmaho[:selmaho.find('.')], xruti,
                                    selmaho_skari, selmaho[selmaho.rfind('.')+1:], xruti)
        #return selmaho_rex.sub (selmaho_skari + '\\1' + xruti + '\\2' + selmaho_skari + '\\3' + xruti, selmaho)
    return selmaho_skari + selmaho + xruti

def rafsi_skagau (rafsi):
    if len(rafsi) == 0:
        return ''
    return rafsi_skari + "\t" + "\t".join(rafsi) + xruti

def tersuhi_skagau (tersuhi):
    te_pruce = []
    zasni = []
    for ts, ts_tcita in tersuhi.items():
        #print ts, ';',ts_tcita
        for da, de in ts_tcita:
            if da and (not de):
                zasni.append (' %s%r%s' % ( tcita_skari, da,
                                            xruti))
            else:
                zasni.append ('%s%r%s in sense %s%r%s' % (tcita_skari,
                                                da, xruti,
                                                tcita_skari,
                                                de, xruti))
        te_pruce.append (("%sx%d%s " % (tersuhi_skari,
                                         ts,xruti) +
                                         ", ".join(zasni)))
    return "; ".join(te_pruce)


def sidju ():
    s = """\t\t%Wla jbofacki%/
    \t\t===========

    "le broda lo brode noi gerku ku selbri"
    \t\t-> %Wget verbose jbofihe output.%/
    "!"
    \t\t-> %Wget camxes output WRT the previous input%/.
    "le broda lo brode noi gerku ku selbri?" or
    "?le broda lo brode noi gerku ku selbri"
    \t\t-> %Wshow colored definitions
    \t\t   of all unique valsi in that input
    \t\t   (%/%Gbroda brode gerku noi
    \t\t   ku le lo selbri%/%W)%/
    "broda CAhA -raf- -bro-?"
    \t\t-> %Wsimilar to above, demonstrating
    \t\t   cmavo class expansion:%/
    \t\t        %GCAhA%/ -> %Gca'a ka'e nu'o pu'i%/
    \t\t        %G-raf-%/ -> %Grafsi%/ (rafsi expansion) also occurs
    "crystal/" | "/crystal"
    \t\t-> %Wsearch through all fields for 'crystal'%/
    \t\t   (natlang or lojban word fragments)
    ":ni x1 is filled with ce'u if ce'u isn't explicitly specified."
    \t\t-> %WWrite the above text "ni x1[...]" to ~/jbofacki-notci.rst%/
    "??"-> %WShow this help%/\t":?"-> %Wshow the last 10 lines of notes.%/
    "clatcebrajvo%"-> %WLujvo analysis (jvokatna). apparent non-lujvo are ignored.%/
    Tab-completion of lojban words, -raf-si, selmaho is available at all times,
    as are the usual Readline niceties.
                    *** Type Ctrl+D to exit. ***
    ------
    (word lookup requires a makfa db. Installing makfa-cli and
     running 'makfa update' should make one.)
    (remember to edit the variable definitions in the 'se cuxna'
    section of the jbominde script file.
    You can configure jbofihe and camxes parameters,
    the path to camxes, whether camxes or jbofihe is default,
    and whether this help is shown at startup.)
    ------...
    .i ai cfari
    """

    s = s.replace ('%W', codes['white'])
    s = s.replace ('%G', codes['green'])
    s = s.replace ('%/', xruti)
    print (s)

def tersuhi_sisku (datni, valsi):
    tersuhi = datni['places']
    for tersuhi, tcita in tersuhi.items():
        for a, b in tcita:
            if valsi in a:
                return True
            if not b:
                continue
            if valsi in b:
                return True
    return False

def xu_na_jarco (valsi):
    t = valsi_datni[valsi]['type']
    for m in mipri_liste:
        if m in t:
            return True
    return False

def ro_selkai_sisku (pagbu):
    mipri = set ()
    ni_mipri = 0
    te_pruce = []
    for cmene, datni in valsi_datni.items():
        mapti_kau = True
        for p in pagbu:
            tohe = False
            if p.startswith ('-'):
                tohe = True
                p = p[1:]
            jehu = not (p in cmene or (datni['notes'] and p in datni['notes']) \
                   or p in datni['definition'] or tersuhi_sisku (datni, p)
                   or (datni['selmaho'] and p in datni['selmaho']) or
                   p in datni['type']
                   )
            if tohe:
                jehu = not jehu
            if jehu:
                mapti_kau = False
            if xu_na_jarco (cmene):
                # le vi valsi ku nenri le mipri liste
                mipri.add (datni['type'])
                ni_mipri += 1
                mapti_kau = False;
                break;

        if mapti_kau == True:
            te_pruce.append (cmene)
    return te_pruce, ni_mipri, mipri

def jarco (valsi, se_porsi = 'cmene'):
    te_pruce = []
    # remove
    ro_rapli = [v for v in valsi if valsi.count(v) > 1]
    for r in ro_rapli:
        while valsi.count(r) > 1:
            valsi.remove (r)
    valsi = galfi_le_porsi (valsi, se_porsi)
    # banro le selma'o ja rafsi
    valsi2 = []
    for v in valsi:
        if selmaho_rex.match(v):
            selmaho_zasni = []
            if '..' in v:
                purci = v[:v.find('.')]
                balvi = v[v.rfind('.')+1:]
            else:
                purci = v
                balvi = None
            for v2 in (purci, balvi):
                if not v2:
                    continue
                for cmene, datni in valsi_datni.items():
                    if not datni['selmaho']:
                        continue
                    selmaho = datni['selmaho']

                    if selmaho:
                        selmaho = selmaho.replace('*','')
                        if v2 == selmaho or selmaho.startswith (v2):
                            # UI -> UI[12345678][abc]?
                            # UI3 facki [UI3a, UI3b, ...]
                            selmaho_zasni.append (cmene)
            selmaho_zasni.sort (key = \
                                lambda v: valsi_datni[v]['selmaho'].replace('*', '') +\
                                          v)
            valsi2.extend (selmaho_zasni)
        elif len(v) in (5,6) and v.startswith ('-') and v.endswith ('-'):
            rafsi = v[1:-1]
            for cmene, datni in valsi_datni.items():
                    if rafsi in datni['rafsi']:
                        valsi2.append (cmene)
                        break; # no more than one valsi should be assigned the same rafsi
        else:
            valsi2.append (v)
    for v in valsi2:
        try:
            datni = valsi_datni[v]
        except KeyError:
            te_pruce.append ((v, selmaho_skari + 'na facki' + xruti))
            continue
        se_valsi = datni['definition']
        se_valsi = skagau (se_valsi, pinka_rex, pinka_skari)
        se_valsi = skagau (se_valsi, tersuhi_rex, tersuhi_skari)
        # skagau [a-z][0-9]
        # skagau (qualifiers)
        notci = datni['notes']
        notci = skagau (notci, pinka_rex, pinka_skari)
        notci = skagau (notci, valsi_rex, jorne_skari)
        notci = skagau (notci, tersuhi_rex, tersuhi_skari)
        rafsi = rafsi_skagau (datni['rafsi'])
        tersuhi = tersuhi_skagau (datni ['places'])
        # skagau {valsi}
        jorne = ''
        selmaho = datni['selmaho']
        if selmaho:
            cfari = selmaho_cfari_rex.match (selmaho).expand('\\1')
            if cfari in manri_jorne:
                jorne = ", ".join(['<http://dag.github.com/cll/%d/%d/>' % (a,b) for a,b in manri_jorne[cfari]])
                jorne = skagau (jorne, jorne_rex, jorne_skari)
        if selmaho in mulno_selmaho:
            selmaho += '...' + mulno_selmaho[selmaho]
        selmaho = selmaho_skagau (selmaho)
        klesi = klesi_skagau (datni['type'])
        zasni = " ".join ([klesi,selmaho,rafsi])
        te_pruce.append ( (v, zasni, se_valsi, tersuhi, notci, jorne))
    return te_pruce

def selmaho (valsi_ja_selmaho):
    if type(valsi_ja_selmaho) == list or valsi_ja_selmaho in ro_valsi:
        valsi = valsi_ja_selmaho
        if type(valsi) != list:
            valsi = [valsi]
        valsi = facki_fi_lo_valsi (valsi)
        # XXX look up all the valsi, return their selmaho
    else:
        raise NotImplementedError ('selmaho klesi zgana')
        # XXX look up all the selmaho in the specified class

def jarco_xire (tcita, ):
    j = tcita
    for da in j:
        print ('')
        print (codes['white'] + da[0] + xruti
              + "\t" + da[1])
        for i, de in enumerate (da[2:]):
            if len(de) > 1:
                print ("\t" + de)
    print ('')

valsi_datni = None
ro_valsi = None
mulno_selcmi = {}

def tcidu_datni ():
    global valsi_datni
    global ro_valsi
    from cPickle import load
    f = open (os.path.expanduser('~/.makfa.dump'), 'rb')
    valsi_datni = load(f)
    ro_valsi = valsi_datni['order']
    valsi_datni = valsi_datni['entries']
    for valsi in ro_valsi:
        mulno_selcmi[valsi] = True

    for valsi, datni in valsi_datni.items():
        if datni['rafsi'] != None and len(datni['rafsi']) > 0:
            for r in datni['rafsi']:
                mulno_selcmi["-%s-" % r] = True
        if datni['selmaho'] and datni['selmaho'] not in mulno_selcmi:
            mulno_selcmi[datni['selmaho']] = True


PYTHON_MINDE         = 0x1
JMINA_LE_NOTCI       = 0x2
DRATA_JUFYJMI        = 0x4
JARCO_LE_KA_SE_VALSI = 0x8
CISKA                = 0x10
TCIDU                = 0x20


def sepuhe_jimpe (sepuhe):
    # notice :?!
    # notice >< redirect (<=1ro) -- this is always "send the results of query X(lvalue) to file Y(rvalue)"
    # strip # from the sentence-to-parse while logging the full input.
    # return what to log, what to parse, flags,  and extra data (redirect target, currently)
    #
    sepuhe = sepuhe.strip()
    if sepuhe.strip() == '$':
        return '$ -> entered python console', None, PYTHON_MINDE, None
    # zoi .ly. ? .ly. na nitcu fi le nu zoi .ry. > .ry. lerfu
    # zgana le se pruce ja te pruce galfi
    # <> (< purci)
    # zgana le drata jufyjmi tcita
    # "!"
    # zgana le valsi ciksi tcita
    # "?"

purci = None

mulno_selcmi = {}

stela = None

def mapti_gismu (lujvo, vi):
    # XXX masno
    pagbu = lujvo[vi:vi+5]
    if (len(pagbu) < 5):
        return False
    satci = False
    pagbu = lujvo[vi:vi+5]
    if vi == (len(lujvo) -5) and len (lujvo) > 5:
        satci = True
    else:
        if lujvo[vi+4] not in 'yr':
            return False # not a valid gismu-in-lujvo form
        pagbu = pagbu[:-1]

    for valsi in ro_valsi:
        if len(valsi) == 5 and valsi_datni[valsi]['type'] == 'gismu':
            if satci:
                if valsi == pagbu:
                    return valsi
            else:
                if valsi[:4] == pagbu:
                    return valsi
    return False

def lujvo_katna (lujvo):
    #
    # cases like this {terdi'ajbari}
    # strictly require distinction between GISMU before word end and GISMU
    # at word end. The latter can preserve it's final V, the former must have a J
    C = 'bcdfgjklmnprstvxyz'
    V = 'aeiou'
    H = "'"
    J = 'yrm' # m is usually not valid.

    # CVV CV'V CVC CCV
    #
    # gismu : CCVCV | CVCCV
    i = 0

    if lujvo[-1] in C or lujvo[-1] == 'y':
        raise ValueError ('toldra vlatai')

    tepuhe = []

    while i < len(lujvo):
        #print "cfari lerfu %r" % lujvo[i]
        if lujvo[i] not in C:
            raise ValueError ('cizra lujvo? [djica C]')
        i+=1
        if lujvo[i] in C:
            i+=1
            if lujvo[i] in V:
                if i < len(lujvo) - 1 and lujvo[i+1] in C and lujvo[i+2] in (V+J): # CCVCV gismu
                   if mapti_gismu (lujvo, i-2):
                       i+= 3
                       zasni = lujvo[i-5:i]
                       if zasni[-1] not in V:
                           tepuhe.append (zasni[:-1])
                           tepuhe.append (zasni[-1])
                       else:
                           tepuhe.append (zasni)
                       continue
                i+=1
                tepuhe.append (lujvo[i-3:i])
                continue # XXX any hyphenation needed here? yes,
            raise ValueError ('cizra lujvo? [djica V]')
        elif lujvo[i] in V:
            i+=1
            if lujvo[i] in V: # what follows can't be a gismu end
                i+=1
                tepuhe.append (lujvo[i-3:i])
                # hyphenation may be needed
                if i < len(lujvo) and lujvo[i] in 'mr': #y can't follow a V
                    tepuhe.append (lujvo[i])
                    i+=1
                continue
            elif lujvo[i] == H: # what follows can't possibly be the end of a gismu.
                i+=1
                if lujvo[i] in V:
                    i+=1
                    tepuhe.append (lujvo[i-4:i])
                    if i < len(lujvo) - 1 and lujvo[i] in 'mr' and lujvo[i+1] in C: #y can't follow a V
                        tepuhe.append (lujvo[i])
                        i+=1
                    continue
                    # hyphenation? yes, see Newton Unit (SI) lujvo
            elif lujvo[i] in C:
                if i < len(lujvo) - 1 and lujvo[i+1] in C and lujvo[i+2] in (V+J): #CVCCV
                   if mapti_gismu (lujvo, i-2):
                       i+= 3
                       zasni = lujvo[i-5:i]
                       if zasni[-1] not in V:
                           tepuhe.append (zasni[:-1])
                           tepuhe.append (zasni[-1])
                       else:
                           tepuhe.append (zasni)
                       continue
                i+=1
                tepuhe.append (lujvo[i-3:i])
                if i < len(lujvo) - 1  and lujvo[i] in J and lujvo[i+1] in C:
                    tepuhe.append (lujvo[i])
                    i+=1
                #XXX detect invalid initial pair + hyphen
                continue
            raise ValueError ('cizra lujvo? [djica VH]')
    return tepuhe




def jei_kau_snura ():
    return True

def zbasu_liste (valsi):
    # banro la'e zo CMAVO
    # je -raf-si xu
    #
    # manri nu se porsi kei pruce
    # canonical word-type sort?
    pass

def python (log):
    # python console.
    # for doing advanced lookups.
    raise NotImplementedError ('python minde')

def vreji_pa_notci (notci):
    notci_vv = open (notcyterciha, 'ab')
    notci_vv.write (notci)
    notci_vv.write ('\n')
    notci_vv.close ()

def jarco_le_ka_vlalihi_pe_le_notci (clani):
    notci_tt = open (notcyterciha, 'rb')
    vlalihi = notci_tt.readlines()
    notci_tt.close()
    for vl in vlalihi [-clani:]:
        print (vl)
    del vlalihi

def vreji_pa_pruce_datni (datni):
    rtc_vv = open (rolterciha, 'ab')
    rtc_vv.write (datni)
    rtc_vv.write ('\n')
    rtc_vv.close ()

def main ():
    from rlcompleter import Completer
    import readline
    tcidu_datni()
    if not jei_kau_snura ():
        print ('something undefined happened. :/')
        sys.exit()
    m = Completer (mulno_selcmi)
    readline.parse_and_bind ('tab: complete')
    readline.set_completer (m.complete)
    drata_lerfu = "?/:%"
    readline.set_completer_delims (drata_lerfu + ". ")
    if jarco_tuha_le_sidju:
        sidju ()
    denpa_notci = rafsi_skari + 'mo ' + cmavo_skari + ': ' + xruti
    while 1:
        try:
            sepuhe = raw_input(denpa_notci)
            if sepuhe == '':
                continue
        except EOFError:
            stela.close ()
            os.remove (os.path.expanduser ('~/.jbofacki.lock'))
            sys.stdout.write('\n')
            sys.exit()
        command = fadyselcuha
        if sepuhe.startswith ('!') and purci != None:
            if fadyselcuha == jbofihe:
                command = camxes
            else:
                command = jbofihe
            from subprocess import Popen, PIPE
            f = Popen (command, stdin = PIPE, stdout = PIPE)
            f.stdin.write(purci)
        elif sepuhe[0] in drata_lerfu or sepuhe[-1] in drata_lerfu:
            # ? (look up a word)
            #
            if sepuhe[0] in drata_lerfu:
                char = sepuhe[0]
                sepuhe = sepuhe[1:]
            else:
                char = sepuhe[-1]
                sepuhe = sepuhe[:-1]
            if char == '?':
                if len (sepuhe) == 1 and sepuhe == '?':
                    sidju()
                else:
                    valsi = sepuhe.strip().split()
                    j = jarco (valsi)
                    jarco_xire (j)
            elif char == '/':
                valsi = sepuhe.strip().split()
                j, ni_mipri, mipri = ro_selkai_sisku (valsi)
                if len(j) > 100:
                    print (codes['red'] +
                           ('\nNot displaying excessive number (%d) of search results.\n' %
                           len(j)) + xruti + 'Please refine your search.\n')
                else:
                    mipri = list (mipri)
                    mipri.sort()
                    if ni_mipri > 0:
                        print ('\t%s%d%s [ %s ] results omitted' %\
                                (cmavo_skari, ni_mipri, xruti,
                                 gismu_skari + (xruti + ", " + gismu_skari).join (mipri) +\
                                 xruti ))
                    j = jarco (j)
                    jarco_xire (j)
            elif char == ':':
                if sepuhe [0] != '?':
                    vreji_pa_notci (sepuhe)
                else:
                    jarco_le_ka_vlalihi_pe_le_notci (10)
            elif char == '%':
                ni_selvimcu = 0
                for pagbu in sepuhe.split():
                    if pagbu in ro_valsi and valsi_datni[pagbu]['type'] != 'lujvo':
                        ni_selvimcu += 1
                        continue # ignore known valsi that are not lujvo.
                    try:
                        zasni = lujvo_katna (pagbu)
                        print (". ".join(zasni))
                        valsi = []
                        for v in zasni:
                            if len (v) > 2:
                                if len (v) == 4 and "'" not in v:
                                    valsi.append (mapti_gismu (v+'y',0))
                                else:
                                    # look for a rafsi, then a cmavo.
                                    mulno = False
                                    for v2,d in valsi_datni.items():
                                        # prefer rafsi to cmavo. .i le rafsi be fa zo ca'e mu'a
                                        if d['rafsi'] != None and v in d['rafsi']:
                                            valsi.append (v2)
                                            mulno = True
                                            break
                                    if not mulno:
                                        for v2,d in valsi_datni.items():
                                            if v2 == v:
                                                valsi.append (v)
                                                break
                        print (valsi)
                        j = jarco (valsi)
                        jarco_xire (j)
                    except IndexError:
                        print ("bad lujvo morphology for %r. ignored." % pagbu)
                    except ValueError:
                        print ("bad lujvo morphology for %r. ignored." % pagbu)
                if ni_selvimcu > 0:
                    print ('%d non-lujvo valsi ignored' % ni_selvimcu)
            vreji_pa_pruce_datni (sepuhe)
            continue
        else:
            from subprocess import Popen, PIPE
            try:
                f = Popen (fadyselcuha, stdin = PIPE, stdout = PIPE)
                f.stdin.write (sepuhe)
            except OSError:
                print ('Your default parser (%r) doesn\'t appear to be present!' % fadyselcuha[0])
                print ('Please fix your setting in ~/.jbofacki.cfg to point at a valid executable.')
                sys.exit()
        purci = sepuhe
        f.stdin.close()
        tepuhe = f.stdout.read()
        f.stdout.close()

        sys.stdout.write (tepuhe)
        sys.stdout.write ('\n')
        sys.stdout.flush ()

        vreji_pa_pruce_datni (sepuhe)
        vreji_pa_pruce_datni (tepuhe)

if __name__ == "__main__":
    main()
back to top