about summary refs log tree commit diff stats
path: root/ranger
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2010-05-06 00:02:47 +0200
committerhut <hut@lavabit.com>2010-05-06 00:02:47 +0200
commit2bd40e06fac5f02f27dbe91a4a48805ee10db60e (patch)
tree95bc4a24e69d947727151632413ea4383776b63e /ranger
parentc6953a55e46aee37a854dff3be5d965b19a7341a (diff)
downloadranger-2bd40e06fac5f02f27dbe91a4a48805ee10db60e.tar.gz
fsobject: a couple of optimizations
Diffstat (limited to 'ranger')
-rw-r--r--ranger/fsobject/directory.py70
-rw-r--r--ranger/fsobject/fsobject.py3
2 files changed, 44 insertions, 29 deletions
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index ca071510..9d12af28 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -14,9 +14,13 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import os.path
+import stat
+from stat import S_ISLNK, S_ISDIR
+from os.path import join, isdir, basename
 from collections import deque
 from time import time
 
+from ranger.ext.mount_path import mount_path
 from ranger.fsobject import BAD_INFO, File, FileSystemObject
 from ranger.shared import SettingsAware
 from ranger.ext.accumulator import Accumulator
@@ -34,6 +38,18 @@ def sort_by_directory(path):
 	"""returns 0 if path is a directory, otherwise 1 (for sorting)"""
 	return 1 - path.is_directory
 
+def accept_file(fname, hidden_filter, name_filter):
+	if hidden_filter:
+		try:
+			if hidden_filter.search(fname):
+				return False
+		except:
+			if hidden_filter in fname:
+				return False
+	if name_filter and name_filter not in fname:
+		return False
+	return True
+
 class Directory(FileSystemObject, Accumulator, SettingsAware):
 	is_directory = True
 	enterable = False
@@ -65,11 +81,11 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 		'type': lambda path: path.mimetype,
 	}
 
-	def __init__(self, path):
+	def __init__(self, path, preload=None):
 		assert not os.path.isfile(path), "No directory given!"
 
 		Accumulator.__init__(self)
-		FileSystemObject.__init__(self, path)
+		FileSystemObject.__init__(self, path, preload=preload)
 
 		self.marked_items = list()
 
