summary refs log tree commit diff stats
path: root/README
blob: 07837688d791751e55d3e0f8a650c3d51d569b0f (plain) (blame)
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
Ranger v.1.0.4
==============

Ranger

   A keeper, guardian, or soldier who ranges over a region
   to protect the area or enforce the law.

This is the filemanager Chuck Norris the Texas Ranger would use
if he had a computer with a unix-like operating system.  (He doesn't
trust computers though and prefers to do the calculations himself.)

After all, as a professional ranger, he needs a broad overview of his
territory, and the multi-column display of ranger provides just that,
rather than restricting you to the current directory only.
You can preview the content of the selected file or directory, copy or move
files around with the VIM-like commands dd and yy, execute predefined
applications when opening a file, etc...

Everything is fully customizable and written in Python (2.6 and 3.1
compatible) using curses for the text-based user interface.


About
-----

* Author:          Roman Zimbelmann
* Email:           romanz@lavabit.com
* Website:         http://savannah.nongnu.org/projects/ranger
* Git repo:        http://git.savannah.gnu.org/cgit/ranger.git
* Version:         1.0.4


Features
--------

* Multi-column display
* Preview of the selected file/directory
* Common file operations (create/chmod/copy/delete/...)
* Quickly find files or text inside files
* VIM-like console and hotkeys
* Open files in external programs
* Mouse support
* Change the directory of your shell after exiting ranger
* Bookmarks


Dependencies
------------

* A Unix-like Operating System
* Python 2.6 or 3.1
* Python curses module  (often but not always included with Python)


Bugs and Feature Requests
-------------------------

Report bugs and feature requests on savannah:
    https://savannah.nongnu.org/bugs/?func=additem&group=ranger

Alternatively you can send an email to romanz@lavabit.com.

Please include as much relevant information as possible.
Using ranger with the --debug option will abort the program and
print tracebacks rather than a red message in the statusbar.
If this applies to you, please include such a traceback in your report.


Getting Started
---------------

If you just want to check out ranger without installing it, type

    ./ranger.py --clean

in the top directory of ranger.  By using the --clean switch, it will
leave no trace on your system whatsoever.

To properly install it, follow the instructions in the INSTALL file,
then type:

    ranger

You should see 4 columns.  The third is the directory where you are at
the moment.  To the left, there are the directories above the current
working directory, and the column on the right is a preview of the selected
file/directory.

Now use the arrow keys to navigate, press enter to open a file.

A list of commands with short descriptions can be viewed by
pressing "?" inside the program and following the instructions.
The file ranger/defaults/keys.py contains all key combinations, so that's
another place you may want to check out.


Opening Files with Ranger
-------------------------

If you use the same applications like me, you'll be able to open
files by pressing the right arrow key.  If not, you will have to
specify them in ranger/defaults/apps.py.  It's explained
in the docstrings how exactly to do that.

Once you've set up your applications, you can also use ranger to
open files from the shell:
    ranger blabla.pdf


Customizing Ranger
------------------

The file ranger/defaults/options.py contains most of the options.
apps.py defines how files are run, keys.py defines keybindings.

The files in ranger/defaults/ can be copied into ~/.ranger/ for per-user
modifications.  Colorschemes can be placed in ~/.ranger/colorschemes.

The configuration files should be self-explanatory.  If you need more
information, check out the source code.

Also, see the file HACKING for more detailed instructions on
modifying the program.


Tips
----

Change the directory of your parent shell when you exit ranger:

ranger() {
    $(which ranger) $@ &&
    cd "$(grep \^\' ~/.ranger/bookmarks | cut -b3-)"
}

