File: langcompleter.py

package info (click to toggle)
syslog-ng 4.8.1-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 20,456 kB
  • sloc: ansic: 177,631; python: 13,035; cpp: 11,611; makefile: 7,012; sh: 5,147; java: 3,651; xml: 3,344; yacc: 1,377; lex: 599; perl: 193; awk: 190; objc: 162
file content (104 lines) | stat: -rw-r--r-- 4,518 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#############################################################################
# Copyright (c) 2015-2016 Balabit
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation, or (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
# As an additional exemption you are allowed to compile & link against the
# OpenSSL libraries as published by the OpenSSL project. See the file
# COPYING for details.
#
#############################################################################

from __future__ import print_function, absolute_import
from .completer import Completer


class LangBasedCompleter(Completer):

    def __init__(self, parser, completers, prefix=None):
        self._parser = parser
        self._completers = completers
        self._prefix = prefix or ''
        self._completing_at_the_beginning_of_the_grammar = False

    def complete(self, entire_text, word_to_be_completed):
        if entire_text.startswith(self._prefix):
            return self._handle_input_with_prefix(entire_text, word_to_be_completed)
        return self._handle_input_without_prefix(entire_text)

    def _handle_input_without_prefix(self, entire_input):
        if self._prefix.startswith(entire_input) or entire_input == '':
            return [self._prefix]
        return []

    def _handle_input_with_prefix(self, entire_input, word_to_be_completed):
        entire_input, word_to_be_completed = self._chop_prefixes(entire_input, word_to_be_completed)

        expected_tokens, last_token, completion_prefix, word_to_be_completed = (
            self._evaluate_language(entire_input, word_to_be_completed))

        completers = self._find_applicable_completers(expected_tokens)
        completions = self._collect_completions(completers, last_token, completion_prefix, word_to_be_completed)
        return completions

    def _chop_prefixes(self, entire_input, word_to_be_completed):
        if word_to_be_completed == entire_input:
            word_to_be_completed = word_to_be_completed[len(self._prefix):]
            self._completing_at_the_beginning_of_the_grammar = True
        else:
            self._completing_at_the_beginning_of_the_grammar = False
        entire_input = entire_input[len(self._prefix):]
        return entire_input, word_to_be_completed

    def _evaluate_language(self, entire_input, word_to_be_completed):
        expected_tokens, replaced_token, token_position = (
            self._parser.get_expected_tokens(entire_input, drop_last_token=word_to_be_completed != ''))

        if token_position >= 0:
            word_position = len(entire_input) - len(word_to_be_completed)
            if word_position <= token_position:
                completion_prefix = entire_input[word_position:token_position]
                word_to_be_completed = entire_input[token_position:]
            else:
                completion_prefix = ''
        else:
            completion_prefix = ''

        if replaced_token is None:
            replaced_token = ''
        else:
            replaced_token = replaced_token.value or ''

        return expected_tokens, replaced_token, completion_prefix, word_to_be_completed

    def _find_applicable_completers(self, expected_tokens):
        completers = []
        for token in expected_tokens:
            try:
                completers.append(self._completers[token])
            except KeyError:
                pass
        return completers

    def _collect_completions(self, completers, last_token, completion_prefix, word_to_be_completed):
        if self._completing_at_the_beginning_of_the_grammar:
            prefix = self._prefix + completion_prefix
        else:
            prefix = completion_prefix
        completions = []
        for completer in completers:
            completions.extend(
                (prefix + completion for completion in completer.complete(last_token, word_to_be_completed)))
        completions = sorted(completions)
        return completions