listpick 0.1.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,258 @@
1
+ #!/bin/python
2
+ import curses
3
+
4
+ """
5
+ Define colour options for list_picker, help, and notification
6
+ """
7
+ def get_theme_count() -> int:
8
+ col_list = []
9
+ i = 0
10
+ for i in range(100):
11
+ x = get_colours(i)
12
+ if x in col_list:
13
+ break
14
+ col_list.append(x)
15
+ return i
16
+
17
+
18
+ def get_colours(pick:int=0) -> dict[str, int]:
19
+ """ Define colour options for list_picker. """
20
+ colours = [
21
+ ### Green header, green title, green modes, purple selected, blue cursor
22
+ {
23
+ 'background': 232,
24
+ 'normal_fg': 253,
25
+ 'unselected_bg': 232,
26
+ 'unselected_fg': 253,
27
+ 'cursor_bg': 25,
28
+ 'cursor_fg': 253,
29
+ 'selected_bg': 135,
30
+ 'selected_fg': 253,
31
+ 'header_bg': 253,
32
+ 'header_fg': 232,
33
+ 'error_bg': 232,
34
+ 'error_fg': curses.COLOR_RED,
35
+ 'complete_bg': 232,
36
+ 'complete_fg': 82,
37
+ 'waiting_bg': 232,
38
+ 'waiting_fg': curses.COLOR_YELLOW,
39
+ 'active_bg': 232,
40
+ 'active_fg': 33,
41
+ 'paused_bg': 232,
42
+ 'paused_fg': 244,
43
+ 'search_bg': 162,
44
+ 'search_fg': 253,
45
+ 'active_input_bg': 253,
46
+ 'active_input_fg': 28,
47
+ 'modes_selected_bg': 28,
48
+ 'modes_selected_fg': 253,
49
+ 'modes_unselected_bg': 253,
50
+ 'modes_unselected_fg': 232,
51
+ 'title_bar': 28,
52
+ 'title_bg': 28,
53
+ 'title_fg': 253,
54
+ 'scroll_bar_bg': 247,
55
+ 'selected_header_column_bg': 247,
56
+ 'selected_header_column_fg': 232,
57
+ 'footer_bg': 28,
58
+ 'footer_fg': 253,
59
+ 'refreshing_bg': 28,
60
+ 'refreshing_fg': 253,
61
+ 'refreshing_inactive_bg': 28,
62
+ 'refreshing_inactive_fg': 232,
63
+ '40pc_bg': 232,
64
+ '40pc_fg': 166,
65
+ 'footer_string_bg': 28,
66
+ 'footer_string_fg': 253,
67
+ },
68
+ ### Black and white
69
+ {
70
+ 'background': 232,
71
+ 'normal_fg': 253,
72
+ 'unselected_bg': 232,
73
+ 'unselected_fg': 253,
74
+ 'cursor_bg': 253,
75
+ 'cursor_fg': 232,
76
+ 'selected_bg': 253,
77
+ 'selected_fg': 232,
78
+ 'header_bg': 253,
79
+ 'header_fg': 232,
80
+ 'error_bg': 232,
81
+ 'error_fg': 253,
82
+ 'complete_bg': 232,
83
+ 'complete_fg': 253,
84
+ 'waiting_bg': 232,
85
+ 'waiting_fg': 253,
86
+ 'active_bg': 232,
87
+ 'active_fg': 253,
88
+ 'paused_bg': 232,
89
+ 'paused_fg': 253,
90
+ 'search_bg': 253,
91
+ 'search_fg': 232,
92
+ 'active_input_bg': 232,
93
+ 'active_input_fg': 253,
94
+ 'modes_selected_bg': 253,
95
+ 'modes_selected_fg': 232,
96
+ 'modes_unselected_bg': 232,
97
+ 'modes_unselected_fg': 253,
98
+ 'title_bar': 232,
99
+ 'title_bg': 253,
100
+ 'title_fg': 232,
101
+ 'scroll_bar_bg': 253,
102
+ 'selected_header_column_bg': 232,
103
+ 'selected_header_column_fg': 253,
104
+ 'footer_bg': 253,
105
+ 'footer_fg': 232,
106
+ 'refreshing_bg': 253,
107
+ 'refreshing_fg': 232,
108
+ 'refreshing_inactive_bg': 232,
109
+ 'refreshing_inactive_fg': 253,
110
+ '40pc_bg': 232,
111
+ '40pc_fg': 253,
112
+ 'footer_string_bg': 253,
113
+ 'footer_string_fg': 232,
114
+ },
115
+ ### Blue header, blue title, blue modes, purple selected, green cursor
116
+ {
117
+ 'background': 232,
118
+ 'normal_fg': 253,
119
+ 'unselected_bg': 232,
120
+ 'unselected_fg': 253,
121
+ 'cursor_bg': 28,
122
+ 'cursor_fg': 253,
123
+ 'selected_bg': 135,
124
+ 'selected_fg': 253,
125
+ 'header_bg': 253,
126
+ 'header_fg': 232,
127
+ 'error_bg': 232,
128
+ 'error_fg': curses.COLOR_RED,
129
+ 'complete_bg': 232,
130
+ 'complete_fg': 82,
131
+ 'waiting_bg': 232,
132
+ 'waiting_fg': curses.COLOR_YELLOW,
133
+ 'active_bg': 232,
134
+ 'active_fg': 33,
135
+ 'paused_bg': 232,
136
+ 'paused_fg': 244,
137
+ 'search_bg': 162,
138
+ 'search_fg': 253,
139
+ 'active_input_bg': 253,
140
+ 'active_input_fg': 25,
141
+ 'modes_selected_bg': 25,
142
+ 'modes_selected_fg': 253,
143
+ 'modes_unselected_bg': 253,
144
+ 'modes_unselected_fg': 232,
145
+ 'title_bar': 25,
146
+ 'title_bg': 25,
147
+ 'title_fg': 253,
148
+ 'scroll_bar_bg': 247,
149
+ 'selected_header_column_bg': 247,
150
+ 'selected_header_column_fg': 232,
151
+ 'footer_bg': 25,
152
+ 'footer_fg': 253,
153
+ 'refreshing_bg': 25,
154
+ 'refreshing_fg': 253,
155
+ 'refreshing_inactive_bg': 25,
156
+ 'refreshing_inactive_fg': 232,
157
+ '40pc_bg': 232,
158
+ '40pc_fg': 166,
159
+ 'footer_string_bg': 25,
160
+ 'footer_string_fg': 253,
161
+ },
162
+ ### Purple header, purple title, white modes, green selected, blue cursor
163
+ {
164
+ 'background': 232,
165
+ 'normal_fg': 253,
166
+ 'unselected_bg': 232,
167
+ 'unselected_fg': 253,
168
+ 'cursor_bg': 57,
169
+ 'cursor_fg': 253,
170
+ 'selected_bg': 135,
171
+ 'selected_fg': 253,
172
+ 'header_bg': 253,
173
+ 'header_fg': 232,
174
+ 'error_bg': 232,
175
+ 'error_fg': curses.COLOR_RED,
176
+ 'complete_bg': 232,
177
+ 'complete_fg': 82,
178
+ 'waiting_bg': 232,
179
+ 'waiting_fg': curses.COLOR_YELLOW,
180
+ 'active_bg': 232,
181
+ 'active_fg': 33,
182
+ 'paused_bg': 232,
183
+ 'paused_fg': 244,
184
+ 'search_bg': 162,
185
+ 'search_fg': 253,
186
+ 'active_input_bg': 253,
187
+ 'active_input_fg': 57,
188
+ 'modes_selected_bg': 57,
189
+ 'modes_selected_fg': 253,
190
+ 'modes_unselected_bg': 253,
191
+ 'modes_unselected_fg': 232,
192
+ 'title_bar': 57,
193
+ 'title_bg': 57,
194
+ 'title_fg': 253,
195
+ 'scroll_bar_bg': 247,
196
+ 'selected_header_column_bg': 247,
197
+ 'selected_header_column_fg': 232,
198
+ 'footer_bg': 57,
199
+ 'footer_fg': 253,
200
+ 'refreshing_bg': 57,
201
+ 'refreshing_fg': 253,
202
+ 'refreshing_inactive_bg': 57,
203
+ 'refreshing_inactive_fg': 232,
204
+ '40pc_bg': 232,
205
+ '40pc_fg': 166,
206
+ 'footer_string_bg': 57,
207
+ 'footer_string_fg': 253,
208
+ },
209
+ ]
210
+ for colour in colours:
211
+ colour["20pc_bg"] = colour["background"]
212
+ colour["40pc_bg"] = colour["background"]
213
+ colour["60pc_bg"] = colour["background"]
214
+ colour["80pc_bg"] = colour["background"]
215
+ colour["100pc_bg"] = colour["background"]
216
+ colour["error_bg"] = colour["background"]
217
+ colour["complete_bg"] = colour["background"]
218
+ colour["waiting_bg"] = colour["background"]
219
+ colour["active_bg"] = colour["background"]
220
+ colour["paused_bg"] = colour["background"]
221
+ colour["paused_bg"] = colour["background"]
222
+ # colour["search_bg"] = colour["background"]
223
+ if pick > len(colours) - 1:
224
+ return colours[0]
225
+ return colours[pick]
226
+
227
+ def get_help_colours(pick: int=0) -> dict:
228
+ colours = [get_colours(i) for i in range(get_theme_count())]
229
+ for i in range(len(colours)):
230
+ colours[i]['cursor_bg'] = 235
231
+ colours[i]['cursor_fg'] = 253
232
+ colours[i]['selected_bg'] = 25
233
+ colours[i]['selected_fg'] = 253
234
+
235
+ if pick > len(colours) - 1:
236
+ return colours[0]
237
+ return colours[pick]
238
+
239
+
240
+ def get_notification_colours(pick:int=0) -> dict:
241
+ colours = [get_colours(i) for i in range(get_theme_count())]
242
+ for i in range(len(colours)):
243
+ colours[i]['background'] = 237
244
+ colours[i]['unselected_bg'] = 237
245
+ colours[i]['cursor_bg'] = 237
246
+ colours[i]['selected_bg'] = 237
247
+
248
+ # Black and white
249
+ colours[1]['background'] = 237
250
+ colours[1]['unselected_bg'] = 237
251
+ colours[1]['cursor_bg'] = 237
252
+ colours[1]['cursor_fg'] = 253
253
+ colours[1]['selected_bg'] = 237
254
+ colours[1]['selected_fg'] = 253
255
+
256
+ if pick > len(colours) - 1:
257
+ return colours[0]
258
+ return colours[pick]
File without changes
@@ -0,0 +1,33 @@
1
+ #!/bin/python
2
+ import pyperclip
3
+ from typing import Tuple
4
+
5
+ """
6
+ representation: python, tab-separated, comma-separated, current view
7
+ rows: selected, all, filtered
8
+ columns: all, not hidden
9
+ """
10
+
11
+ def copy_to_clipboard(items: list[list[str]], indexed_items: list[Tuple[int, list[str]]], selections: dict, hidden_columns: set, representation: str="python", copy_hidden_cols: bool = False, separator="\t") -> None:
12
+ """
13
+ Copy selected items to clipboard.
14
+
15
+ representation (str): The representation of the rows that should be copied.
16
+ accepted values: python, csv, tsv, current view, custom_sv
17
+
18
+ """
19
+ selected_indices = [i for i, selected in selections.items() if selected]
20
+ rows_to_copy = [item for i, item in enumerate(items) if i in selected_indices]
21
+ formatted_items = [[cell for i, cell in enumerate(item) if i not in hidden_columns or copy_hidden_cols] for item in rows_to_copy]
22
+ if representation == "python":
23
+ pyperclip.copy(repr(formatted_items))
24
+ elif representation == "tsv":
25
+ pyperclip.copy("\n".join(["\t".join(row) for row in formatted_items]))
26
+ elif representation == "csv":
27
+ pyperclip.copy("\n".join([",".join(row) for row in formatted_items]))
28
+ elif representation == "custom_sv":
29
+ # Ensure that escapes are interpreted properly in separator
30
+ separator = bytes(separator, "utf-8").decode("unicode_escape")
31
+ pyperclip.copy("\n".join([separator.join(row) for row in formatted_items]))
32
+ # elif representation == "current_view":
33
+ # pyperclip.copy("\n".join([format_row(row, hidden_columns, column_widths, separator, centre_in_cols) for row in formatted_items]))
@@ -0,0 +1,78 @@
1
+ #!/bin/python
2
+ import os
3
+ import dill as pickle
4
+
5
+ def make_list_unique(l:list) -> list:
6
+ result = []
7
+ for i in l:
8
+ if i not in result:
9
+ result.append(i)
10
+ else:
11
+ result[-1] += f'_({len(result)-1})'
12
+ result.append(i)
13
+ return result
14
+
15
+ def dump_state(function_data:dict, file_path:str) -> None:
16
+ """ Dump state of list picker to file. """
17
+ exclude_keys = ["refresh_function", "get_data_startup", "get_new_data", "auto_refresh"]
18
+ function_data = {key: val for key, val in function_data.items() if key not in exclude_keys}
19
+ with open(os.path.expandvars(os.path.expanduser(file_path)), 'wb') as f:
20
+ pickle.dump(function_data, f)
21
+
22
+ def dump_data(function_data:dict, file_path:str, format="pickle") -> str:
23
+ """ Dump data from list_picker. Returns whether there was an error. """
24
+ include_keys = ["items", "header"]
25
+ function_data = {key: val for key, val in function_data.items() if key in include_keys }
26
+
27
+ try:
28
+ if format == "pickle":
29
+ with open(os.path.expandvars(os.path.expanduser(file_path)), 'wb') as f:
30
+ pickle.dump(function_data, f)
31
+ elif format == "csv":
32
+ import csv
33
+ with open(os.path.expandvars(os.path.expanduser(file_path)), mode='w', newline='') as f:
34
+ writer = csv.writer(f)
35
+ for row in [function_data["header"]] + function_data["items"]:
36
+ writer.writerow(row)
37
+ elif format == "tsv":
38
+ import csv
39
+ with open(os.path.expandvars(os.path.expanduser(file_path)), mode='w', newline='') as f:
40
+ writer = csv.writer(f, delimiter='\t')
41
+ for row in [function_data["header"]] + function_data["items"]:
42
+ writer.writerow(row)
43
+
44
+ elif format == "json":
45
+ import json
46
+ with open(os.path.expandvars(os.path.expanduser(file_path)), mode='w') as f:
47
+ json.dump([function_data["header"]]+ function_data["items"], f, indent=4)
48
+
49
+ elif format == "feather":
50
+ import pyarrow as pa
51
+ import pandas as pd
52
+ import pyarrow.feather as feather
53
+ table = pa.Table.from_pandas(pd.DataFrame(function_data["items"], columns=make_list_unique(function_data["header"])))
54
+ feather.write_feather(table, os.path.expandvars(os.path.expanduser(file_path)))
55
+
56
+ elif format == "parquet":
57
+ import pyarrow as pa
58
+ import pyarrow.parquet as pq
59
+ import pandas as pd
60
+ table = pa.Table.from_pandas(pd.DataFrame(function_data["items"], columns=make_list_unique(function_data["header"])))
61
+
62
+ pq.write_table(table, os.path.expandvars(os.path.expanduser(file_path)))
63
+ elif format == "msgpack":
64
+ import msgpack as mp
65
+ with open(os.path.expandvars(os.path.expanduser(file_path)), mode='wb') as f:
66
+ mp.dump([function_data["header"]]+ function_data["items"], f)
67
+ except Exception as e:
68
+ return str(e)
69
+ return ""
70
+
71
+
72
+
73
+ def load_state(file_path:str) -> dict:
74
+ """ Load list_picker state from dump. """
75
+ with open(os.path.expandvars(os.path.expanduser(file_path)), 'rb') as f:
76
+ loaded_data = pickle.load(f)
77
+ return loaded_data
78
+
@@ -0,0 +1,32 @@
1
+ #!/bin/python
2
+ import re
3
+ from typing import Tuple
4
+ from list_picker.utils.search_and_filter_utils import apply_filter, tokenise
5
+ import os
6
+
7
+ def filter_items(items: list[list[str]], indexed_items: list[Tuple[int, list[str]]], query: str) -> list[Tuple[int, list[str]]]:
8
+ """
9
+ Filter items based on the query.
10
+
11
+ Accepts:
12
+ regular expressions
13
+ --# to specify column to match
14
+ --i to specify case-sensitivity (it is case insensitive by default)
15
+ --v to specify inverse match
16
+
17
+ E.g.,
18
+
19
+ --1 query matches query in the 1 column
20
+
21
+
22
+ Returns indexed_items, which is a list of tuples; each tuple consists of the index and the data of the matching row in the original items list.
23
+ """
24
+
25
+
26
+ invert_filter = False
27
+ case_sensitive = False
28
+
29
+ filters = tokenise(query)
30
+
31
+ indexed_items = [(i, item) for i, item in enumerate(items) if apply_filter(item, filters)]
32
+ return indexed_items
@@ -0,0 +1,74 @@
1
+ import subprocess
2
+ import os
3
+ from typing import Tuple, Callable
4
+ import toml
5
+
6
+ def generate_columns(funcs: list, files: list) -> list[list[str]]:
7
+ """
8
+ Takes a list of functions and a list of files. Each function is run for each file and a list of lists is returned.
9
+ """
10
+ items = []
11
+ for file in files:
12
+ item = []
13
+ for func in funcs:
14
+ item.append(func(file))
15
+ items.append(item)
16
+
17
+ return items
18
+
19
+ def command_to_func(command: str) -> Callable:
20
+ """
21
+ Convert a command string to a function that will run the command.
22
+
23
+ E.g.,
24
+ mediainfo {} | grep -i format
25
+ mediainfo {} | grep -i format | head -n 1 | awk '{{print $3}}'
26
+ """
27
+
28
+ func = lambda arg: subprocess.run(command.format(repr(arg)), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode("utf-8")
29
+ return func
30
+
31
+ def load_environment(envs:dict):
32
+ """
33
+ Load environment variables from an envs dict.
34
+ """
35
+
36
+ if "cwd" in envs:
37
+ os.chdir(os.path.expandvars(os.path.expanduser(envs["cwd"])))
38
+
39
+
40
+ def read_toml(file_path) -> Tuple[dict, list, list]:
41
+ """
42
+ Read toml file and return the environment, commands and header sections.
43
+ """
44
+ with open(file_path, 'r') as file:
45
+ config = toml.load(file)
46
+
47
+ environment = config['environment'] if 'environment' in config else {}
48
+ data = config['data'] if 'data' in config else {}
49
+ commands = [command.strip() for command in data['commands']] if 'commands' in data else []
50
+ header = [header for header in data['header']] if 'header' in data else []
51
+ return environment, commands, header
52
+
53
+ def generate_list_picker_data(file_path: str) -> Tuple[list[list[str]], list[str]]:
54
+ """
55
+ Generate data for list picker based upon the toml file commands.
56
+ """
57
+ environment, commands, header = read_toml(file_path)
58
+ lines = commands
59
+
60
+ if environment:
61
+ load_environment(environment)
62
+
63
+ arg_command = lines[0]
64
+ args = subprocess.run(arg_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.decode("utf-8").split("\n")
65
+ args = [arg.strip() for arg in args if arg]
66
+
67
+ commands_list = [line.strip() for line in lines[1:]]
68
+ command_funcs = [command_to_func(command) for command in commands_list]
69
+ items = generate_columns(command_funcs, args)
70
+ items = [[args[i]] + items[i] for i in range(len(args))]
71
+ items = [[cell.strip() for cell in item] for item in items]
72
+
73
+ return items, header
74
+
@@ -0,0 +1,67 @@
1
+ #!/bin/python
2
+ import curses
3
+ from typing import Tuple
4
+ from list_picker.ui.input_field import input_field
5
+ from list_picker.utils.utils import dir_picker
6
+
7
+ def default_option_input(stdscr: curses.window, refresh_screen_function=None, starting_value:str="", field_name:str="Opts", registers={}) -> Tuple[bool, str]:
8
+ # notification(stdscr, message=f"opt required for {index}")
9
+ usrtxt = f"{starting_value} " if starting_value else ""
10
+ h, w = stdscr.getmaxyx()
11
+ # field_end = w-38 if show_footer else w-3
12
+ field_end = w-3
13
+ field_end_f = lambda: stdscr.getmaxyx()[1]-3
14
+ usrtxt, return_val = input_field(
15
+ stdscr,
16
+ usrtxt=usrtxt,
17
+ field_name=field_name,
18
+ x=lambda:2,
19
+ y=lambda: stdscr.getmaxyx()[0]-1,
20
+ max_length=field_end_f,
21
+ registers=registers,
22
+ )
23
+ if return_val: return True, usrtxt
24
+ else: return False, starting_value
25
+
26
+
27
+ def default_option_selector(stdscr: curses.window, refresh_screen_function=None, starting_value:str="", field_name:str="Opts", registers={}) -> Tuple[bool, str]:
28
+ # notification(stdscr, message=f"opt required for {index}")
29
+ usrtxt = f"{starting_value} " if starting_value else ""
30
+ h, w = stdscr.getmaxyx()
31
+ # field_end = w-38 if show_footer else w-3
32
+ field_end = w-3
33
+ field_end_f = lambda: stdscr.getmaxyx()[1]-3
34
+ usrtxt, return_val = input_field(
35
+ stdscr,
36
+ usrtxt=usrtxt,
37
+ field_name=field_name,
38
+ x=lambda:2,
39
+ y=lambda: stdscr.getmaxyx()[0]-1,
40
+ max_length=field_end_f,
41
+ registers=registers,
42
+ )
43
+ if return_val: return True, usrtxt
44
+ else: return False, starting_value
45
+
46
+
47
+ def output_file_option_selector(stdscr:curses.window, refresh_screen_function, registers={}) -> Tuple[bool, str]:
48
+ s = dir_picker()
49
+
50
+ stdscr.clear()
51
+ stdscr.refresh()
52
+ refresh_screen_function()
53
+ usrtxt = f"{s}/"
54
+ h, w = stdscr.getmaxyx()
55
+ # field_end = w-38 if show_footer else w-3
56
+ field_end_f = lambda: stdscr.getmaxyx()[1]-3
57
+ usrtxt, return_val = input_field(
58
+ stdscr,
59
+ usrtxt=usrtxt,
60
+ field_name="Save as",
61
+ x=lambda:2,
62
+ y=lambda: stdscr.getmaxyx()[0]-1,
63
+ max_length=field_end_f,
64
+ registers=registers,
65
+ )
66
+ if return_val: return True, usrtxt
67
+ else: return False, ""
@@ -0,0 +1,79 @@
1
+ import re
2
+
3
+ def apply_filter(row: list[str], filters: dict, case_sensitive: bool = False, add_highlights:bool = False, highlights: list=[]) -> bool:
4
+ """ Checks if row matches the filter. """
5
+ for col, filter_list in filters.items():
6
+ for filter in filter_list:
7
+ if case_sensitive or (filter != filter.lower()):
8
+ pattern = re.compile(filter)
9
+ else:
10
+ pattern = re.compile(filter, re.IGNORECASE)
11
+ if col == -1: # Apply filter to all columns
12
+ if not any(pattern.search(str(item)) for item in row):
13
+ return False
14
+ # return not invert_filter
15
+ elif col >= len(row) or col < 0:
16
+ return False
17
+ else:
18
+ cell_value = str(row[col])
19
+ if not pattern.search(str(cell_value)):
20
+ return False
21
+ # return invert_filter
22
+
23
+ if add_highlights:
24
+ for col, filter_list in filters.items():
25
+ for filter in filter_list:
26
+ hcol = "all" if col == -1 else col
27
+ highlights.append({
28
+ "match": filter,
29
+ "field": hcol,
30
+ "color": 10,
31
+ "type": "search",
32
+ })
33
+
34
+ return True
35
+
36
+
37
+ def tokenise(query:str) -> dict:
38
+ """ Convert query into dict consisting of filters. '--1 """
39
+ filters = {}
40
+
41
+ # tokens = re.split(r'(\s+--\d+|\s+--i)', query)
42
+ # tokens = re.split(r'((\s+|^)--\w)', query)
43
+ tokens = re.split(r'\s+', query)
44
+ tokens = [token.strip() for token in tokens if token.strip()] # Remove empty tokens
45
+ i = 0
46
+ while i < len(tokens):
47
+ token = tokens[i]
48
+ if token:
49
+ if token.startswith("--"):
50
+ flag = token
51
+ if flag == '--v':
52
+ invert_filter = True
53
+ i += 1
54
+ elif flag == '--i':
55
+ case_sensitive = True
56
+ i += 1
57
+ else:
58
+ if i+1 >= len(tokens):
59
+ break
60
+ col = int(flag[2:])
61
+ arg = tokens[i+1].strip()
62
+ try:
63
+ i+=2
64
+ re.compile(arg)
65
+ if col in filters: filters[col].append(arg)
66
+ else: filters[col] = [arg]
67
+ except:
68
+ pass
69
+ else:
70
+ try:
71
+ i += 1
72
+ re.compile(token)
73
+ if -1 in filters: filters[-1].append(token)
74
+ else: filters[-1] = [token]
75
+ except:
76
+ pass
77
+ else:
78
+ i += 1
79
+ return filters