Test Failed
Push — master ( b264b0...0ab505 )
by Yoshihiro
03:23
created

NovelEditor.ComplementProcessing   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 17
eloc 77
dl 0
loc 160
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
B ComplementProcessingClass.get_current_insert_word() 0 39 5
A ComplementProcessingClass.selection() 0 19 2
A ComplementProcessingClass.auto_complete() 0 27 2
A ComplementProcessingClass.tab() 0 14 2
A ComplementProcessingClass.get_keywords() 0 23 4
A ComplementProcessingClass.remove_list() 0 10 1
A ComplementProcessingClass.__init__() 0 4 1
1
#!/usr/bin/env python3
2
import tkinter as tk
3
4
from . import Definition
5
6
7
class ComplementProcessingClass(Definition.DefinitionClass):
8
    """ 補完処理のクラス.
9
10
    ・補完処理にあるプログラム群
11
12
    Args:
13
        app (instance): MainProcessingClass のインスタンス
14
        tokenizer (instance): Tokenizer のインスタンス
15
        locale_var (str): ロケーション
16
        master (instance): toplevel のインスタンス
17
    """
18
    def __init__(self, app, tokenizer, locale_var, master=None):
19
        super().__init__(locale_var, master)
20
        self.app = app
21
        self.tokenizer = tokenizer
22
23
    def tab(self, event=None):
24
        """タブ押下時の処理.
25
26
        ・タブキーを押したときに補完リストを出す。
27
28
        Args:
29
            event (instance): tkinter.Event のインスタンス
30
        """
31
        # 文字を選択していないとき
32
        sel_range = self.app.NovelEditor.tag_ranges('sel')
33
        if not sel_range:
34
            return self.auto_complete()
35
        else:
36
            return
37
38
    def auto_complete(self):
39
        """補完リストの設定.
40
41
        ・補完リストの設定をする。
42
        """
43
        self.auto_complete_list = tk.Listbox(self.app.NovelEditor)
44
        # エンターでそのキーワードを選択
45
        self.auto_complete_list.bind('<Return>', self.selection)
46
        self.auto_complete_list.bind('<Double-1>', self.selection)
47
        # エスケープ、タブ、他の場所をクリックで補完リスト削除
48
        self.auto_complete_list.bind('<Escape>', self.remove_list)
49
        self.auto_complete_list.bind('<Tab>', self.remove_list)
50
        self.auto_complete_list.bind('<FocusOut>', self.remove_list)
51
        # (x,y,width,height,baseline)
52
        x, y, width, height, _ = self.app.NovelEditor.dlineinfo(
53
            'insert'
54
        )
55
        # 現在のカーソル位置のすぐ下に補完リストを貼る
56
        self.auto_complete_list.place(x=x+width, y=y+height)
57
        # 補完リストの候補を作成
58
        for word in self.get_keywords():
59
            self.auto_complete_list.insert(tk.END, word)
60
61
        # 補完リストをフォーカスし、0番目を選択している状態に
62
        self.auto_complete_list.focus_set()
63
        self.auto_complete_list.selection_set(0)
64
        return 'break'
65
66
    def get_keywords(self):
67
        """補完リストの候補キーワードを作成.
68
69
        ・補完リストに表示するキーワードを得る。
70
71
        Returns:
72
            str: 補完リスト配列
73
        """
74
        text = ''
75
        text, _, _ = self.get_current_insert_word()
76
        my_func_and_class = set()
77
        # コード補完リストをTreeviewにある'名前'から得る
78
        children = self.app.tree.get_children('data/character')
79
        for child in children:
80
            childname = self.app.tree.item(child, "text")
81
            # 前列の文字列と同じものを選び出す
82
            if childname.startswith(text) or childname.startswith(
83
                text.title()
84
            ):
85
                my_func_and_class.add(childname)
86
87
        result = list(my_func_and_class)
88
        return result
89
90
    def remove_list(self, event=None):
91
        """補完リストの削除処理.
92
93
        ・補完リストを削除し、テキストボックスにフォーカスを戻す。
94
95
        Args:
96
            event (instance): tkinter.Event のインスタンス
97
        """
98
        self.auto_complete_list.destroy()
99
        self.app.NovelEditor.focus()  # テキストウィジェットにフォーカスを戻す
100
101
    def selection(self, event=None):
102
        """補完リストでの選択後の処理.
103
104
        ・補完リストを選択したときにその文字を入力する。
105
106
        Args:
107
            event (instance): tkinter.Event のインスタンス
108
        """
109
        # リストの選択位置を取得
110
        select_index = self.auto_complete_list.curselection()
111
        if select_index:
112
            # リストの表示名を取得
113
            value = self.auto_complete_list.get(select_index)
114
115
            # 現在入力中の単語位置の取得
116
            _, start, end = self.get_current_insert_word()
117
            self.app.NovelEditor.delete(start, end)
118
            self.app.NovelEditor.insert('insert', value)
119
            self.remove_list()
120
121
    def get_current_insert_word(self):
122
        """現在入力中の単語と位置を取得.
123
124
        ・現在入力している単語とその位置を取得する。
125
        """
126
        text = ''
127
        start_i = 1
128
        end_i = 0
129
        while True:
130
            start = 'insert-{0}c'.format(start_i)
131
            end = 'insert-{0}c'.format(end_i)
132
            text = self.app.NovelEditor.get(start, end)
133
            # 1文字ずつ見て、スペース、改行、タブ、空文字、句読点にぶつかったら終わり
134
            if text in (' ', ' ', '\t', '\n', '', '、', '。'):
135
                text = self.app.NovelEditor.get(end, 'insert')
136
137
                # 最終単語を取得する
138
                pri = [
139
                    token.surface for token in self.tokenizer.tokenize(
140
                        text
141
                    )
142
                ]
143
                hin = [
144
                    token.part_of_speech.split(',')[0] for token
145
                    in self.tokenizer.tokenize(text)
146
                ]
147
                if len(pri) > 0:
148
                    if hin[len(pri)-1] == u'名詞':
149
                        text = pri[len(pri)-1]
150
                    else:
151
                        text = ""
152
                else:
153
                    text = ""
154
155
                end = 'insert-{0}c'.format(len(text))
156
                return text, end, 'insert'
157
158
            start_i += 1
159
            end_i += 1
160