aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.htaccess6
-rw-r--r--INSTALL79
-rw-r--r--__init__.py0
-rw-r--r--dicoclient/__init__.py19
-rw-r--r--dicoclient/dicoclient.py415
-rw-r--r--dicoclient/dicoshell.py321
-rw-r--r--dicoclient/setup.py39
-rw-r--r--dicoweb.wsgi27
-rw-r--r--dummy_translations.py40
-rw-r--r--gcide.wsgi25
-rw-r--r--index.html15
-rw-r--r--manage.py23
-rw-r--r--settings-sample.py110
-rw-r--r--settings.py109
-rw-r--r--static/18px-Bulbgraph.pngbin0 -> 1210 bytes
-rw-r--r--static/dicoweb.css134
-rw-r--r--static/dicoweb.js80
-rw-r--r--static/gcide.css206
-rw-r--r--static/gnu-head-sm.jpgbin0 -> 5286 bytes
-rw-r--r--templates/404.html5
-rw-r--r--templates/500.html5
-rw-r--r--templates/about.html53
-rw-r--r--templates/base.html71
-rw-r--r--templates/download.html118
-rw-r--r--templates/index.html154
-rw-r--r--templates/license.html21
-rw-r--r--templates/opensearch.xml8
-rw-r--r--templatetags/__init__.py0
-rw-r--r--templatetags/dictlookup.py27
-rw-r--r--templatetags/macros.py160
-rw-r--r--templatetags/withsetting.py67
-rw-r--r--urls.py28
-rw-r--r--views.py253
33 files changed, 2618 insertions, 0 deletions
diff --git a/.htaccess b/.htaccess
new file mode 100644
index 0000000..2df5844
--- /dev/null
+++ b/.htaccess
@@ -0,0 +1,6 @@
+Options All -Indexes
+<Files ~ "^\.emacs">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..ee9a98b
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,79 @@
+GNU Dico - Dicoweb INSTALL
+Copyright (C) 2008-2010, 2012 Wojciech Polak
+
+* Dicoweb requirements
+======================
+
+- Django 1.0+ -- a Python Web framework (http://www.djangoproject.com/)
+- Wit -- a wiki translator distributed within GNU Dico.
+ (http://puszcza.gnu.org.ua/projects/wit/)
+
+* Installation instructions
+===========================
+
+Rename 'settings-sample.py' to 'settings.py' and edit your
+local Dicoweb site configuration.
+
+
+** The development/test server
+------------------------------
+
+Change the current working directory into the `dicoweb' directory
+and run the command `python manage.py runserver'. You will see
+the following output:
+
+ Validating models...
+ 0 errors found.
+
+ Django version 1.0, using settings 'dicoweb.settings'
+ Development server is running at http://127.0.0.1:8000/
+ Quit the server with CONTROL-C.
+
+** Production server with mod_wsgi
+----------------------------------
+
+Apache configuration:
+
+ LoadModule wsgi_module modules/mod_wsgi.so
+ WSGIScriptAlias / /usr/local/django/dicoweb/dicoweb.wsgi
+ Alias /static "/usr/local/django/dicoweb/static"
+
+More detailed information is available at:
+http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
+
+** Production server with mod_python
+------------------------------------
+
+Apache configuration:
+
+ LoadModule python_module modules/mod_python.so
+ <Location "/">
+ SetHandler python-program
+ PythonHandler django.core.handlers.modpython
+ PythonPath "sys.path + ['/usr/local/django', '/usr/local/django/dicoweb']"
+ SetEnv DJANGO_SETTINGS_MODULE dicoweb.settings
+ PythonInterpreter dicoweb
+ PythonDebug Off
+ </Location>
+
+ <Location "/static">
+ SetHandler None
+ </Location>
+ <Location "/favicon.ico">
+ SetHandler None
+ </Location>
+
+ <Directory "/usr/local/django/dicoweb/">
+ AllowOverride All
+ Options None
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+
+
+Local Variables:
+mode: outline
+paragraph-separate: "[ ]*$"
+version-control: never
+End:
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/__init__.py
diff --git a/dicoclient/__init__.py b/dicoclient/__init__.py
new file mode 100644
index 0000000..a300cea
--- /dev/null
+++ b/dicoclient/__init__.py
@@ -0,0 +1,19 @@
+# This file is part of GNU Dico.
+# Copyright (C) 2008-2009, 2012 Wojciech Polak
+#
+# GNU Dico is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Dico is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Dico. If not, see <http://www.gnu.org/licenses/>.
+
+__all__ = ["dicoclient"]
+
+from dicoclient import *
diff --git a/dicoclient/dicoclient.py b/dicoclient/dicoclient.py
new file mode 100644
index 0000000..76336c2
--- /dev/null
+++ b/dicoclient/dicoclient.py
@@ -0,0 +1,415 @@
+# This file is part of GNU Dico.
+# Copyright (C) 2008-2010, 2012 Wojciech Polak
+#
+# GNU Dico is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Dico is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Dico. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import socket
+import base64
+import quopri
+import hashlib
+
+__version__ = '1.0'
+
+class DicoClient:
+ """GNU Dico client module written in Python
+ (a part of GNU Dico software)"""
+
+ host = None;
+ levenshtein_distance = 0
+ mime = False
+
+ verbose = 0
+ timeout = 10
+ transcript = False
+ __connected = False
+
+ def __init__ (self, host=None):
+ if host != None:
+ self.host = host;
+
+ def __del__ (self):
+ if self.__connected:
+ self.socket.close ()
+
+ def open (self, host=None, port=2628, cred=None):
+ """Open the connection to the DICT server."""
+ if host != None:
+ self.host = host
+ if self.verbose:
+ self.__debug ('Connecting to %s:%d' % (self.host, port))
+ socket.setdefaulttimeout (int (self.timeout))
+ self.socket = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
+ self.socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.socket.connect ((self.host, port))
+ self.__connected = True
+ self.fd = self.socket.makefile ();
+
+ self.server_banner = self.__read ()[0]
+ capas, msgid = re.search ('<(.*)> (<.*>)$',
+ self.server_banner).groups ()
+ self.server_capas = capas.split ('.')
+ self.server_msgid = msgid
+
+ self.__send_client ()
+ self.__read ()
+ if cred and 'user' in cred and 'password' in cred:
+ self.auth(cred['user'], cred['password'])
+
+ def auth (self, user, passwd):
+ if self.__connected and 'auth' in self.server_capas:
+ if self.verbose:
+ self.__debug ('Authenticating on %s' % (self.host))
+ m = hashlib.md5()
+ m.update(self.server_msgid)
+ m.update(passwd)
+ self.__send ('AUTH %s %s' % (user, m.hexdigest()))
+ res = self.__read ()
+ code, msg = res[0].split (' ', 1)
+ if int (code) == 230:
+ return True
+ return False
+
+ def close (self):
+ """Close the connection."""
+ if self.__connected:
+ self.__send_quit ()
+ self.__read ()
+ self.socket.close ()
+ self.__connected = False
+
+ def option (self, name, *args):
+ """Send the OPTION command."""
+ if self.__connected:
+ self.__send ('OPTION %s%s' %
+ (name, reduce (lambda x, y: str (x) +' '+ str (y),
+ args, '')))
+ res = self.__read ()
+ code, msg = res[0].split (' ', 1)
+ if int (code) == 250:
+ if name.lower () == 'mime':
+ self.mime = True
+ return True
+ return False
+
+ def __get_mime (self, lines):
+ cnt = 0
+ mimeinfo = {}
+ firstline = lines[0].lower ()
+ if firstline.find ('content-type:') != -1 or \
+ firstline.find ('content-transfer-encoding:') != -1:
+ cnt += 1
+ for line in lines:
+ if line == '':
+ break
+ t = line.split (':', 1)
+ mimeinfo[t[0].lower ()] = t[1].strip ()
+ cnt += 1
+ for i in range (0, cnt):
+ lines.pop (0)
+ else:
+ lines.pop (0)
+ if 'content-transfer-encoding' in mimeinfo:
+ if mimeinfo['content-transfer-encoding'].lower () == 'base64':
+ buf = base64.decodestring ('\n'.join (lines))
+ lines[:] = (buf.split ('\r\n'))
+ if lines[-1] == '': del lines[-1]
+ del mimeinfo['content-transfer-encoding']
+ elif mimeinfo['content-transfer-encoding'].lower () == 'quoted-printable':
+ buf = quopri.decodestring ('\n'.join (lines))
+ lines[:] = buf.split ('\r\n')
+ if lines[-1] == '': del lines[-1]
+ del mimeinfo['content-transfer-encoding']
+ return mimeinfo
+
+ def __get_rs (self, line):
+ code, text = line.split (' ', 1)
+ code = int (code)
+ return code, text
+
+ def __read (self):
+ if not self.__connected:
+ raise DicoNotConnectedError ('Not connected')
+ buf = []
+ line = self.__readline ()
+ if len (line) == 0:
+ raise DicoNotConnectedError ('Not connected')
+ buf.append (line)
+ code, text = self.__get_rs (line)
+
+ if code >= 100 and code < 200:
+ if code == 150:
+ while True:
+ rs = self.__readline ()
+ code, text = self.__get_rs (rs)
+ if code != 151:
+ buf.append (rs)
+ break
+ buf.append ([rs, self.__readblock ()])
+ else:
+ buf.append (self.__readblock ())
+ buf.append (self.__readline ())
+ return buf
+
+ def __readline (self):
+ line = self.fd.readline ().rstrip ()
+ if self.transcript:
+ self.__debug ('S:%s' % line)
+ return line
+
+ def __readblock (self):
+ buf = []
+ while True:
+ line = self.__readline ()
+ if line == '.':
+ break
+ buf.append (line)
+ return buf
+
+
+ def __send (self, command):
+ if not self.__connected:
+ raise DicoNotConnectedError ('Not connected')
+ self.socket.send (command.encode ('utf_8') + "\r\n")
+ if self.transcript:
+ self.__debug ('C:%s' % command)
+
+ def __send_client (self):
+ if self.verbose:
+ self.__debug ('Sending client information')
+ self.__send ('CLIENT "%s %s"' % ("GNU Dico (Python Edition)",
+ __version__))
+
+ def __send_quit (self):
+ if self.verbose:
+ self.__debug ('Quitting')
+ self.__send ('QUIT');
+
+ def __send_show (self, what, arg=None):
+ if arg != None:
+ self.__send ('SHOW %s "%s"' % (what, arg))
+ else:
+ self.__send ('SHOW %s' % what)
+ return self.__read ()
+
+ def __send_define (self, database, word):
+ if self.verbose:
+ self.__debug ('Sending query for word "%s" in database "%s"' %
+ (word, database))
+ self.__send ('DEFINE "%s" "%s"' % (database, word))
+ return self.__read ()
+
+ def __send_match (self, database, strategy, word):
+ if self.verbose:
+ self.__debug ('Sending query to match word "%s" in database "%s", using "%s"'
+ % (word, database, strategy))
+ self.__send ('MATCH "%s" "%s" "%s"' % (database, strategy, word))
+ return self.__read ()
+
+ def __send_xlev (self, distance):
+ self.__send ('XLEV %u' % distance)
+ return self.__read ()
+
+ def show_databases (self):
+ """List all accessible databases."""
+ if self.verbose:
+ self.__debug ('Getting list of databases')
+ res = self.__send_show ('DATABASES')
+ if self.mime:
+ mimeinfo = self.__get_mime (res[1])
+ dbs_res = res[1:-1][0]
+ dbs = []
+ for d in dbs_res:
+ short_name, full_name = d.split (' ', 1)
+ dbs.append ([short_name, self.__unquote (full_name)])
+ dct = {
+ 'count': len (dbs),
+ 'databases': dbs,
+ }
+ return dct
+
+ def show_strategies (self):
+ """List available matching strategies."""
+ if self.verbose:
+ self.__debug ('Getting list of strategies')
+ res = self.__send_show ('STRATEGIES')
+ if self.mime:
+ mimeinfo = self.__get_mime (res[1])
+ sts_res = res[1:-1][0]
+ sts = []
+ for s in sts_res:
+ short_name, full_name = s.split (' ', 1)
+ sts.append ([short_name, self.__unquote (full_name)])
+ dct = {
+ 'count': len (sts),
+ 'strategies': sts,
+ }
+ return dct
+
+ def show_info (self, database):
+ """Provide information about the database."""
+ res = self.__send_show ("INFO", database)
+ code, msg = res[0].split (' ', 1)
+ if int (code) < 500:
+ if self.mime:
+ mimeinfo = self.__get_mime (res[1])
+ dsc = res[1]
+ return {'desc': '\n'.join (dsc), 'type': 'info' }
+ else:
+ return {'error': code, 'msg': msg}
+
+ def show_lang_db (self):
+ """Show databases with their language preferences."""
+ res = self.__send_show ('LANG DB')
+ code, msg = res[0].split (' ', 1)
+ if int (code) < 500:
+ if self.mime:
+ mimeinfo = self.__get_mime (res[1])
+ dsc = res[1]
+ lang_src = {}
+ lang_dst = {}
+ for i in dsc:
+ pair = i.split (' ', 1)[1]
+ src, dst = pair.split (':', 1)
+ for j in src:
+ lang_src[src.strip()] = True
+ for j in dst:
+ lang_dst[dst.strip()] = True
+ return {
+ 'desc': '\n'.join (dsc),
+ 'type': 'lang',
+ 'lang_src': lang_src.keys (),
+ 'lang_dst': lang_dst.keys (),
+ }
+ else:
+ return {'error': code, 'msg': msg}
+
+ def show_lang_pref (self):
+ """Show server language preferences."""
+ res = self.__send_show ('LANG PREF')
+ code, msg = res[0].split (' ', 1)
+ if int (code) < 500:
+ return {'msg': msg}
+ else:
+ return {'error': code, 'msg': msg}
+
+ def show_server (self):
+ """Provide site-specific information."""
+ res = self.__send_show ('SERVER')
+ code, msg = res[0].split (' ', 1)
+ if int (code) < 500:
+ dsc = res[1]
+ return {'desc': '\n'.join (dsc), 'type': 'server'}
+ else:
+ return {'error': code, 'msg': msg}
+
+ def define (self, database, word):
+ """Look up word in database."""
+ database = database.replace ('"', "\\\"")
+ word = word.replace ('"', "\\\"")
+ res = self.__send_define (database, word)
+ code, msg = res[-1].split (' ', 1)
+ if int (code) < 500:
+ defs_res = res[1:-1]
+ defs = []
+ rx = re.compile ('^\d+ ("[^"]+"|\w+) ([a-zA-Z0-9_\-]+) ("[^"]*"|\w+)')
+ for i in defs_res:
+ term, db, db_fullname = rx.search (i[0]).groups ()
+ df = {
+ 'term': self.__unquote (term),
+ 'db': db,
+ 'db_fullname': self.__unquote (db_fullname),
+ }
+ if self.mime:
+ mimeinfo = self.__get_mime (i[1])
+ df.update (mimeinfo)
+ df['desc'] = '\n'.join (i[1])
+ defs.append (df)
+ dct = {
+ 'count': len (defs),
+ 'definitions': defs,
+ 'type': 'define'
+ }
+ return dct
+ else:
+ return {'error': code, 'msg': msg}
+
+ def match (self, database, strategy, word):
+ """Match word in database using strategy."""
+ if not self.__connected:
+ raise DicoNotConnectedError ('Not connected')
+
+ if self.levenshtein_distance and 'xlev' in self.server_capas:
+ res = self.__send_xlev (self.levenshtein_distance)
+ code, msg = res[-1].split (' ', 1)
+ if int (code) != 250 and self.verbose:
+ self.__debug ('Server rejected XLEV command')
+ self.__debug ('Server reply: %s' % msg)
+
+ database = database.replace ('"', "\\\"")
+ strategy = strategy.replace ('"', "\\\"")
+ word = word.replace ('"', "\\\"")
+
+ res = self.__send_match (database, strategy, word)
+ code, msg = res[-1].split (' ', 1)
+ if int (code) < 500:
+ if self.mime:
+ mimeinfo = self.__get_mime (res[1])
+ mts_refs = res[1:-1][0]
+ mts = {}
+ for i in mts_refs:
+ db, term = i.split (' ', 1)
+ if mts.has_key (db):
+ mts[db].append (self.__unquote (term))
+ else:
+ mts[db] = [self.__unquote (term)]
+ dct = {
+ 'matches': mts,
+ }
+ return dct
+ else:
+ return {'error': code, 'msg': msg}
+
+ def xlev (self, distance):
+ """Set Levenshtein distance."""
+ self.levenshtein_distance = distance
+ res = self.__send_xlev (distance)
+ code, msg = res[0].split (' ', 1)
+ if int (code) == 250:
+ return True
+ return False
+
+ def __unquote (self, s):
+ s = s.replace ("\\\\'", "'")
+ if s[0] == '"' and s[-1] == '"':
+ s = s[1:-1]
+ try:
+ s = self.__decode (s)
+ except UnicodeEncodeError:
+ pass
+ return s
+
+ def __decode (self, encoded):
+ for octc in (c for c in re.findall (r'\\(\d{3})', encoded)):
+ encoded = encoded.replace (r'\%s' % octc, chr (int (octc, 8)))
+ return unicode (encoded, 'utf_8')
+
+ def __debug (self, msg):
+ print 'dico: Debug: %s' % msg
+
+class DicoNotConnectedError (Exception):
+ def __init__ (self, value):
+ self.parameter = value
+ def __str__(self):
+ return repr (self.parameter)
diff --git a/dicoclient/dicoshell.py b/dicoclient/dicoshell.py
new file mode 100644
index 0000000..1c0e64d
--- /dev/null
+++ b/dicoclient/dicoshell.py
@@ -0,0 +1,321 @@
+# This file is part of GNU Dico.
+# Copyright (C) 2008-2010, 2012 Wojciech Polak
+#
+# GNU Dico is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Dico is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Dico. If not, see <http://www.gnu.org/licenses/>.
+
+import re
+import os
+import sys
+import atexit
+import getopt
+import readline
+import curses.ascii
+import socket
+import dicoclient
+
+class Shell:
+ """Simple GNU Dico-Python Shell."""
+
+ prompt = 'dico> '
+ prefix = '.'
+
+ default_host = 'gnu.org.ua'
+ database = '!'
+ strategy = '.'
+ last_matches = []
+ last_databases = []
+ last_strategies = []
+ transcript = False
+
+ def __init__ (self, opts, args):
+ for o, a in opts:
+ if o in ('-h', '--host'):
+ self.default_host = a
+
+ self.dc = dicoclient.DicoClient (self.default_host)
+
+ def run (self):
+ histfile = os.path.expanduser ('~/.dico_history')
+ try:
+ readline.read_history_file (histfile)
+ except IOError:
+ pass
+ atexit.register (readline.write_history_file, histfile)
+
+ print '\nType ? for help summary\n'
+ while True:
+ try:
+ input = raw_input (self.prompt).strip ()
+ input = unicode (input, 'utf_8')
+ except (EOFError, KeyboardInterrupt):
+ print
+ sys.exit ()
+
+ try:
+ self.parse (input)
+ except socket.timeout:
+ self.__error ('socket timed out')
+ except dicoclient.DicoNotConnectedError:
+ try:
+ self.dc.open ()
+ dict = self.dc.show_databases ()
+ self.last_databases = dict['databases']
+ dict = self.dc.show_strategies ()
+ self.last_strategies = dict['strategies']
+ self.parse (input)
+ except socket.error, (errno, strerror):
+ self.__error (strerror)
+
+ def parse (self, input):
+ if len (input) < 1:
+ return
+ if input[0] == self.prefix:
+ self.parse_command (input[1:])
+ elif input == '?':
+ self.print_help ()
+ elif re.match (r'^[0-9]+$', input):
+ try:
+ match = self.last_matches[int (input)]
+ dict = self.dc.define (match[0], match[1])
+ if 'count' in dict:
+ for d in dict['definitions']:
+ print 'From %s, %s:' % (d['db'], d['db_fullname'].
+ encode ('utf_8'))
+ print d['desc']
+ elif 'error' in dict:
+ print dict['msg']
+ except IndexError:
+ self.__error ('No previous match')
+ elif input[0] == '/':
+ if len (input) > 1:
+ dict = self.dc.match (self.database, self.strategy, input[1:])
+ if 'matches' in dict:
+ self.last_matches = []
+ lmi = 0
+ for db in dict['matches']:
+ print 'From %s, %s:' % (db, self.__lookup_db (db).
+ encode ('utf_8'))
+ for term in dict['matches'][db]:
+ print '%4d) "%s"' % (lmi, term.encode ('utf_8'))
+ self.last_matches.append ([db, term])
+ lmi = lmi + 1
+ elif 'error' in dict:
+ print dict['msg']
+ else:
+ if len (self.last_matches) > 0:
+ m = {}
+ lmi = 0
+ for i, db in enumerate (self.last_matches):
+ if not db[0] in m: m[db[0]] = []
+ m[db[0]].append (self.last_matches[i][1])
+ for db in m:
+ print 'From %s, %s:' % (db, self.__lookup_db (db))
+ for term in m[db]:
+ print '%4d) "%s"' % (lmi, term)
+ lmi = lmi + 1
+ else:
+ self.__error ('No previous match')
+ elif input[0] == '!':
+ if re.match (r'^![0-9]+$', input):
+ number = int (input[1:])
+ readline.insert_text (readline.get_history_item (number))
+ readline.redisplay ()
+ else:
+ dict = self.dc.define (self.database, input)
+ if 'count' in dict:
+ for d in dict['definitions']:
+ print 'From %s, %s:' % (d['db'], d['db_fullname'].
+ encode ('utf_8'))
+ print d['desc']
+ elif 'error' in dict:
+ print dict['msg']
+
+ def parse_command (self, input):
+ input = input.split (' ', 1)
+ cmd = input[0]
+ args = None
+ if len (input) == 2:
+ args = input[1]
+
+ if cmd == 'open':
+ try:
+ if args != None:
+ args = args.split (' ', 1)
+ if len (args) == 2:
+ self.dc.open (args[0], int (args[1]))
+ else:
+ self.dc.open (args[0])
+ else:
+ self.dc.open ()
+ dict = self.dc.show_databases ()
+ self.last_databases = dict['databases']
+ dict = self.dc.show_strategies ()
+ self.last_strategies = dict['strategies']
+ except socket.error, (errno, strerror):
+ self.__error (strerror)
+ elif cmd == 'close':
+ self.dc.close ()
+ elif cmd == 'database':
+ if args != None:
+ self.database = args
+ else:
+ print self.database
+ elif cmd == 'strategy':
+ if args != None:
+ self.strategy = args
+ else:
+ print self.strategy
+ elif cmd == 'distance':
+ if args != None:
+ self.dc.levenshtein_distance = int (args)
+ else:
+ if self.dc.levenshtein_distance:
+ print 'Configured Levenshtein distance: %u' % \
+ self.dc.levenshtein_distance
+ else:
+ print 'No distance configured'
+ elif cmd == 'ls':
+ dict = self.dc.show_strategies ()
+ self.last_strategies = dict['strategies']
+ if len (self.last_strategies):
+ for i in self.last_strategies:
+ print '%s "%s"' % (i[0], i[1])
+ elif cmd == 'ld':
+ dict = self.dc.show_databases ()
+ self.last_databases = dict['databases']
+ if len (self.last_databases):
+ for i in self.last_databases:
+ print '%s "%s"' % (i[0], i[1])
+ elif cmd == 'mime':
+ print self.dc.option ('MIME')
+ elif cmd == 'server':
+ dict = self.dc.show_server ()
+ if 'desc' in dict:
+ print dict['desc']
+ elif 'error' in dict:
+ self.__error (dict['error'] + ' ' + dict['msg'])
+ elif cmd == 'info':
+ if args != None:
+ dict = self.dc.show_info (args)
+ if 'desc' in dict:
+ print dict['desc']
+ elif 'error' in dict:
+ self.__error (dict['error'] + ' ' + dict['msg'])
+ elif cmd == 'history':
+ hl = int (readline.get_current_history_length ())
+ for i in xrange (0, hl):
+ print '%4d) %s' % (i, readline.get_history_item (i))
+ elif cmd == 'help':
+ self.print_help ()
+ elif cmd == 'transcript':
+ if args != None:
+ if args in ('yes', 'on', 'true'):
+ self.dc.transcript = True
+ elif args in ('no', 'off', 'false'):
+ self.dc.transcript = False
+ else:
+ self.__error ('Expected boolean value')
+ else:
+ if self.dc.transcript:
+ print 'transcript is on'
+ else:
+ print 'transcript is off'
+ elif cmd == 'verbose':
+ if args != None:
+ self.dc.verbose = args
+ else:
+ print self.dc.verbose
+ elif cmd == 'prompt':
+ if args != None:
+ self.prompt = args
+ else:
+ self.__error ('not enough arguments')
+ elif cmd == 'prefix':
+ if args != None:
+ if len (args) == 1 and args != '#' and \
+ curses.ascii.ispunct (args):
+ self.prefix = args
+ else:
+ self.__error ('Expected a single punctuation character')
+ elif cmd == 'version':
+ self.print_version ()
+ elif cmd == 'warranty':
+ self.print_warranty ()
+ elif cmd == 'quit':
+ sys.exit ()
+
+ def __lookup_db (self, db):
+ for d in self.last_databases:
+ if d[0] == db:
+ return d[1]
+ return ''
+
+ def __error (self, msg):
+ print 'dico: Error: %s' % msg
+
+ def print_version (self):
+ print 'GNU Dico (Python Edition) ' + dicoclient.__version__
+
+ def print_warranty (self):
+ self.print_version ()
+ print """Copyright (C) 2008, 2009, 2010 Wojciech Polak
+
+ GNU Dico is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Dico is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Dico. If not, see <http://www.gnu.org/licenses/>."""
+
+ def print_help (self):
+ print 'WORD Define WORD.'
+ print '/WORD Match WORD.'
+ print '/ Redisplay previous matches.'
+ print 'NUMBER Define NUMBERth match.'
+ p