@@ -144,33 +160,19 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 		in each iteration.
 		"""
 
-		# log("generating loader for " + self.path + "(" + str(id(self)) + ")")
-		from os.path import join, isdir, basename
-		from os import listdir
-		import ranger.ext.mount_path
-
 		self.loading = True
 		self.load_if_outdated()
 
 		try:
 			if self.exists and self.runnable:
 				yield
-				self.mount_path = ranger.ext.mount_path.mount_path(self.path)
-
-				filenames = []
-				for fname in listdir(self.path):
-					if not self.settings.show_hidden:
-						hfilter = self.settings.hidden_filter
-						if hfilter:
-							if isinstance(hfilter, str) and hfilter in fname:
-								continue
-							if hasattr(hfilter, 'search') and \
-								hfilter.search(fname):
-								continue
-					if isinstance(self.filter, str) and self.filter \
-							and self.filter not in fname:
-						continue
-					filenames.append(join(self.path, fname))
+				self.mount_path = mount_path(self.path)
+
+				hidden_filter = not self.settings.show_hidden \
+						and self.settings.hidden_filter
+				filenames = [join(self.path, fname) \
+						for fname in os.listdir(self.path) \
+						if accept_file(fname, hidden_filter, self.filter)]
 				yield
 
 				self.load_content_mtime = os.stat(self.path).st_mtime
@@ -179,13 +181,24 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 
 				files = []
 				for name in filenames:
-					if isdir(name):
+					file_lstat = os.lstat(name)
+					try:
+						if S_ISLNK(file_lstat.st_mode):
+							file_stat = os.stat(name)
+						else:
+							file_stat = file_lstat
+						stats = (file_stat, file_lstat)
+						is_a_dir = S_ISDIR(file_stat.st_mode)
+					except:
+						stats = None
+						is_a_dir = False
+					if is_a_dir:
 						try:
 							item = self.fm.env.get_directory(name)
 						except:
-							item = Directory(name)
+							item = Directory(name, preload=stats)
 					else:
-						item = File(name)
+						item = File(name, preload=stats)
 					item.load_if_outdated()
 					files.append(item)
 					yield
@@ -199,9 +212,10 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 				self._clear_marked_items()
 				for item in self.files:
 					if item.path in marked_paths:
-						self.mark_item(item, True)
+						item._mark(True)
+						self.marked_items.append(item)
 					else:
-						self.mark_item(item, False)
+						item._mark(False)
 
 				self.sort()
 
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index 18024743..5b64cd75 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -69,7 +69,7 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 	container = False
 	mimetype_tuple = ()
 
-	def __init__(self, path):
+	def __init__(self, path, preload=None):
 		MimeTypeAware.__init__(self)
 
 		path = abspath(path)
@@ -78,6 +78,7 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 		self.basename_lower = self.basename.lower()
 		self.dirname = dirname(path)
 		self.realpath = self.path
+		self.preload = preload
 
 		try:
 			lastdot = self.basename.rindex('.') + 1
ry.md?h=main&id=9a524793ee01ce47f3963768559a0d6c348631c5'>9a524793 ^
cec5ef31 ^
9a524793 ^
cec5ef31 ^

9a524793 ^
cec5ef31 ^

9a524793 ^
cec5ef31 ^



9a524793 ^
cec5ef31 ^


9a524793 ^
cec5ef31 ^

9a524793 ^
cec5ef31 ^
9a524793 ^
cec5ef31 ^




9a524793 ^
cec5ef31 ^
9a524793 ^
cec5ef31 ^







9a524793 ^
02b7f9bd ^
9a524793 ^


cec5ef31 ^

4b57c101 ^

cec5ef31 ^





e6b42204 ^

cec5ef31 ^
9a524793 ^
cec5ef31 ^
















b9883225 ^



cec5ef31 ^























































































b9883225 ^



















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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249



                                                  



                                                                             








                                                                                
 
                                                                           
                                                                        
                               










                                                                                                                 
                                      

                                  
                                             
 

                                                                            
 

                                                                               
 
             
 

                                                                               
 
                                                                           
 
                         
 









                                                                                  
 
               
 

                                                                             
 

                                                                            
 



                                                                                 
 


                                                                       
 

                                                              
 
           
 




                                                                           
 
            
 







                                                                              
 
                                                                             


                                                                               

                                                                             

                                                                          





                                                                           

                                                                              
 
                                                    
















                                                                                



                                                                            























































































                                                                                



















                                                                               
## Reference documentation on available primitives

### Data Structures

For memory safety, the following data structures are opaque and only modified
using functions described further down. I still find it useful to understand
how they work under the hood.

- Handles: addresses to objects allocated on the heap. They're augmented with
  book-keeping to guarantee memory-safety, and so cannot be stored in registers.
  See [mu.md](mu.md) for details, but in brief:
    - You need `addr` values to access data they point to.
    - You can't store `addr` values in other types. They're temporary.
    - You can store `handle` values in other types.
    - To convert `handle` to `addr`, use `lookup`.
    - Reclaiming memory (currently unimplemented) invalidates all `addr`
      values.

- Arrays: size-prefixed regions of memory containing multiple elements of a
  single type. Contents are preceded by 4 bytes (32 bits) containing the
  `size` of the array in bytes.

- Slices: a pair of 32-bit addresses denoting a [half-open](https://en.wikipedia.org/wiki/Interval_(mathematics))
  \[`start`, `end`) interval to live memory with a consistent lifetime.

  Invariant: `start` <= `end`

- Streams: strings prefixed by 32-bit `write` and `read` indexes that the next
  write or read goes to, respectively.

  - offset 0: write index
  - offset 4: read index
  - offset 8: size of array (in bytes)
  - offset 12: start of array data

  Invariant: 0 <= `read` <= `write` <= `size`

  By default, writes to a stream abort if it's full. Reads to a stream abort
  if it's empty.

- Graphemes: 32-bit fragments of utf-8 that encode a single Unicode code-point.
- Code-points: 32-bit integers representing a Unicode character.

### Functions

The most useful functions from 400.mu and later .mu files. Look for definitions
(using `ctags`) to see type signatures.

- `abort`: print a message in red on the bottom left of the screen and halt

#### assertions for tests

- `check`: fails current test if given boolean is false (`= 0`).
- `check-not`: fails current test if given boolean isn't false (`!= 0`).
- `check-ints-equal`: fails current test if given ints aren't equal.
- `check-strings-equal`: fails current test if given strings have different bytes.
- `check-stream-equal`: fails current test if stream's data doesn't match
  string in its entirety. Ignores the stream's read index.
- `check-array-equal`: fails if an array's elements don't match what's written
  in a whitespace-separated string.
- `check-next-stream-line-equal`: fails current test if next line of stream
  until newline doesn't match string.

#### predicates

- `handle-equal?`: checks if two handles point at the identical address. Does
  not compare payloads at their respective addresses.

- `array-equal?`: checks if two arrays (of ints only for now) have identical
  elements.

- `string-equal?`: compares two strings.
- `stream-data-equal?`: compares a stream with a string.
- `next-stream-line-equal?`: compares with string the next line in a stream, from
  `read` index to newline.

- `slice-empty?`: checks if the `start` and `end` of a slice are equal.
- `slice-equal?`: compares a slice with a string.
- `slice-starts-with?`: compares the start of a slice with a string.

- `stream-full?`: checks if a write to a stream would abort.
- `stream-empty?`: checks if a read from a stream would abort.

#### arrays

- `populate`: allocates space for `n` objects of the appropriate type.
- `copy-array`: allocates enough space and writes out a copy of an array of
  some type.
- `slice-to-string`: allocates space for an array of bytes and copies the
  slice into it.

#### streams

- `populate-stream`: allocates space in a stream for `n` objects of the
  appropriate type.
- `write-to-stream`: writes arbitrary objects to a stream of the appropriate
  type.
- `read-from-stream`: reads arbitrary objects from a stream of the appropriate
  type.
- `stream-to-array`: allocates just enough space and writes out a stream's
  data between its read index (inclusive) and write index (exclusive).

- `clear-stream`: resets everything in the stream to `0` (except its `size`).
- `rewind-stream`: resets the read index of the stream to `0` without modifying
  its contents.

- `write`: writes a string into a stream of bytes. Doesn't support streams of
  other types.
- `try-write`: writes a string into a stream of bytes if possible. Doesn't
  support streams of other types.
- `write-stream`: concatenates one stream into another.
- `write-slice`: writes a slice into a stream of bytes.
- `append-byte`: writes a single byte into a stream of bytes.
- `append-byte-hex`: writes textual representation of lowest byte in hex to
  a stream of bytes. Does not write a '0x' prefix.
- `read-byte`: reads a single byte from a stream of bytes.
- `read-grapheme`: reads a single unicode grapheme (up to 4 bytes containing a
  single code-point encoded in utf-8) from a stream of bytes.

#### reading/writing hex representations of integers

- `write-int32-hex`
- `hex-int?`: checks if a slice contains an int in hex. Supports '0x' prefix.
- `parse-hex-int`: reads int in hex from string
- `parse-hex-int-from-slice`: reads int in hex from slice
- `parse-array-of-ints`: reads in multiple ints in hex, separated by whitespace.
- `hex-digit?`: checks if byte is in [0, 9] or [a, f] (lowercase only)

- `write-int32-decimal`
- `parse-decimal-int`
- `parse-decimal-int-from-slice`
- `parse-decimal-int-from-stream`
- `parse-array-of-decimal-ints`
- `decimal-digit?`: checks if byte is in [0, 9]

#### printing to screen

`pixel-on-real-screen` draws a single pixel in one of 256 colors.

All text-mode screen primitives require a screen object, which can be either
the real screen on the computer or a fake screen for tests.

The real screen on the Mu computer can currently display only ASCII characters,
though it's easy to import more of the font. There is only one font. All
graphemes are 8 pixels wide and 16 pixels tall. These constraints only apply
to the real screen.

- `draw-grapheme`: draws a single grapheme at a given coordinate, with given
  foreground and background colors.
- `render-grapheme`: like `draw-grapheme` and can also handle newlines
  assuming text is printed left-to-right, top-to-bottom.
- `draw-code-point`
- `clear-screen`

- `draw-text-rightward`: draws a single line of text, stopping when it reaches
  either the provided bound or the right screen margin.
- `draw-stream-rightward`
- `draw-text-rightward-over-full-screen`: does not provide a bound.
- `draw-text-wrapping-right-then-down`: draws multiple lines of text on screen
  with simplistic word-wrap (no hyphenation) within (x, y) bounds.
- `draw-stream-wrapping-right-then-down`
- `draw-text-wrapping-right-then-down-over-full-screen`
- `draw-int32-hex-wrapping-right-then-down`
- `draw-int32-hex-wrapping-right-then-down-over-full-screen`
- `draw-int32-decimal-wrapping-right-then-down`
- `draw-int32-decimal-wrapping-right-then-down-over-full-screen`

Similar primitives for writing text top-to-bottom, left-to-right.

- `draw-text-downward`
- `draw-stream-downward`
- `draw-text-wrapping-down-then-right`
- `draw-stream-wrapping-down-then-right`
- `draw-text-wrapping-down-then-right-over-full-screen`
- `draw-int32-hex-wrapping-down-then-right`
- `draw-int32-hex-wrapping-down-then-right-over-full-screen`
- `draw-int32-decimal-wrapping-down-then-right`
- `draw-int32-decimal-wrapping-down-then-right-over-full-screen`

Screens remember the current cursor position.

- `cursor-position`
- `set-cursor-position`
- `draw-grapheme-at-cursor`
- `draw-code-point-at-cursor`
- `draw-cursor`: highlights the current position of the cursor. Programs must
  pass in the grapheme to draw at the cursor position, and are responsible for
  clearing the highlight when the cursor moves.
- `move-cursor-left`, `move-cursor-right`, `move-cursor-up`, `move-cursor-down`.
  These primitives always silently fail if the desired movement would go out
  of screen bounds.
- `move-cursor-to-left-margin-of-next-line`
- `move-cursor-rightward-and-downward`: move cursor one grapheme to the right

- `draw-text-rightward-from-cursor`
- `draw-text-wrapping-right-then-down-from-cursor`
- `draw-text-wrapping-right-then-down-from-cursor-over-full-screen`
- `draw-int32-hex-wrapping-right-then-down-from-cursor`
- `draw-int32-hex-wrapping-right-then-down-from-cursor-over-full-screen`
- `draw-int32-decimal-wrapping-right-then-down-from-cursor`
- `draw-int32-decimal-wrapping-right-then-down-from-cursor-over-full-screen`

- `draw-text-wrapping-down-then-right-from-cursor`
- `draw-text-wrapping-down-then-right-from-cursor-over-full-screen`

Assertions for tests:

- `check-screen-row`: compare a screen from the left margin of a given row
  index with a string. The row index counts downward from 0 at the top of the
  screen. String can be smaller or larger than a single row, and defines the
  region of interest. Strings longer than a row wrap around to the left margin
  of the next screen row. Currently assumes text is printed left-to-right on
  the screen.
- `check-screen-row-from`: compare a fragment of a screen (left to write, top
  to bottom) starting from a given (x, y) coordinate with an expected string.
  Currently assumes text is printed left-to-right and top-to-bottom on the
  screen.
- `check-screen-row-in-color`: like `check-screen-row` but:
  - also compares foreground color
  - ignores screen locations where the expected string contains spaces
- `check-screen-row-in-color-from`
- `check-screen-row-in-background-color`
- `check-screen-row-in-background-color-from`
- `check-background-color-in-screen-row`: unlike previous functions, this
  doesn't check screen contents, only background color. Ignores background
  color where expected string contains spaces, and compares background color
  where expected string does not contain spaces. Never compares the character
  at any screen location.
- `check-background-color-in-screen-row-from`

#### events

`read-key` reads a single key from the keyboard and returns it if it exists.
Returns 0 if no key has been pressed.

`read-mouse-event` returns a recent change in x and y coordinate.

Mu doesn't currently support interrupt-based mouse events.

#### persistent storage

`load-sector` synchronously reads a single _sector_ from a _disk_ of persistent
storage. The disk must follow the ATA specification with a 28-bit sector
address. Each sector is 512 bytes. Therefore, Mu currently supports ATA hard
disks of up to 128GB capacity.

Similarly, `store-sector` synchronously writes a single sector to disk.

Mu doesn't currently support asynchronous transfers to or from a disk.