This can be put into your ~/.bashrc or something similar.
uted during 'tailor-exit-descriptor'. # Its value is its output, computed during stop and available to the test. == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # Configure an exit-descriptor for a call pushing 'nbytes' bytes of args to # the stack. # Ugly that we need to know the size of args. Don't allocate variables between # tailor-exit-descriptor and the call it's for. tailor-exit-descriptor: # ed: (addr exit-descriptor), nbytes: int # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax 51/push-ecx # eax = nbytes 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0xc/disp8 . # copy *(ebp+12) to eax # Let X be the value of esp in the caller, before the call to tailor-exit-descriptor. # The return address for a call in the caller's body will be at: # X-8 if the caller takes 4 bytes of args for the exit-descriptor (add 4 bytes for the return address) # X-12 if the caller takes 8 bytes of args # ..and so on # That's the value we need to return: X-nbytes-4 # # However, we also need to account for the perturbance to esp caused by the # call to tailor-exit-descriptor. It pushes 8 bytes of args followed by 4 # bytes for the return address and 4 bytes to push ebp above. # So ebp at this point is X-16. # # So the return address for the next call in the caller is: # ebp+8 if the caller takes 4 bytes of args # ebp+4 if the caller takes 8 bytes of args # ebp if the caller takes 12 bytes of args # ebp-4 if the caller takes 16 bytes of args # ..and so on # That's ebp+12-nbytes. # option 1: 6 + 3 bytes #? 2d/subtract 3/mod/direct 0/rm32/eax . . . . . 8/imm32 # subtract from eax #? 8d/copy-address 0/mod/indirect 4/rm32/sib 5/base/ebp 0/index/eax . 0/r32/eax . . # copy ebp+eax to eax # option 2: 2 + 4 bytes f7 3/subop/negate 3/mod/direct 0/rm32/eax . . . . . . # negate eax 8d/copy-address 1/mod/*+disp8 4/rm32/sib 5/base/ebp 0/index/eax . 0/r32/eax 0xc/disp8 . # copy ebp+eax+12 to eax # copy eax to ed->target 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx 89/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy eax to *ecx # initialize ed->value c7 0/subop/copy 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # copy to *(ecx+4) $tailor-exit-descriptor:end: # . restore registers 59/pop-to-ecx 58/pop-to-eax # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return stop: # ed: (addr exit-descriptor), value: int # no prologue; one way or another, we're going to clobber registers # eax = ed 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none . 0/r32/eax 4/disp8 . # copy *(esp+4) to eax # if (ed->target == 0) really exit 81 7/subop/compare 0/mod/indirect 0/rm32/eax . . . . . 0/imm32 # compare *eax 75/jump-if-!= $stop:fake/disp8 # . syscall(exit, value) 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none . 3/r32/ebx 8/disp8 . # copy *(esp+8) to ebx b8/copy-to-eax 1/imm32/exit cd/syscall 0x80/imm8 $stop:fake: # otherwise: # ed->value = value+1 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/esp 4/index/none . 1/r32/ecx 8/disp8 . # copy *(esp+8) to ecx 41/increment-ecx 89/copy 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy ecx to *(eax+4) # perform a non-local jump to ed->target 8b/copy 0/mod/indirect 0/rm32/eax . . . 4/r32/esp . . # copy *eax to esp $stop:end: c3/return # doesn't return to caller test-stop-skips-returns-on-exit: # This looks like the standard prologue, but is here for different reasons. # A function calling 'stop' can't rely on ebp persisting past the call. # # Use ebp here as a stable base to refer to locals and arguments from in the # presence of push/pop/call instructions. # *Don't* use ebp as a way to restore esp. 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # Make room for an exit descriptor on the stack. That's almost always the # right place for it, available only as long as it's legal to use. Once this # containing function returns we'll need a new exit descriptor. # var ed/eax: exit-descriptor 68/push 0/imm32 68/push 0/imm32 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax # Size the exit-descriptor precisely for the next call below, to _test-stop-1. # tailor-exit-descriptor(ed, 4) # . . push args 68/push 4/imm32/nbytes-of-args-for-_test-stop-1 50/push-eax # . . call e8/call tailor-exit-descriptor/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . _test-stop-1(ed) # . . push args 50/push-eax # . . call e8/call _test-stop-1/disp32 # registers except esp may be clobbered at this point # restore args 58/pop-to-eax # check that _test-stop-1 tried to call exit(1) # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 # . . push args 68/push "F - test-stop-skips-returns-on-exit"/imm32 68/push 2/imm32 # . . push ed->value ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue # don't restore esp from ebp; manually reclaim locals 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5d/pop-to-ebp c3/return _test-stop-1: # ed: (addr exit-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # _test-stop-2(ed) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call _test-stop-2/disp32 # should never get past this point $_test-stop-1:dead-end: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp # signal test failed: check-ints-equal(1, 0, msg) # . . push args 68/push "F - test-stop-skips-returns-on-exit"/imm32 68/push 0/imm32 68/push 1/imm32 # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return _test-stop-2: # ed: (addr exit-descriptor) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . stop(ed, 1) # . . push args 68/push 1/imm32 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call stop/disp32 # should never get past this point $_test-stop-2:dead-end: # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return # . . vim:nowrap:textwidth=0