/
switcher.py
142 lines (122 loc) · 4.98 KB
/
switcher.py
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
# (see spyder/__init__.py for details)
"""
Utils to handle Switcher elements.
"""
# Standard library imports
import os
import os.path as osp
import sys
# Local imports
from spyder.config.base import _
from spyder.py3compat import iteritems
from spyder.utils.icon_manager import ima
def shorten_paths(path_list, is_unsaved):
"""
Takes a list of paths and tries to "intelligently" shorten them all. The
aim is to make it clear to the user where the paths differ, as that is
likely what they care about. Note that this operates on a list of paths
not on individual paths.
If the path ends in an actual file name, it will be trimmed off.
"""
# TODO: at the end, if the path is too long, should do a more dumb kind of
# shortening, but not completely dumb.
# Convert the path strings to a list of tokens and start building the
# new_path using the drive
path_list = path_list[:] # Make a local copy
new_path_list = []
common_prefix = osp.dirname(osp.commonprefix(path_list))
for ii, (path, is_unsav) in enumerate(zip(path_list, is_unsaved)):
if is_unsav:
new_path_list.append(_('unsaved file'))
path_list[ii] = None
else:
drive, path = osp.splitdrive(osp.dirname(path))
new_path_list.append(drive + osp.sep)
path_list[ii] = [part for part in path.split(osp.sep) if part]
def recurse_level(level_idx):
sep = os.sep
# If toks are all empty we need not have recursed here
if not any(level_idx.values()):
return
# Firstly, find the longest common prefix for all in the level
# s = len of longest common prefix
sample_toks = list(level_idx.values())[0]
if not sample_toks:
s = 0
else:
for s, sample_val in enumerate(sample_toks):
if not all(len(toks) > s and toks[s] == sample_val
for toks in level_idx.values()):
break
# Shorten longest common prefix
if s == 0:
short_form = ''
else:
if s == 1:
short_form = sample_toks[0]
elif s == 2:
short_form = sample_toks[0] + sep + sample_toks[1]
else:
short_form = "..." + sep + sample_toks[s-1]
for idx in level_idx:
new_path_list[idx] += short_form + sep
level_idx[idx] = level_idx[idx][s:]
# Group the remaining bit after the common prefix, shorten, and recurse
while level_idx:
k, group = 0, level_idx # k is length of the group's common prefix
while True:
# Abort if we've gone beyond end of one or more in the group
prospective_group = {idx: toks for idx, toks
in group.items() if len(toks) == k}
if prospective_group:
if k == 0: # we spit out the group with no suffix
group = prospective_group
break
# Only keep going if all n still match on the kth token
_, sample_toks = next(iteritems(group))
prospective_group = {idx: toks for idx, toks
in group.items()
if toks[k] == sample_toks[k]}
if len(prospective_group) == len(group) or k == 0:
group = prospective_group
k += 1
else:
break
_, sample_toks = next(iteritems(group))
if k == 0:
short_form = ''
elif k == 1:
short_form = sample_toks[0]
elif k == 2:
short_form = sample_toks[0] + sep + sample_toks[1]
else: # k > 2
short_form = sample_toks[0] + "..." + sep + sample_toks[k-1]
for idx in group.keys():
new_path_list[idx] += short_form + (sep if k > 0 else '')
del level_idx[idx]
recurse_level({idx: toks[k:] for idx, toks in group.items()})
recurse_level({i: pl for i, pl in enumerate(path_list) if pl})
if common_prefix:
result_paths = []
for path in new_path_list:
path_elements = path.rstrip(os.sep).split(common_prefix)
if len(path_elements) > 1:
result_paths.append("...{}".format(path_elements[-1]))
else:
result_paths.append(path)
else:
result_paths = [path.rstrip(os.sep) for path in new_path_list]
return result_paths
def get_file_icon(path):
"""Get icon for file by extension."""
if sys.platform == 'darwin':
scale_factor = 0.9
elif os.name == 'nt':
scale_factor = 0.8
else:
scale_factor = 0.6
return ima.get_icon_by_extension_or_type(path, scale_factor)