From fddcfcbebe4c0d10a5d1787b0cfcf0c61c246a4f Mon Sep 17 00:00:00 2001 From: oysteini Date: Mon, 27 Sep 2010 17:32:24 +0000 Subject: [PATCH] Kommandolinjetolking. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Laget kommandolinjetolker, og definert noen kommandoer (de fleste uten implementasjon). Knyttet boksøkefunksjonen inn i denne galskapen. Oppdaterte arguments.txt litt. --- python/arguments.txt | 9 ++- python/search.py | 16 ++++- python/util.py | 4 ++ python/worblehat.py | 155 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 python/util.py create mode 100755 python/worblehat.py diff --git a/python/arguments.txt b/python/arguments.txt index 514feef..58e4b61 100644 --- a/python/arguments.txt +++ b/python/arguments.txt @@ -1,11 +1,14 @@ # Forslag til kommandolinjeargumenter og deres betydning. -# søk etter bøker som inneholder «computer», «programming» og «knuth» (i tittel eller forfatternavn): -worlbehat search 'computer programming knuth' +# søk etter bøker som inneholder «computer programming» og «knuth» (i +# tittel, undertittel eller forfatternavn): +worlbehat search 'computer programming' knuth +# søk i beskrivelse også: +worblehat --search-description search tex # vis boken med en gitt ISBN: worblehat show 5467237485472 # søk etter person: -worblehat search-person 'donald knuth' +worblehat search-person donald knuth # vis en person: worblehat show dek # skriv ut informasjon i samme format som commit forventer: diff --git a/python/search.py b/python/search.py index 95c1613..f5a5c1f 100644 --- a/python/search.py +++ b/python/search.py @@ -2,11 +2,21 @@ import os os.environ['DJANGO_SETTINGS_MODULE']='web.settings' from web.library.models import * from django.db.models import Q +from util import * -def search(string): - words = string.split() +def search_book_cmd(search_strings, search_description=False): + books = search_book(search_strings, search_description) + format = '%13s %10s %-40s %15s' + for book in books: + b_id = book.getid() or '' + title = cut_str(book.title, 40) + # TODO author + author = '' + print format % (book.isbn, b_id, title, author) + +def search_book(search_strings, search_description=False): basic_query = Book.objects - for word in words: + for word in search_strings: basic_query=basic_query.filter(Q(title__icontains=word) | Q(subtitle__icontains=word) | Q(id__id__icontains=word) | diff --git a/python/util.py b/python/util.py new file mode 100644 index 0000000..963cbc8 --- /dev/null +++ b/python/util.py @@ -0,0 +1,4 @@ +def cut_str(string, length, ellipsis='...'): + if len(string) < length: + return string + return string[0:length-len(ellipsis)]+ellipsis diff --git a/python/worblehat.py b/python/worblehat.py new file mode 100755 index 0000000..52befdf --- /dev/null +++ b/python/worblehat.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import getopt +import sys +import search + +def show_book_or_person(ids, commit_format=False, tmp_file=False): + pass + +# def search_book(): +# pass + +def search_person(): + pass + +def commit(filename=None): + pass + +def edit_book_or_person(ids): + filename = show_book_or_person(ids, commit_format=True, tmp_file=True) +# run_editor(filename) + commit(filename) + +commands = { 'show': + { 'args': [('ids', (1,None))], + 'options': ['commit_format', 'tmp_file'], + 'fun': show_book_or_person }, + 'search': + { 'args': [('search_strings', (1,None))], + 'options': ['search_description'], + 'fun': search.search_book_cmd }, + 'search-person': + { 'args': [('search_strings', (1,None))], + 'options': [], + 'fun': search_person }, + 'commit': + { 'args': [('filename', (0,1))], + 'options': [], + 'fun': commit }, + 'edit': + { 'args': [('ids', (1,None))], + 'options': [], + 'fun': edit_book_or_person } + } + +flags = { 'commit_format': + { 'help': 'output data in the format expected by the commit command' }, + 'tmp_file': + { 'help': 'output data to a new temporary file instead of to stdout' }, + 'search_description': + { 'help': 'include description field when searching' } + } + +general_options = [] # options applicable to all commands + +class BadCommandLine(Exception): + def __init__(self, msg): + Exception.__init__(self, 'Bad command line: ' + msg) + +def check_command_args(args, command): + cmd_decl = commands[command] + min_num_args = sum(map(lambda a: a[1][0], cmd_decl['args'])) + unlimited = any(map(lambda a: a[1][1] == None, cmd_decl['args'])) + if not unlimited: + max_num_args = sum(map(lambda a: a[1][1], cmd_decl['args'])) + if len(args) < min_num_args: + raise BadCommandLine('Too few arguments for command %s (expects at least %d, %d given).' + % (command, min_num_args, len(args))) + if (not unlimited) and (len(args) < max_num_args): + raise BadCommandLine('Too many arguments for command %s (expects at most %d, %d given).' + % (command, max_num_args, len(args))) + +def check_command_opts(opts, command): + cmd_decl = commands[command] + for opt,val in opts: + if ((opt not in cmd_decl['options']) and + (opt not in general_options)): + raise BadCommandLine('Option %s not applicable to command %s.' + % (opt, command)) + +def assign_command_args(args, command): + cmd_decl = commands[command] + d = {} + i = 0 + for param in cmd_decl['args']: + pname = param[0] + pmin = param[1][0] + pmax = param[1][1] + if pmax == 1: + if i < len(args): + d[pname] = args[i] + i += 1 + else: + d[pname] = None + else: + d[pname] = [] + j = 0 + while i + j < len(args) and (pmax == None or j < pmax): + d[pname].append(args[i + j]) + j += 1 + i = i + j + return d + +def assign_command_opts(opts, command): + d = {} + for option, value in opts: + if option in flags: + d[option] = True + else: + d[option] = value + return d + +def parse_cmdline(args): + def getopt_option_name(internal_name): + return internal_name.replace('_', '-') + def internal_option_name(getopt_ret_name): + return getopt_ret_name[2:].replace('-', '_') + + option_names = map(getopt_option_name, flags) + + options, args = getopt.getopt(args, '', option_names) + + if len(args) == 0: + raise BadCommandLine('No command specified.') + cmd_name = args[0] + if cmd_name not in commands: + raise BadCommandLine('Nonexisting command %s.' % cmd_name) + cmd_decl = commands[cmd_name] + cmd_args = args[1:] + cmd_opts = map(lambda (opt,val): (internal_option_name(opt), val), + options) + + check_command_args(cmd_args, cmd_name) + check_command_opts(cmd_opts, cmd_name) + + return { 'command': cmd_name, + 'args': combine_dicts(assign_command_args(cmd_args, cmd_name), + assign_command_opts(cmd_opts, cmd_name)) } + +def invoke_command(command, args): + cmd_decl = commands[command] + cmd_decl['fun'](**args) + +def combine_dicts(*dicts): + res = {} + for d in dicts: + res.update(d) + return res + + +cmdline_parsed = parse_cmdline(sys.argv[1:]) +print 'command line parsed to:', cmdline_parsed +invoke_command(cmdline_parsed['command'], + cmdline_parsed['args'])