7 from ui
.utils
import human_unit
, short_string
8 from ui
.char_matrix
import CharMatrix
, MASK
, SELECTED
9 from core
.pysize_fs_tree
import pysize_tree
13 def __init__(self
, win
, options
, args
):
15 self
.max_depth
= options
.max_depth
16 self
.root_path
= args
[0]
17 self
._set
_path
(self
.root_path
)
20 def _init_curses(self
):
21 curses
.use_default_colors()
26 return sum(map(lambda n
: 1<<n
, positions
))
28 self
.MATRIX_TO_CURSES
= {
30 dots(3, 4, 5): curses
.ACS_HLINE
,
31 dots(1, 4, 7): curses
.ACS_VLINE
,
32 dots(1, 3, 4, 5, 7): curses
.ACS_PLUS
,
33 dots(4, 5, 7): curses
.ACS_ULCORNER
,
34 dots(3, 4, 7): curses
.ACS_URCORNER
,
35 dots(1, 4, 5): curses
.ACS_LLCORNER
,
36 dots(1, 3, 4): curses
.ACS_LRCORNER
,
37 dots(3, 4, 5, 7): curses
.ACS_TTEE
,
38 dots(1, 3, 4, 5): curses
.ACS_BTEE
,
39 dots(1, 4, 5, 7): curses
.ACS_LTEE
,
40 dots(1, 3, 4, 7): curses
.ACS_RTEE
44 self
.status_win
= curses
.newwin(0, 0)
45 self
.panel
= curses
.newwin(0, 0)
48 print 'Cannot create windows'
52 """Called when the terminal size changes."""
53 self
.height
, self
.width
= self
.window
.getmaxyx()
54 self
.height
-= 1 # Status bar
56 self
.status_win
.resize(1, self
.width
)
57 self
.status_win
.mvwin(self
.height
, 0)
58 self
.panel
.resize(self
.height
, self
.width
)
59 self
._set
_path
(self
.path
)
65 self
.tree
= pysize_tree(self
.path
, self
.max_depth
,
67 self
.need_tree
= False
68 if not self
.tree
.root
:
72 self
._draw
_matrix
(CharMatrix(self
.width
, self
.height
, self
.tree
,
76 self
.status_win
.erase()
77 self
.status_win
.hline(0, 0, ord(' ') | curses
.A_REVERSE
, self
.width
)
79 status_line
= self
.path
+ ' ' + human_unit(self
.tree
.root
.size
)
80 if len(status_line
) + len(END
) >= self
.width
:
81 status_line
= short_string(status_line
, self
.width
- 1)
84 self
.status_win
.addstr(status_line
, curses
.A_REVERSE
)
85 self
.status_win
.refresh()
92 except curses
.error
, e
:
96 def _set_path(self
, path
):
97 self
.selected_item
= None
100 self
.need_tree
= True
102 def _next_step(self
):
103 sequel
= self
.selected_item
.get_fullpath()[len(self
.path
) + 1:]
104 sequel
= sequel
.split('/', 1)[0]
105 self
._set
_path
(os
.path
.join(self
.path
, sequel
))
107 def _select(self
, function
):
108 if not self
.selected_item
:
109 if self
.tree
.root
.get_children():
110 self
.selected_item
= self
.tree
.root
.get_children()[0]
112 selected
= function(self
.selected_item
)
114 if function
== self
.tree
.get_first_child
and \
115 self
.selected_item
.is_dir():
116 # Browsing to the right
119 self
.selected_item
= selected
120 if self
.selected_item
is self
.tree
.root
:
121 # Browsing to the left
122 if not os
.path
.samefile(self
.path
, self
.root_path
):
123 parent
= os
.path
.dirname(self
.selected_item
.get_fullpath())
124 self
._set
_path
(parent
)
126 self
.selected_item
= None
129 if self
.selected_item
and self
.selected_item
.is_dir():
130 self
._set
_path
(self
.selected_item
.get_fullpath())
133 """The main dispatcher."""
138 curses
.KEY_RESIZE
: lambda:
141 curses
.KEY_DOWN
: lambda:
142 self
._select
(self
.tree
.get_next_sibling
),
144 curses
.KEY_UP
: lambda:
145 self
._select
(self
.tree
.get_previous_sibling
),
147 curses
.KEY_LEFT
: lambda:
148 self
._select
(self
.tree
.get_parent
),
150 curses
.KEY_RIGHT
: lambda:
151 self
._select
(self
.tree
.get_first_child
),
159 c
= self
.window
.getch()
160 action
= key_bindings
.get(c
, lambda: None)
163 def _draw_matrix(self
, matrix
):
164 for (y
, line
) in enumerate(matrix
.matrix
):
165 for (x
, char
) in enumerate(line
):
166 if isinstance(char
, int):
167 selected
= (char
& SELECTED
) != 0
169 char
= self
.MATRIX_TO_CURSES
[char
]
171 char |
= curses
.A_REVERSE
172 self
.panel
.insch(y
, x
, char
)
174 char
= char
.encode('UTF-8')
175 self
.panel
.insstr(y
, x
, char
)
177 def _run_curses(win
, options
, args
):
178 app
= _CursesApp(win
, options
, args
)
181 def run(options
, args
):
182 locale
.setlocale(locale
.LC_ALL
, '')
183 curses
.wrapper(_run_curses
, options
, args
)
186 return sys
.stdin
.isatty() and sys
.stdout
.isatty()