diff options
-rw-r--r-- | doc/ranger.1 | 374 | ||||
-rw-r--r-- | doc/ranger.pod | 335 | ||||
-rw-r--r-- | examples/README | 2 | ||||
-rw-r--r-- | examples/plugin_chmod_keybindings.py | 18 | ||||
-rw-r--r-- | examples/plugin_file_filter.py | 17 | ||||
-rw-r--r-- | examples/plugin_hello_world.py | 21 | ||||
-rw-r--r-- | examples/plugin_new_macro.py | 17 | ||||
-rw-r--r-- | examples/plugin_new_sorting_method.py | 7 | ||||
-rw-r--r-- | examples/plugin_skip_default_rc.py | 9 | ||||
-rw-r--r-- | examples/rifle_different_file_opener.conf | 7 | ||||
-rw-r--r-- | ranger/api/__init__.py | 28 | ||||
-rw-r--r-- | ranger/config/commands.py | 8 | ||||
-rw-r--r-- | ranger/config/options.py | 216 | ||||
-rw-r--r-- | ranger/config/rc.conf | 119 | ||||
-rw-r--r-- | ranger/container/history.py | 2 | ||||
-rw-r--r-- | ranger/container/settingobject.py | 46 | ||||
-rw-r--r-- | ranger/core/actions.py | 29 | ||||
-rw-r--r-- | ranger/core/fm.py | 12 | ||||
-rw-r--r-- | ranger/core/main.py | 45 | ||||
-rw-r--r-- | ranger/core/shared.py | 32 | ||||
-rwxr-xr-x | ranger/ext/rifle.py | 2 | ||||
-rw-r--r-- | ranger/gui/ansi.py | 55 | ||||
-rw-r--r-- | ranger/gui/colorscheme.py | 29 |
23 files changed, 829 insertions, 601 deletions
diff --git a/doc/ranger.1 b/doc/ranger.1 index cfdbd455..7bf542fd 100644 --- a/doc/ranger.1 +++ b/doc/ranger.1 @@ -124,7 +124,7 @@ .\" ======================================================================== .\" .IX Title "RANGER 1" -.TH RANGER 1 "ranger-1.5.5" "08/10/2012" "ranger manual" +.TH RANGER 1 "ranger-1.5.5" "12/03/2012" "ranger manual" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -185,7 +185,7 @@ Open ranger with \fItargetfile\fR selected. .IX Item "--copy-config=file" Create copies of the default configuration files in your local configuration directory. Existing ones will not be overwritten. Possible values: \fIall\fR, -\&\fIrc\fR, \fIapps\fR, \fIcommands\fR, \fIoptions\fR, \fIscope\fR. +\&\fIrc\fR, \fIcommands\fR, \fIscope\fR. .IP "\fB\-\-list\-unused\-keys\fR" 14 .IX Item "--list-unused-keys" List common keys which are not bound to any action in the \*(L"browser\*(R" context. @@ -220,6 +220,8 @@ Print the version and exit. Print a list of options and exit. .SH "CONCEPTS" .IX Header "CONCEPTS" +This part explains how certain parts of ranger work and how they can be used +efficiently. .SS "\s-1TAGS\s0" .IX Subsection "TAGS" Tags are single characters which are displayed left of a filename. You can use @@ -272,7 +274,7 @@ are in different directories: .Ve .PP Macros for file paths are generally shell-escaped so they can be used in the -:shell command. +\&\f(CW\*(C`shell\*(C'\fR command. .SS "\s-1BOOKMARKS\s0" .IX Subsection "BOOKMARKS" Type \fBm<key>\fR to bookmark the current directory. You can re-enter this @@ -285,40 +287,81 @@ to the last directory. So typing \*(L"``\*(R" gets you back to where you were be Bookmarks are selectable when tabbing in the :cd command. .PP Note: The bookmarks ' (Apostrophe) and ` (Backtick) are the same. +.SS "\s-1RIFLE\s0" +.IX Subsection "RIFLE" +Rifle is the file opener of ranger. It can be used as a standalone program or +a python module. It is located at \fIranger/ext/rifle.py\fR. In contrast to +other, more simple file openers, rifle can automatically find installed +programs so it can be used effectively out of the box on a variety of systems. +.PP +It's configured in \fIrifle.conf\fR through a list of conditions and commands. +For each line the conditions are checked and if they are met, the respective +command is taken into consideration. By default, simply the first matching +rule is used. In ranger, you can list and choose rules by typing \*(L"r\*(R" or simply +by typing \*(L"<rulenumber><enter>\*(R". If you use rifle standalone, you can list all +rules with the \*(L"\-l\*(R" option and pick a rule with \*(L"\-p <number>\*(R". +.PP +The rules, along with further documentation, are contained in +\&\fIranger/config/rifle.conf\fR. .SS "\s-1FLAGS\s0" .IX Subsection "FLAGS" Flags give you a way to modify the behavior of the spawned process. They are -used in the commands :open_with (key \*(L"r\*(R") and :shell (key \*(L"!\*(R"). +used in the commands \f(CW\*(C`:open_with\*(C'\fR (key \*(L"r\*(R") and \f(CW\*(C`:shell\*(C'\fR (key \*(L"!\*(R"). .PP -.Vb 7 -\& s Silent mode. Output will be discarded. -\& d Detach the process. (Run in background) -\& p Redirect output to the pager -\& w Wait for an Enter\-press when the process is done +.Vb 4 +\& f Fork the process. (Run in background) \& c Run the current file only, instead of the selection \& r Run application with root privilege (requires sudo) \& t Run application in a new terminal window .Ve .PP -By default, all the flags are off unless specified otherwise in the \fIapps.py\fR -configuration file. You can specify as many flags as you want. An uppercase -flag negates the effect: \*(L"ddcccDs\*(R" is equivalent to \*(L"cs\*(R". -.PP -The \*(L"t\*(R" flag looks for the environment variable \s-1TERMCMD\s0, and uses it as the -terminal command, if it's not set it'll use xterm. -.PP -Examples: \f(CW\*(C`:open_with p\*(C'\fR will pipe the output of that process into -the pager. \f(CW\*(C`:shell \-w df\*(C'\fR will run \*(L"df\*(R" and wait for you to press Enter before -switching back to ranger. -.SS "\s-1MODES\s0" -.IX Subsection "MODES" -By specifying a mode (a positive integer), you can tell ranger what to do with -a file when running it. You can specify which mode to use by typing <mode>l or -<mode><Enter> or :open_with <mode>. The default mode is 0. -.PP -Examples: \f(CW\*(C`l\*(C'\fR (mode zero) to list the contents of an archive, \f(CW\*(C`1l\*(C'\fR (mode one) -to extract an archive. See the \fIapps.py\fR configuration file for all programs -and modes. +There are some additional flags that can currently be used only in the \f(CW\*(C`shell\*(C'\fR +command: (for example \f(CW\*(C`:shell \-w df\*(C'\fR) +.PP +.Vb 3 +\& p Redirect output to the pager +\& s Silent mode. Output will be discarded. +\& w Wait for an Enter\-press when the process is done +.Ve +.PP +By default, all the flags are off unless specified otherwise in the +\&\fIrifle.conf\fR configuration file. You can specify as many flags as you want. +An uppercase flag negates the effect: \*(L"ffcccFsf\*(R" is equivalent to \*(L"cs\*(R". +.PP +The terminal program name for the \*(L"t\*(R" flag is taken from the environment +variable \f(CW$TERMCMD\fR. If it doesn't exist, it tries to extract it from \f(CW$TERM\fR and +uses \*(L"xterm\*(R" as a fallback if that fails. +.PP +Examples: \f(CW\*(C`:open_with c\*(C'\fR will open the file that you currently point at, even +if you have selected other files. \f(CW\*(C`:shell \-w df\*(C'\fR will run \*(L"df\*(R" and wait for +you to press Enter before switching back to ranger. +.SS "\s-1PLUGINS\s0" +.IX Subsection "PLUGINS" +ranger's plugin system consists of python files which are located in +\&\fI~/.config/ranger/plugins/\fR and are imported in alphabetical order when +starting ranger. A plugin changes rangers behavior by overwriting or extending +a function that ranger uses. This allows you to change pretty much every part +of ranger, but there is no guarantee that things will continue to work in +future versions as the source code evolves. +.PP +There are some hooks that are specifically made for the use in plugins. They +are functions that start with hook_ and can be found throughout the code. +.PP +.Vb 1 +\& grep \*(Aqdef hook_\*(Aq \-r /path/to/rangers/source +.Ve +.PP +Also try: +.PP +.Vb 1 +\& pydoc ranger.api +.Ve +.PP +Note that you should \s-1NOT\s0 simply overwrite a function unless you know what +you're doing. Instead, save the existing function and call it from your new +one. This way, multiple plugins can use the same hook. There are several +sample plugins in the \fIexamples/\fR directory, including a hello-world plugin +that describes this procedure. .SH "KEY BINDINGS" .IX Header "KEY BINDINGS" Key bindings are defined in the file \fIranger/config/rc.conf\fR. Check this @@ -472,40 +515,60 @@ directory, by clicking on the preview. Enter a directory or run a file. .IP "Scroll Wheel" 4 .IX Item "Scroll Wheel" -Scrolls up or down. You can point at the column of the parent directory to -switch directories. +Scrolls up or down. You can point at the column of the parent directory while +scrolling to switch directories. .SH "SETTINGS" .IX Header "SETTINGS" This section lists all built-in settings of ranger. The valid types for the value are in [brackets]. The hotkey to toggle the setting is in <brokets>, if a hotkey exists. .PP -Settings can be changed in the file \fI~/.config/ranger/options.py\fR or on the +Settings can be changed in the file \fI~/.config/ranger/rc.conf\fR or on the fly with the command \fB:set option value\fR. Examples: - :set column_ratios (1,2,3) - :set show_hidden=True +.PP +.Vb 2 +\& set column_ratios 1,2,3 +\& set show_hidden true +.Ve +.PP +The different types of settings and an example for each type: +.PP +.Vb 7 +\& setting type | example values +\& \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- +\& bool | true, false +\& integer | 1, 23, 1337 +\& string | foo, hello world +\& list | 1,2,3,4 +\& none | none +.Ve +.PP +You can view a list of all settings and their current values by pressing \*(L"3?\*(R" +in ranger. .IP "autosave_bookmarks [bool]" 4 .IX Item "autosave_bookmarks [bool]" Save bookmarks (used with mX and `X) instantly? This helps to synchronize bookmarks between multiple ranger instances but leads to *slight* performance loss. When false, bookmarks are saved when ranger is exited. +.IP "autoupdate_cumulative_size [bool]" 4 +.IX Item "autoupdate_cumulative_size [bool]" +You can display the \*(L"real\*(R" cumulative size of directories by using the command +:get_cumulative_size or typing \*(L"dc\*(R". The size is expensive to calculate and +will not be updated automatically. You can choose to update it automatically +though by turning on this option. .IP "collapse_preview [bool] <zc>" 4 .IX Item "collapse_preview [bool] <zc>" When no preview is visible, should the last column be squeezed to make use of the whitespace? -.IP "colorscheme_overlay [function, None]" 4 -.IX Item "colorscheme_overlay [function, None]" -An overlay function for colorschemes. See the default options.py for an -explanation and an example. .IP "colorscheme [string]" 4 .IX Item "colorscheme [string]" Which colorscheme to use? These colorschemes are available by default: -\&\fBdefault\fR, \fBdefault88\fR, \fBtexas\fR, \fBjungle\fR, \fBsnow\fR. Snow is monochrome, -texas and default88 use 88 colors. -.IP "column_ratios [tuple, list]" 4 -.IX Item "column_ratios [tuple, list]" +\&\fBdefault\fR, \fBjungle\fR, \fBsnow\fR. Snow is a monochrome scheme, jungle replaces +blue directories with green ones for better visibility on certain terminals. +.IP "column_ratios [list]" 4 +.IX Item "column_ratios [list]" How many columns are there, and what are their relative widths? For example, a -value of (1, 1, 1) would mean 3 even sized columns. (1, 1, 1, 1, 4) means 5 columns +value of 1,1,1 would mean 3 evenly sized columns. 1,1,1,1,4 means 5 columns with the preview column being as large as the other columns combined. .IP "dirname_in_tabs [bool]" 4 .IX Item "dirname_in_tabs [bool]" @@ -519,25 +582,32 @@ Display the file size in the status bar? .IP "display_tags_in_all_columns [bool]" 4 .IX Item "display_tags_in_all_columns [bool]" Display tags in all columns? -.IP "draw_bookmark_borders [bool]" 4 -.IX Item "draw_bookmark_borders [bool]" -Draw borders around the bookmark window? .IP "draw_borders [bool]" 4 .IX Item "draw_borders [bool]" Draw borders around columns? +.IP "draw_progress_bar_in_statusbar [bool]" 4 +.IX Item "draw_progress_bar_in_statusbar [bool]" +Draw a progress bar in the status bar which displays the average state of all +currently running tasks which support progress bars? .IP "flushinput [bool] <zi>" 4 .IX Item "flushinput [bool] <zi>" Flush the input after each key hit? One advantage is that when scrolling down with \*(L"j\*(R", ranger stops scrolling instantly when you release the key. One disadvantage is that when you type commands blindly, some keys might get lost. -.IP "hidden_filter [regexp]" 4 -.IX Item "hidden_filter [regexp]" -A regular expression pattern for files which should be hidden. -.IP "max_console_history_size [integer, None]" 4 -.IX Item "max_console_history_size [integer, None]" -How many console commands should be kept in history? -.IP "max_history_size [integer, None]" 4 -.IX Item "max_history_size [integer, None]" +.IP "hidden_filter [string]" 4 +.IX Item "hidden_filter [string]" +A regular expression pattern for files which should be hidden. For example, +this pattern will hide all files that start with a dot or end with a tilde. +.Sp +.Vb 1 +\& set hidden_filter ^\e.|~$ +.Ve +.IP "max_console_history_size [integer, none]" 4 +.IX Item "max_console_history_size [integer, none]" +How many console commands should be kept in history? \*(L"none\*(R" will disable the +limit. +.IP "max_history_size [integer, none]" 4 +.IX Item "max_history_size [integer, none]" How many directory changes should be kept in history? .IP "mouse_enabled [bool] <zm>" 4 .IX Item "mouse_enabled [bool] <zm>" @@ -553,8 +623,8 @@ Preview directories in the preview column? .IP "preview_files [bool] <zp>" 4 .IX Item "preview_files [bool] <zp>" Preview files in the preview column? -.IP "preview_script [string, None]" 4 -.IX Item "preview_script [string, None]" +.IP "preview_script [string, none]" 4 +.IX Item "preview_script [string, none]" Which script should handle generating previews? If the file doesn't exist, or use_preview_script is off, ranger will handle previews itself by just printing the content. @@ -587,7 +657,7 @@ its \s-1ASCII\s0 value is higher. Sort directories first? .IP "sort_reverse [bool] <or>" 4 .IX Item "sort_reverse [bool] <or>" -Sort reversed? +Reverse the order of files? .IP "sort [string] <oa>, <ob>, <oc>, <om>, <on>, <ot>, <os>" 4 .IX Item "sort [string] <oa>, <ob>, <oc>, <om>, <on>, <ot>, <os>" Which sorting mechanism should be used? Choose one of \fBatime\fR, \fBbasename\fR, @@ -614,10 +684,61 @@ Enable this if key combinations with the Alt Key don't work for you. .IX Header "COMMANDS" You can enter the commands in the console which is opened by pressing \*(L":\*(R". .PP +You can always get a list of the currently existing commands by typing \*(L"2?\*(R" in +ranger. For your convenience, this is a list of the \*(L"public\*(R" commands including their parameters, excluding descriptions: +.PP +.Vb 10 +\& alias [newcommand] [oldcommand] +\& bulkrename +\& cd [directory] +\& chain command1[; command2[; command3...]] +\& chmod octal_number +\& cmap key command +\& console [\-pSTARTPOSITION] command +\& copycmap key newkey [newkey2...] +\& copymap key newkey [newkey2...] +\& copypmap key newkey [newkey2...] +\& copytmap key newkey [newkey2...] +\& cunmap keys... +\& delete [confirmation] +\& edit [filename] +\& eval [\-q] python_code +\& filter [string] +\& find pattern +\& grep pattern +\& load_copy_buffer +\& map key command +\& mark pattern +\& mkdir dirname +\& open_with [application] [flags] [mode] +\& pmap key command +\& punmap keys... +\& quit +\& quit! +\& relink newpath +\& rename newname +\& save_copy_buffer +\& search pattern +\& search_inc pattern +\& set option value +\& shell [\-FLAGS] command +\& terminal +\& tmap key command +\& touch filename +\& tunmap keys... +\& unmap keys... +\& unmark pattern +.Ve +.PP There are additional commands which are directly translated to python functions, one for every method in the ranger.core.actions.Actions class. They are not documented here, since they are mostly for key bindings, not to be typed in by a user. Read the source if you are interested in them. +.PP +These are the public commands including their descriptions: +.IP "alias [\fInewcommand\fR] [\fIoldcommand\fR]" 2 +.IX Item "alias [newcommand] [oldcommand]" +Copies the oldcommand as newcommand. .IP "bulkrename" 2 .IX Item "bulkrename" This command opens a list of selected files in an external editor. After you @@ -632,7 +753,7 @@ The cd command changes the directory. The command \f(CW\*(C`:cd \-\*(C'\fR is e typing ``. .IP "chain \fIcommand1\fR[; \fIcommand2\fR[; \fIcommand3\fR...]]" 2 .IX Item "chain command1[; command2[; command3...]]" -Combines multiple commands into one, separated by columns. +Combines multiple commands into one, separated by semicolons. .IP "chmod \fIoctal_number\fR" 2 .IX Item "chmod octal_number" Sets the permissions of the selection to the octal number. @@ -671,8 +792,8 @@ See \f(CW\*(C`copymap\*(C'\fR .IP "copytmap \fIkey\fR \fInewkey\fR [\fInewkey2\fR ...]" 2 .IX Item "copytmap key newkey [newkey2 ...]" See \f(CW\*(C`copymap\*(C'\fR -.IP "cunmap \fIkey\fR \fIcommand\fR" 2 -.IX Item "cunmap key command" +.IP "cunmap [\fIkeys...\fR]" 2 +.IX Item "cunmap [keys...]" Removes key mappings of the console. Works like the \f(CW\*(C`unmap\*(C'\fR command. .IP "delete [\fIconfirmation\fR]" 2 .IX Item "delete [confirmation]" @@ -697,7 +818,8 @@ Examples: :eval p(\*(L"Hello World!\*(R") .IP "filter [\fIstring\fR]" 2 .IX Item "filter [string]" -Displays only the files which contain the \fIstring\fR in their basename. +Displays only the files which contain the \fIstring\fR in their basename. Running +this command without any parameter will reset the fitler. .IP "find \fIpattern\fR" 2 .IX Item "find pattern" Search files in the current directory that match the given (case-insensitive) @@ -735,8 +857,8 @@ in their own sections. .IP "pmap \fIkey\fR \fIcommand\fR" 2 .IX Item "pmap key command" Binds keys for the pager. Works like the \f(CW\*(C`map\*(C'\fR command. -.IP "punmap \fIkey\fR \fIcommand\fR" 2 -.IX Item "punmap key command" +.IP "punmap [\fIkeys ...\fR]" 2 +.IX Item "punmap [keys ...]" Removes key mappings of the pager. Works like the \f(CW\*(C`unmap\*(C'\fR command. .IP "quit" 2 .IX Item "quit" @@ -745,13 +867,14 @@ Like quit!, but closes only this tab if multiple tabs are open. .IX Item "quit!" Quit ranger. The current directory will be bookmarked as ' so you can re-enter it by typing `` or '' the next time you start ranger. +.IP "relink \fInewpath\fR" 2 +.IX Item "relink newpath" +Change the link destination of the current symlink file to <newpath>. First +<tab> will load the original link. .IP "rename \fInewname\fR" 2 .IX Item "rename newname" Rename the current file. If a file with that name already exists, the renaming will fail. Also try the key binding A for appending something to a file name. -.IP "relink \fInewpath\fR" 2 -.IX Item "relink newpath" -Change the link destination of the current symlink file to <newpath>. First <tab> will load the original link. .IP "save_copy_buffer" 2 .IX Item "save_copy_buffer" Save the copy buffer from \fI~/.config/ranger/copy_buffer\fR. This can be used to @@ -765,21 +888,20 @@ regular expression pattern. Search files in the current directory that match the given (case insensitive) regular expression pattern. This command gets you to matching files as you type. -.IP "set \fIoption\fR=\fIvalue\fR" 2 -.IX Item "set option=value" +.IP "set \fIoption\fR \fIvalue\fR" 2 +.IX Item "set option value" Assigns a new value to an option. Valid options are listed in the settings section. Use tab completion to get the current value of an option, though this doesn't work for functions and regular expressions. Valid values are: .Sp -.Vb 8 -\& None None -\& bool True or False -\& integer 0 or 1 or \-1 or 2 etc. -\& list [1, 2, 3] -\& tuple 1, 2, 3 or (1, 2, 3) -\& function lambda <arguments>: <expression> -\& regexp regexp(\*(Aq<pattern>\*(Aq) -\& string Anything +.Vb 7 +\& setting type | example values +\& \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- +\& bool | true, false +\& integer | 1, 23, 1337 +\& string | foo, hello world +\& list | 1,2,3,4 +\& none | none .Ve .IP "shell [\-\fIflags\fR] \fIcommand\fR" 2 .IX Item "shell [-flags] command" @@ -787,14 +909,14 @@ Run a shell command. \fIflags\fR are discussed in their own section. .IP "terminal" 2 .IX Item "terminal" Spawns the \fIx\-terminal-emulator\fR starting in the current directory. -.IP "touch \fIfilename\fR" 2 -.IX Item "touch filename" -Creates an empty file with the name \fIfilename\fR, unless it already exists. .IP "tmap \fIkey\fR \fIcommand\fR" 2 .IX Item "tmap key command" Binds keys for the taskview. Works like the \f(CW\*(C`map\*(C'\fR command. -.IP "tunmap \fIkey\fR \fIcommand\fR" 2 -.IX Item "tunmap key command" +.IP "touch \fIfilename\fR" 2 +.IX Item "touch filename" +Creates an empty file with the name \fIfilename\fR, unless it already exists. +.IP "tunmap [\fIkeys ...\fR]" 2 +.IX Item "tunmap [keys ...]" Removes key mappings of the taskview. Works like the \f(CW\*(C`unmap\*(C'\fR command. .IP "unmap [\fIkeys\fR ...]" 2 .IX Item "unmap [keys ...]" @@ -807,45 +929,40 @@ Unmark all files matching a regular expression pattern. .IX Header "FILES" ranger reads several configuration files which are located in \&\fI\f(CI$HOME\fI/.config/ranger\fR or \fI\f(CI$XDG_CONFIG_HOME\fI/ranger\fR if \f(CW$XDG_CONFIG_HOME\fR is -defined. The configuration is done mostly in python. When removing a -configuration file, remove its compiled version too. (Python automatically -compiles modules. Since python3 they are saved in the _\|_pycache_\|_ directory, -earlier versions store them with the .pyc extension in the same directory.) -.PP -Use the \-\-copy\-config option to obtain the default configuration files. They -include further documentation and it's too much to put here. +defined. You can use the \-\-copy\-config option to obtain the default +configuration files. Each of the files contains further documentation. .PP You don't need to copy the whole file though, most configuration files are -overlaid on top of the defaults (\fIoptions.py\fR, \fIcommand.py\fR, \fIrc.conf\fR) or -can be sub-classed (\fIapps.py\fR, \fIcolorschemes\fR). +overlaid on top of the defaults (\fIcommands.py\fR, \fIrc.conf\fR) or can be +sub-classed (\fIcolorschemes\fR). .PP When starting ranger with the \fB\-\-clean\fR option, it will not access or create any of these files. .SS "\s-1CONFIGURATION\s0" .IX Subsection "CONFIGURATION" -.IP "apps.py" 10 -.IX Item "apps.py" -Controls which applications are used to open files. -.IP "commands.py" 10 -.IX Item "commands.py" -Defines commands which can be used by typing \*(L":\*(R". .IP "rc.conf" 10 .IX Item "rc.conf" Contains a list of commands which are executed on startup. Mostly key bindings -are defined here. -.IP "options.py" 10 -.IX Item "options.py" -Sets a handful of basic options. +and settings are defined here. +.IP "commands.py" 10 +.IX Item "commands.py" +A python module that defines commands which can be used in ranger's console by +typing \*(L":\*(R" or in the rc.conf file. +.IP "rifle.conf" 10 +.IX Item "rifle.conf" +This is the configuration file for the built-in file launcher called \*(L"rifle\*(R". .IP "scope.sh" 10 .IX Item "scope.sh" This is a script that handles file previews. When the options -\&\fIuse_preview_script\fR and \fIpreview_files\fR or, respectively, -\&\fIpreview_directories\fR are set, the program specified in the option -\&\fIpreview_script\fR is run and its output and/or exit code determines rangers -reaction. +\&\fIuse_preview_script\fR and \fIpreview_files\fR are set, the program specified in +the option \fIpreview_script\fR is run and its output and/or exit code determines +rangers reaction. .IP "colorschemes/" 10 .IX Item "colorschemes/" Colorschemes can be placed here. +.IP "plugins/" 10 +.IX Item "plugins/" +Plugins can be placed here. .SS "\s-1STORAGE\s0" .IX Subsection "STORAGE" .IP "bookmarks" 10 @@ -874,7 +991,7 @@ with T. To assign a named tag, type "<tagname>. These environment variables have an effect on ranger: .IP "\s-1RANGER_LEVEL\s0" 8 .IX Item "RANGER_LEVEL" -Ranger sets this environment variable to \*(L"1\*(R" or increments it if it already +ranger sets this environment variable to \*(L"1\*(R" or increments it if it already exists. External programs can determine whether they were spawned from ranger by checking for this variable. .IP "\s-1EDITOR\s0" 8 @@ -904,50 +1021,9 @@ Using PYTHONOPTIMIZE=2 (like python \-OO) will additionally discard any docstrings. Using this will disable the <F1> key on commands. .SH "EXAMPLES" .IX Header "EXAMPLES" -.SS "\s-1BASH:\s0 Display that the shell spawned from ranger:" -.IX Subsection "BASH: Display that the shell spawned from ranger:" -By putting this in ~/.bashrc, \*(L"(in ranger) \*(R" will be displayed next to your -prompt to notify you that the shell spawned from ranger. -.PP -.Vb 1 -\& [ \-n "$RANGER_LEVEL" ] && PS1="$PS1"\*(Aq(in ranger) \*(Aq -.Ve -.SS "\s-1VIM:\s0 File Chooser" -.IX Subsection "VIM: File Chooser" -This is a vim function which allows you to use ranger to select a file for -opening in your current vim session. -.PP -.Vb 9 -\& fun! RangerChooser() -\& exec "silent !ranger \-\-choosefile=/tmp/chosenfile " . expand("%:p:h") -\& if filereadable(\*(Aq/tmp/chosenfile\*(Aq) -\& exec \*(Aqedit \*(Aq . system(\*(Aqcat /tmp/chosenfile\*(Aq) -\& call system(\*(Aqrm /tmp/chosenfile\*(Aq) -\& endif -\& redraw! -\& endfun -\& map ,r :call RangerChooser()<CR> -.Ve -.SS "Bash: cd to last path after exit" -.IX Subsection "Bash: cd to last path after exit" -This is a bash function (for \fI~/.bashrc\fR) to change the directory to the last -visited one after ranger quits. You can always type \f(CW\*(C`cd \-\*(C'\fR to go back to the -original one. -.PP -.Vb 9 -\& function ranger\-cd { -\& tempfile=\*(Aq/tmp/chosendir\*(Aq -\& /usr/bin/ranger \-\-choosedir="$tempfile" "${@:\-$(pwd)}" -\& test \-f "$tempfile" && -\& if [ "$(cat \-\- "$tempfile")" != "$(echo \-n \`pwd\`)" ]; then -\& cd \-\- "$(cat "$tempfile")" -\& fi -\& rm \-f \-\- "$tempfile" -\& } -\& -\& # This binds Ctrl\-O to ranger\-cd: -\& bind \*(Aq"\eC\-o":"ranger\-cd\eC\-m"\*(Aq -.Ve +There are various examples on how to extend ranger with plugins or combine +ranger with other programs. These can be found in the \fIexamples/\fR directory +that is provided along with the source code. .SH "LICENSE" .IX Header "LICENSE" \&\s-1GNU\s0 General Public License 3 or (at your option) any later version. diff --git a/doc/ranger.pod b/doc/ranger.pod index 2a3a345b..f8ba66b1 100644 --- a/doc/ranger.pod +++ b/doc/ranger.pod @@ -75,7 +75,7 @@ Open ranger with I<targetfile> selected. Create copies of the default configuration files in your local configuration directory. Existing ones will not be overwritten. Possible values: I<all>, -I<rc>, I<apps>, I<commands>, I<options>, I<scope>. +I<rc>, I<commands>, I<scope>. =item B<--list-unused-keys> @@ -124,6 +124,9 @@ Print a list of options and exit. =head1 CONCEPTS +This part explains how certain parts of ranger work and how they can be used +efficiently. + =head2 TAGS Tags are single characters which are displayed left of a filename. You can use @@ -175,7 +178,7 @@ are in different directories: @diff %c %f Macros for file paths are generally shell-escaped so they can be used in the -:shell command. +C<shell> command. =head2 BOOKMARKS @@ -190,39 +193,75 @@ Bookmarks are selectable when tabbing in the :cd command. Note: The bookmarks ' (Apostrophe) and ` (Backtick) are the same. +=head2 RIFLE + +Rifle is the file opener of ranger. It can be used as a standalone program or +a python module. It is located at F<ranger/ext/rifle.py>. In contrast to +other, more simple file openers, rifle can automatically find installed +programs so it can be used effectively out of the box on a variety of systems. + +It's configured in F<rifle.conf> through a list of conditions and commands. +For each line the conditions are checked and if they are met, the respective +command is taken into consideration. By default, simply the first matching +rule is used. In ranger, you can list and choose rules by typing "r" or simply +by typing "<rulenumber><enter>". If you use rifle standalone, you can list all +rules with the "-l" option and pick a rule with "-p <number>". + +The rules, along with further documentation, are contained in +F<ranger/config/rifle.conf>. + =head2 FLAGS Flags give you a way to modify the behavior of the spawned process. They are -used in the commands :open_with (key "r") and :shell (key "!"). +used in the commands C<:open_with> (key "r") and C<:shell> (key "!"). - s Silent mode. Output will be discarded. - d Detach the process. (Run in background) - p Redirect output to the pager - w Wait for an Enter-press when the process is done + f Fork the process. (Run in background) c Run the current file only, instead of the selection r Run application with root privilege (requires sudo) t Run application in a new terminal window -By default, all the flags are off unless specified otherwise in the F<apps.py> -configuration file. You can specify as many flags as you want. An uppercase -flag negates the effect: "ddcccDs" is equivalent to "cs". +There are some additional flags that can currently be used only in the C<shell> +command: (for example C<:shell -w df>) + + p Redirect output to the pager + s Silent mode. Output will be discarded. + w Wait for an Enter-press when the process is done + +By default, all the flags are off unless specified otherwise in the +F<rifle.conf> configuration file. You can specify as many flags as you want. +An uppercase flag negates the effect: "ffcccFsf" is equivalent to "cs". + +The terminal program name for the "t" flag is taken from the environment +variable $TERMCMD. If it doesn't exist, it tries to extract it from $TERM and +uses "xterm" as a fallback if that fails. + +Examples: C<:open_with c> will open the file that you currently point at, even +if you have selected other files. C<:shell -w df> will run "df" and wait for +you to press Enter before switching back to ranger. + +=head2 PLUGINS + +ranger's plugin system consists of python files which are located in +F<~/.config/ranger/plugins/> and are imported in alphabetical order when +starting ranger. A plugin changes rangers behavior by overwriting or extending +a function that ranger uses. This allows you to change pretty much every part +of ranger, but there is no guarantee that things will continue to work in +future versions as the source code evolves. -The "t" flag looks for the environment variable TERMCMD, and uses it as the -terminal command, if it's not set it'll use xterm. +There are some hooks that are specifically made for the use in plugins. They +are functions that start with hook_ and can be found throughout the code. -Examples: C<:open_with p> will pipe the output of that process into -the pager. C<:shell -w df> will run "df" and wait for you to press Enter before -switching back to ranger. + grep 'def hook_' -r /path/to/rangers/source -=head2 MODES +Also try: -By specifying a mode (a positive integer), you can tell ranger what to do with -a file when running it. You can specify which mode to use by typing <mode>l or -<mode><Enter> or :open_with <mode>. The default mode is 0. + pydoc ranger.api -Examples: C<l> (mode zero) to list the contents of an archive, C<1l> (mode one) -to extract an archive. See the F<apps.py> configuration file for all programs -and modes. +Note that you should NOT simply overwrite a function unless you know what +you're doing. Instead, save the existing function and call it from your new +one. This way, multiple plugins can use the same hook. There are several +sample plugins in the F<examples/> directory, including a hello-world plugin +that describes this procedure. @@ -443,8 +482,8 @@ Enter a directory or run a file. =item Scroll Wheel -Scrolls up or down. You can point at the column of the parent directory to -switch directories. +Scrolls up or down. You can point at the column of the parent directory while +scrolling to switch directories. =back @@ -457,10 +496,24 @@ This section lists all built-in settings of ranger. The valid types for the value are in [brackets]. The hotkey to toggle the setting is in <brokets>, if a hotkey exists. -Settings can be changed in the file F<~/.config/ranger/options.py> or on the +Settings can be changed in the file F<~/.config/ranger/rc.conf> or on the fly with the command B<:set option value>. Examples: - :set column_ratios (1,2,3) - :set show_hidden=True + + set column_ratios 1,2,3 + set show_hidden true + +The different types of settings and an example for each type: + + setting type | example values + ---------------+---------------------------- + bool | true, false + integer | 1, 23, 1337 + string | foo, hello world + list | 1,2,3,4 + none | none + +You can view a list of all settings and their current values by pressing "3?" +in ranger. =over @@ -470,26 +523,28 @@ Save bookmarks (used with mX and `X) instantly? This helps to synchronize bookmarks between multiple ranger instances but leads to *slight* performance loss. When false, bookmarks are saved when ranger is exited. +=item autoupdate_cumulative_size [bool] + +You can display the "real" cumulative size of directories by using the command +:get_cumulative_size or typing "dc". The size is expensive to calculate and +will not be updated automatically. You can choose to update it automatically +though by turning on this option. + =item collapse_preview [bool] <zc> When no preview is visible, should the last column be squeezed to make use of the whitespace? -=item colorscheme_overlay [function, None] - -An overlay function for colorschemes. See the default options.py for an -explanation and an example. - =item colorscheme [string] Which colorscheme to use? These colorschemes are available by default: -B<default>, B<default88>, B<texas>, B<jungle>, B<snow>. Snow is monochrome, -texas and default88 use 88 colors. +B<default>, B<jungle>, B<snow>. Snow is a monochrome scheme, jungle replaces +blue directories with green ones for better visibility on certain terminals. -=item column_ratios [tuple, list] +=item column_ratios [list] How many columns are there, and what are their relative widths? For example, a -value of (1, 1, 1) would mean 3 even sized columns. (1, 1, 1, 1, 4) means 5 columns +value of 1,1,1 would mean 3 evenly sized columns. 1,1,1,1,4 means 5 columns with the preview column being as large as the other columns combined. =item dirname_in_tabs [bool] @@ -508,29 +563,34 @@ Display the file size in the status bar? Display tags in all columns? -=item draw_bookmark_borders [bool] - -Draw borders around the bookmark window? - =item draw_borders [bool] Draw borders around columns? +=item draw_progress_bar_in_statusbar [bool] + +Draw a progress bar in the status bar which displays the average state of all +currently running tasks which support progress bars? + =item flushinput [bool] <zi> Flush the input after each key hit? One advantage is that when scrolling down with "j", ranger stops scrolling instantly when you release the key. One disadvantage is that when you type commands blindly, some keys might get lost. -=item hidden_filter [regexp] +=item hidden_filter [string] -A regular expression pattern for files which should be hidden. +A regular expression pattern for files which should be hidden. For example, +this pattern will hide all files that start with a dot or end with a tilde. -=item max_console_history_size [integer, None] + set hidden_filter ^\.|~$ -How many console commands should be kept in history? +=item max_console_history_size [integer, none] -=item max_history_size [integer, None] +How many console commands should be kept in history? "none" will disable the +limit. + +=item max_history_size [integer, none] How many directory changes should be kept in history? @@ -552,7 +612,7 @@ Preview directories in the preview column? Preview files in the preview column? -=item preview_script [string, None] +=item preview_script [string, none] Which script should handle generating previews? If the file doesn't exist, or use_preview_script is off, ranger will handle previews itself by just printing @@ -595,7 +655,7 @@ Sort directories first? =item sort_reverse [bool] <or> -Sort reversed? +Reverse the order of files? =item sort [string] <oa>, <ob>, <oc>, <om>, <on>, <ot>, <os> @@ -632,13 +692,63 @@ Enable this if key combinations with the Alt Key don't work for you. You can enter the commands in the console which is opened by pressing ":". +You can always get a list of the currently existing commands by typing "2?" in +ranger. For your convenience, this is a list of the "public" commands including their parameters, excluding descriptions: + + alias [newcommand] [oldcommand] + bulkrename + cd [directory] + chain command1[; command2[; command3...]] + chmod octal_number + cmap key command + console [-pSTARTPOSITION] command + copycmap key newkey [newkey2...] + copymap key newkey [newkey2...] + copypmap key newkey [newkey2...] + copytmap key newkey [newkey2...] + cunmap keys... + delete [confirmation] + edit [filename] + eval [-q] python_code + filter [string] + find pattern + grep pattern + load_copy_buffer + map key command + mark pattern + mkdir dirname + open_with [application] [flags] [mode] + pmap key command + punmap keys... + quit + quit! + relink newpath + rename newname + save_copy_buffer + search pattern + search_inc pattern + set option value + shell [-FLAGS] command + terminal + tmap key command + touch filename + tunmap keys... + unmap keys... + unmark pattern + There are additional commands which are directly translated to python functions, one for every method in the ranger.core.actions.Actions class. They are not documented here, since they are mostly for key bindings, not to be typed in by a user. Read the source if you are interested in them. +These are the public commands including their descriptions: + =over 2 +=item alias [I<newcommand>] [I<oldcommand>] + +Copies the oldcommand as newcommand. + =item bulkrename This command opens a list of selected files in an external editor. After you @@ -655,7 +765,7 @@ typing ``. =item chain I<command1>[; I<command2>[; I<command3>...]] -Combines multiple commands into one, separated by columns. +Combines multiple commands into one, separated by semicolons. =item chmod I<octal_number> @@ -702,7 +812,7 @@ See C<copymap> See C<copymap> -=item cunmap I<key> I<command> +=item cunmap [I<keys...>] Removes key mappings of the console. Works like the C<unmap> command. @@ -732,7 +842,8 @@ Examples: =item filter [I<string>] -Displays only the files which contain the I<string> in their basename. +Displays only the files which contain the I<string> in their basename. Running +this command without any parameter will reset the fitler. =item find I<pattern> @@ -779,7 +890,7 @@ in their own sections. Binds keys for the pager. Works like the C<map> command. -=item punmap I<key> I<command> +=item punmap [I<keys ...>] Removes key mappings of the pager. Works like the C<unmap> command. @@ -792,15 +903,16 @@ Like quit!, but closes only this tab if multiple tabs are open. Quit ranger. The current directory will be bookmarked as ' so you can re-enter it by typing `` or '' the next time you start ranger. +=item relink I<newpath> + +Change the link destination of the current symlink file to <newpath>. First +<tab> will load the original link. + =item rename I<newname> Rename the current file. If a file with that name already exists, the renaming will fail. Also try the key binding A for appending something to a file name. -=item relink I<newpath> - -Change the link destination of the current symlink file to <newpath>. First <tab> will load the original link. - =item save_copy_buffer Save the copy buffer from I<~/.config/ranger/copy_buffer>. This can be used to @@ -817,20 +929,19 @@ Search files in the current directory that match the given (case insensitive) regular expression pattern. This command gets you to matching files as you type. -=item set I<option>=I<value> +=item set I<option> I<value> Assigns a new value to an option. Valid options are listed in the settings section. Use tab completion to get the current value of an option, though this doesn't work for functions and regular expressions. Valid values are: - None None - bool True or False - integer 0 or 1 or -1 or 2 etc. - list [1, 2, 3] - tuple 1, 2, 3 or (1, 2, 3) - function lambda <arguments>: <expression> - regexp regexp('<pattern>') - string Anything + setting type | example values + ---------------+---------------------------- + bool | true, false + integer | 1, 23, 1337 + string | foo, hello world + list | 1,2,3,4 + none | none =item shell [-I<flags>] I<command> @@ -840,15 +951,15 @@ Run a shell command. I<flags> are discussed in their own section. Spawns the I<x-terminal-emulator> starting in the current directory. -=item touch I<filename> - -Creates an empty file with the name I<filename>, unless it already exists. - =item tmap I<key> I<command> Binds keys for the taskview. Works like the C<map> command. -=item tunmap I<key> I<command> +=item touch I<filename> + +Creates an empty file with the name I<filename>, unless it already exists. + +=item tunmap [I<keys ...>] Removes key mappings of the taskview. Works like the C<unmap> command. @@ -870,17 +981,12 @@ Unmark all files matching a regular expression pattern. ranger reads several configuration files which are located in F<$HOME/.config/ranger> or F<$XDG_CONFIG_HOME/ranger> if $XDG_CONFIG_HOME is -defined. The configuration is done mostly in python. When removing a -configuration file, remove its compiled version too. (Python automatically -compiles modules. Since python3 they are saved in the __pycache__ directory, -earlier versions store them with the .pyc extension in the same directory.) - -Use the --copy-config option to obtain the default configuration files. They -include further documentation and it's too much to put here. +defined. You can use the --copy-config option to obtain the default +configuration files. Each of the files contains further documentation. You don't need to copy the whole file though, most configuration files are -overlaid on top of the defaults (F<options.py>, F<command.py>, F<rc.conf>) or -can be sub-classed (F<apps.py>, F<colorschemes>). +overlaid on top of the defaults (F<commands.py>, F<rc.conf>) or can be +sub-classed (F<colorschemes>). When starting ranger with the B<--clean> option, it will not access or create any of these files. @@ -889,35 +995,35 @@ any of these files. =over 10 -=item apps.py +=item rc.conf -Controls which applications are used to open files. +Contains a list of commands which are executed on startup. Mostly key bindings +and settings are defined here. =item commands.py -Defines commands which can be used by typing ":". - -=item rc.conf - -Contains a list of commands which are executed on startup. Mostly key bindings -are defined here. +A python module that defines commands which can be used in ranger's console by +typing ":" or in the rc.conf file. -=item options.py +=item rifle.conf -Sets a handful of basic options. +This is the configuration file for the built-in file launcher called "rifle". =item scope.sh This is a script that handles file previews. When the options -I<use_preview_script> and I<preview_files> or, respectively, -I<preview_directories> are set, the program specified in the option -I<preview_script> is run and its output and/or exit code determines rangers -reaction. +I<use_preview_script> and I<preview_files> are set, the program specified in +the option I<preview_script> is run and its output and/or exit code determines +rangers reaction. =item colorschemes/ Colorschemes can be placed here. +=item plugins/ + +Plugins can be placed here. + =back =head2 STORAGE @@ -962,7 +1068,7 @@ These environment variables have an effect on ranger: =item RANGER_LEVEL -Ranger sets this environment variable to "1" or increments it if it already +ranger sets this environment variable to "1" or increments it if it already exists. External programs can determine whether they were spawned from ranger by checking for this variable. @@ -1004,46 +1110,9 @@ docstrings. Using this will disable the <F1> key on commands. =head1 EXAMPLES -=head2 BASH: Display that the shell spawned from ranger: - -By putting this in ~/.bashrc, "(in ranger) " will be displayed next to your -prompt to notify you that the shell spawned from ranger. - - [ -n "$RANGER_LEVEL" ] && PS1="$PS1"'(in ranger) ' - -=head2 VIM: File Chooser - -This is a vim function which allows you to use ranger to select a file for -opening in your current vim session. - - fun! RangerChooser() - exec "silent !ranger --choosefile=/tmp/chosenfile " . expand("%:p:h") - if filereadable('/tmp/chosenfile') - exec 'edit ' . system('cat /tmp/chosenfile') - call system('rm /tmp/chosenfile') - endif - redraw! - endfun - map ,r :call RangerChooser()<CR> - -=head2 Bash: cd to last path after exit - -This is a bash function (for F<~/.bashrc>) to change the directory to the last -visited one after ranger quits. You can always type C<cd -> to go back to the -original one. - - function ranger-cd { - tempfile='/tmp/chosendir' - /usr/bin/ranger --choosedir="$tempfile" "${@:-$(pwd)}" - test -f "$tempfile" && - if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then - cd -- "$(cat "$tempfile")" - fi - rm -f -- "$tempfile" - } - - # This binds Ctrl-O to ranger-cd: - bind '"\C-o":"ranger-cd\C-m"' +There are various examples on how to extend ranger with plugins or combine +ranger with other programs. These can be found in the F<examples/> directory +that is provided along with the source code. diff --git a/examples/README b/examples/README index 60f29ac6..8606a89d 100644 --- a/examples/README +++ b/examples/README @@ -1,2 +1,2 @@ -Thes files in this directory contain applications or extensions of ranger which +The files in this directory contain applications or extensions of ranger which are put here for your inspiration and as references. diff --git a/examples/plugin_chmod_keybindings.py b/examples/plugin_chmod_keybindings.py new file mode 100644 index 00000000..62ca6c58 --- /dev/null +++ b/examples/plugin_chmod_keybindings.py @@ -0,0 +1,18 @@ +# This plugin serves as an example for adding key bindings through a plugin. +# It could replace the ten lines in the rc.conf that create the key bindings +# for the "chmod" command. + +import ranger.api +old_hook_init = ranger.api.hook_init + +def hook_init(fm): + old_hook_init(fm) + + # Generate key bindings for the chmod command + command = "map {0}{1}{2} shell -d chmod {1}{0}{2} %s" + for mode in list('ugoa') + '': + for perm in "rwxXst": + fm.execute_console(command.format('-', mode, perm)) + fm.execute_console(command.format('+', mode, perm)) + +ranger.api.hook_init = hook_init diff --git a/examples/plugin_file_filter.py b/examples/plugin_file_filter.py new file mode 100644 index 00000000..99d026bb --- /dev/null +++ b/examples/plugin_file_filter.py @@ -0,0 +1,17 @@ +# This plugin hides the directories "boot", "sbin", "proc" and "sys" in the +# root directory. + +# Save the original filter function +import ranger.fsobject.directory +old_accept_file = ranger.fsobject.directory.accept_file + +# Define a new one +def custom_accept_file(fname, mypath, hidden_filter, name_filter): + if hidden_filter and mypath == '/' and fname in ('boot', 'sbin', 'proc', 'sys'): + return False + else: + return old_accept_file(fname, mypath, hidden_filter, name_filter) + +# Overwrite the old function +import ranger.fsobject.directory +ranger.fsobject.directory.accept_file = custom_accept_file diff --git a/examples/plugin_hello_world.py b/examples/plugin_hello_world.py new file mode 100644 index 00000000..187f428e --- /dev/null +++ b/examples/plugin_hello_world.py @@ -0,0 +1,21 @@ +# This is a sample plugin that displays "Hello World" in ranger's console after +# it started. + +# We are going to extend the hook "ranger.api.hook_ready", so first we need +# to import ranger.api: +import ranger.api + +# Save the previously existing hook, because maybe another module already +# extended that hook and we don't want to lose it: +old_hook_ready = ranger.api.hook_ready + +# Create a replacement for the hook that... +def hook_ready(fm): + # ...does the desired action... + fm.notify("Hello World") + # ...and calls the saved hook. If you don't care about the return value, simply + # return the return value of the previous hook to be on the safe side. + return old_hook_ready(fm) + +# Finally, "monkey patch" the existing hook_ready function with our replacement: +ranger.api.hook_ready = hook_ready diff --git a/examples/plugin_new_macro.py b/examples/plugin_new_macro.py new file mode 100644 index 00000000..ec0c487c --- /dev/null +++ b/examples/plugin_new_macro.py @@ -0,0 +1,17 @@ +# This plugin adds the new macro %date which is substituted with the current +# date in commands that allow macros. You can test it with the command +# ":shell echo %date; read" + +# Save the original macro function +import ranger.core.actions +old_get_macros = ranger.core.actions.Actions._get_macros + +# Define a new macro function +import time +def get_macros_with_date(self): + macros = old_get_macros(self) + macros['date'] = time.strftime('%m/%d/%Y') + return macros + +# Overwrite the old one +ranger.core.actions.Actions._get_macros = get_macros_with_date diff --git a/examples/plugin_new_sorting_method.py b/examples/plugin_new_sorting_method.py new file mode 100644 index 00000000..2500c1c1 --- /dev/null +++ b/examples/plugin_new_sorting_method.py @@ -0,0 +1,7 @@ +# This plugin adds the sorting algorithm called 'random'. To enable it, type +# ":set sort=random" or create a key binding with ":map oz set sort=random" + +from ranger.fsobject.directory import Directory +from random import random +Directory.sort_dict['random'] = lambda path: random() + diff --git a/examples/plugin_skip_default_rc.py b/examples/plugin_skip_default_rc.py new file mode 100644 index 00000000..6a657a99 --- /dev/null +++ b/examples/plugin_skip_default_rc.py @@ -0,0 +1,9 @@ +# This plugin inhibits the loading of the default rc.conf. This serves to +# speed up starting time by avoiding to load rc.conf twice if you have a full +# copy of it in ~/.config/ranger. +# +# Don't use this if you have a supplementary rc.conf or no rc.conf at all, or +# you will end up without key bindings and options. + +import ranger.core.main +ranger.core.main.load_default_config = False diff --git a/examples/rifle_different_file_opener.conf b/examples/rifle_different_file_opener.conf new file mode 100644 index 00000000..1362a1eb --- /dev/null +++ b/examples/rifle_different_file_opener.conf @@ -0,0 +1,7 @@ +# Replace your rifle.conf with this file to use xdg-open as your file opener. +# This is, of course, adaptable for use with any other file opener. +else = xdg-open "$1" + +# You need an "editor" and "pager" in order to use certain functions in ranger: +label editor = "$EDITOR" -- "$@" +label pager = "$PAGER" -- "$@" diff --git a/ranger/api/__init__.py b/ranger/api/__init__.py index cc64a7c0..1121197a 100644 --- a/ranger/api/__init__.py +++ b/ranger/api/__init__.py @@ -1,4 +1,28 @@ """ -Files in this module contain helper functions used in -configuration files. +Files in this module contain helper functions used in configuration files. """ + +# Hooks for use in plugins: + +def hook_init(fm): + """ + Parameters: + fm = the file manager instance + Return Value: + ignored + + This hook is executed after fm is initialized but before fm.ui is + initialized. You can safely print to stdout and have access to fm to add + keybindings and such. + """ + +def hook_ready(fm): + """ + Parameters: + fm = the file manager instance + Return Value: + ignored + + This hook is executed after the user interface is initialized. You should + NOT print anything to stdout anymore from here on. Use fm.notify instead. + """ diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 962b9fd1..4a2bb912 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -387,13 +387,7 @@ class set_(Command): def execute(self): name = self.arg(1) name, value, _ = self.parse_setting_line() - if name and value: - from re import compile as regexp - try: - value = eval(value) - except: - pass - self.fm.settings[name] = value + self.fm.set_option_from_string(name, value) def tab(self): name, value, name_done = self.parse_setting_line() diff --git a/ranger/config/options.py b/ranger/config/options.py deleted file mode 100644 index a401abc5..00000000 --- a/ranger/config/options.py +++ /dev/null @@ -1,216 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 2009, 2010, 2011 Roman Zimbelmann <romanz@lavabit.com> -# This configuration file is licensed under the same terms as ranger. -# =================================================================== -# This is the main configuration file of ranger. It consists of python -# code, but fear not, you don't need any python knowledge for changing -# the settings. -# -# Lines beginning with # are comments. To enable a line, remove the #. -# -# You can customize ranger in the file ~/.config/ranger/options.py. -# It has the same syntax as this file. In fact, you can just copy this -# file there with `ranger --copy-config=options' and make your modifications. -# But make sure you update your configs when you update ranger. -# =================================================================== - -# Load the deault rc.conf file? If you've copied it to your configuration -# direcory, then you should deactivate this option. -load_default_rc = True - -# How many columns are there, and what are their relative widths? -column_ratios = (1, 3, 4) - -# Which files should be hidden? Toggle this by typing `zh' or -# changing the setting `show_hidden' -hidden_filter = r'^\.|\.(?:pyc|pyo|bak|swp)$|^lost\+found$|^__(py)?cache__$' -show_hidden = False - -# Which script is used to generate file previews? -# ranger ships with scope.sh, a script that calls external programs (see -# README for dependencies) to preview images, archives, etc. -preview_script = '~/.config/ranger/scope.sh' - -# Use that external preview script or display internal plain text previews? -use_preview_script = True - -# Use a unicode "..." character to mark cut-off filenames? -unicode_ellipsis = False - -# Show dotfiles in the bookmark preview box? -show_hidden_bookmarks = True - -# Which colorscheme to use? These colorschemes are available by default: -# default, default88, jungle, snow -# Snow is monochrome and default88 uses 88 colors. -colorscheme = 'default' - -# Preview files on the rightmost column? -# And collapse (shrink) the last column if there is nothing to preview? -preview_files = True -preview_directories = True -collapse_preview = True - -# Save the console history on exit? -save_console_history = True - -# Draw a progress bar in the status bar which displays the average state of all -# currently running tasks which support progress bars? -draw_progress_bar_in_status_bar = True - -# Draw borders around columns? -draw_borders = False -draw_bookmark_borders = True - -# Display the directory name in tabs? -dirname_in_tabs = False - -# Enable the mouse support? -mouse_enabled = True - -# Display the file size in the main column or status bar? -display_size_in_main_column = True -display_size_in_status_bar = False - -# Display files tags in all columns or only in main column? -display_tags_in_all_columns = True - -# Set a title for the window? -update_title = True - -# Shorten the title if it gets long? The number defines how many -# directories are displayed at once, False turns off this feature. -shorten_title = 3 - -# Abbreviate $HOME with ~ in the titlebar (first line) of ranger? -tilde_in_titlebar = True - -# How many directory-changes or console-commands should be kept in history? -max_history_size = 20 -max_console_history_size = 50 - -# Try to keep so much space between the top/bottom border when scrolling: -scroll_offset = 8 - -# Flush the input after each key hit? (Noticable when ranger lags) -flushinput = True - -# Padding on the right when there's no preview? -# This allows you to click into the space to run the file. -padding_right = True - -# Save bookmarks (used with mX and `X) instantly? -# This helps to synchronize bookmarks between multiple ranger -# instances but leads to *slight* performance loss. -# When false, bookmarks are saved when ranger is exited. -autosave_bookmarks = True - -# You can display the "real" cumulative size of directories by using the -# command :get_cumulative_size or typing "dc". The size is expensive to -# calculate and will not be updated automatically. You can choose -# to update it automatically though by turning on this option: -autoupdate_cumulative_size = False - -# Makes sense for screen readers: -show_cursor = False - -# One of: size, basename, mtime, type -sort = 'natural' -sort_reverse = False -sort_case_insensitive = True -sort_directories_first = True - -# Enable this if key combinations with the Alt Key don't work for you. -# (Especially on xterm) -xterm_alt_key = False - -# A function that is called when the user interface is being set up. -init_function = None - -# You can use it to initialize some custom functionality or bind singals -#def init_function(fm): -# fm.notify("Hello :)") -# def on_tab_change(signal): -# signal.origin.notify("Changing tab! Yay!") -# fm.signal_bind("tab.change", on_tab_change) - -# The color scheme overlay. Explained below. -colorscheme_overlay = None - -## Apply an overlay function to the colorscheme. It will be called with -## 4 arguments: the context and the 3 values (fg, bg, attr) returned by -## the original use() function of your colorscheme. The return value -## must be a 3-tuple of (fg, bg, attr). -## Note: Here, the colors/attributes aren't directly imported into -## the namespace but have to be accessed with color.xyz. - -#from ranger.gui import color -#def colorscheme_overlay(context, fg, bg, attr): -# if context.directory and attr & color.bold and \ -# not any((context.marked, context.selected)): -# attr ^= color.bold # I don't like bold directories! -# -# if context.main_column and context.selected: -# fg, bg = color.red, color.default # To highlight the main column! -# -# return fg, bg, attr - - -# =================================================================== -# Beware: from here on, you are on your own. This part requires python -# knowledge. -# -# Since python is a dynamic language, it gives you the power to replace any -# part of ranger without touching the code. This is commonly referred to as -# Monkey Patching and can be helpful if you, for some reason, don't want to -# modify rangers code directly. Just remember: the more you mess around, the -# more likely it is to break when you switch to another version. -# -# Here are some practical examples of monkey patching. -# -# Technical information: This file is imported as a python module. If a -# variable has the name of a setting, ranger will attempt to use it to change -# that setting. You can write "del <variable-name>" to avoid that. -# =================================================================== -# Add a new sorting algorithm: Random sort. -# Enable this with :set sort=random - -#from ranger.fsobject.directory import Directory -#from random import random -#Directory.sort_dict['random'] = lambda path: random() - -# =================================================================== -# A function that changes which files are displayed. This is more powerful -# than the hidden_filter setting since this function has more information. - -## Save the original filter function -#import ranger.fsobject.directory -#old_accept_file = ranger.fsobject.directory.accept_file -# -## Define a new one -#def accept_file_MOD(fname, mypath, hidden_filter, name_filter): -# if hidden_filter and mypath == '/' and fname in ('boot', 'sbin', 'proc', 'sys'): -# return False -# else: -# return old_accept_file(fname, mypath, hidden_filter, name_filter) -# -## Overwrite the old function -#import ranger.fsobject.directory -#ranger.fsobject.directory.accept_file = accept_file_MOD - -# =================================================================== -# A function that adds an additional macro. Test this with :shell -p echo %date - -## Save the original macro function -#import ranger.core.actions -#old_get_macros = ranger.core.actions.Actions._get_macros -# -## Define a new macro function -#import time -#def get_macros_MOD(self): -# macros = old_get_macros(self) -# macros['date'] = time.strftime('%m/%d/%Y') -# return macros -# -## Overwrite the old one -#ranger.core.actions.Actions._get_macros = get_macros_MOD diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf index 1b344465..2a6be5d8 100644 --- a/ranger/config/rc.conf +++ b/ranger/config/rc.conf @@ -8,9 +8,9 @@ # # load_default_rc = False # -# The purpose of this file is mainly to define keybindings. For -# changing settings or running more complex python code, use the -# configuation file "options.py" or define commands in "commands.py". +# The purpose of this file is mainly to define keybindings and settings. +# For running more complex python code, please create a plugin in "plugins/" or +# a command in "commands.py". # # Each line is a command that will be run before the user interface # is initialized. As a result, you can not use commands which rely @@ -18,6 +18,119 @@ # =================================================================== # =================================================================== +# == Options +# =================================================================== + +# How many columns are there, and what are their relative widths? +set column_ratios 1,3,4 + +# Which files should be hidden? (regular expression) +set hidden_filter ^\.|\.(?:pyc|pyo|bak|swp)$|^lost\+found$|^__(py)?cache__$ + +# Show hidden files? You can toggle this by typing 'zh' +set show_hidden false + +# Which script is used to generate file previews? +# ranger ships with scope.sh, a script that calls external programs (see +# README for dependencies) to preview images, archives, etc. +set preview_script ~/.config/ranger/scope.sh + +# Use the external preview script or display simple plain text previews? +set use_preview_script true + +# Use a unicode "..." character to mark cut-off filenames? +set unicode_ellipsis false + +# Show dotfiles in the bookmark preview box? +set show_hidden_bookmarks true + +# Which colorscheme to use? These colorschemes are available by default: +# default, default88, jungle, snow +# Snow is monochrome and default88 uses 88 colors. +set colorscheme default + +# Preview files on the rightmost column? +# And collapse (shrink) the last column if there is nothing to preview? +set preview_files true +set preview_directories true +set collapse_preview true + +# Save the console history on exit? +set save_console_history true + +# Draw a progress bar in the status bar which displays the average state of all +# currently running tasks which support progress bars? +set draw_progress_bar_in_status_bar True + +# Draw borders around columns? +set draw_borders false + +# Display the directory name in tabs? +set dirname_in_tabs false + +# Enable the mouse support? +set mouse_enabled true + +# Display the file size in the main column or status bar? +set display_size_in_main_column true +set display_size_in_status_bar true + +# Display files tags in all columns or only in main column? +set display_tags_in_all_columns true + +# Set a title for the window? +set update_title false + +# Shorten the title if it gets long? The number defines how many +# directories are displayed at once, False turns off this feature. +set shorten_title 3 + +# Abbreviate $HOME with ~ in the titlebar (first line) of ranger? +set tilde_in_titlebar false + +# How many directory-changes or console-commands should be kept in history? +set max_history_size 20 +set max_console_history_size 50 + +# Try to keep so much space between the top/bottom border when scrolling: +set scroll_offset 8 + +# Flush the input after each key hit? (Noticable when ranger lags) +set flushinput true + +# Padding on the right when there's no preview? +# This allows you to click into the space to run the file. +set padding_right true + +# Save bookmarks (used with mX and `X) instantly? +# This helps to synchronize bookmarks between multiple ranger +# instances but leads to *slight* performance loss. +# When false, bookmarks are saved when ranger is exited. +set autosave_bookmarks true + +# You can display the "real" cumulative size of directories by using the +# command :get_cumulative_size or typing "dc". The size is expensive to +# calculate and will not be updated automatically. You can choose +# to update it automatically though by turning on this option: +set autoupdate_cumulative_size false + +# Turning this on makes sense for screen readers: +set show_cursor false + +# One of: size, basename, mtime, type +set sort natural + +# Additional sorting options +set sort_reverse false +set sort_case_insensitive true +set sort_directories_first true + +# Enable this if key combinations with the Alt Key don't work for you. +# (Especially on xterm) +set xterm_alt_key true + + +# =================================================================== # == Command Aliases in the Console # =================================================================== diff --git a/ranger/container/history.py b/ranger/container/history.py index 8ba092bc..d0e077aa 100644 --- a/ranger/container/history.py +++ b/ranger/container/history.py @@ -33,7 +33,7 @@ class History(object): if self._history and self._history[-1] == item: del self._history[-1] # Remove first if list is too long - if len(self._history) > self.maxlen - 1: + if len(self._history) > max(self.maxlen - 1, 0): del self._history[0] # Append the item and fast forward self._history.append(item) diff --git a/ranger/container/settingobject.py b/ranger/container/settingobject.py index f70361b5..70eac7b5 100644 --- a/ranger/container/settingobject.py +++ b/ranger/container/settingobject.py @@ -4,35 +4,32 @@ from inspect import isfunction from ranger.ext.signals import SignalDispatcher from ranger.core.shared import FileManagerAware +import re ALLOWED_SETTINGS = { 'autosave_bookmarks': bool, 'autoupdate_cumulative_size': bool, 'collapse_preview': bool, - 'colorscheme_overlay': (type(None), type(lambda:0)), 'colorscheme': str, 'column_ratios': (tuple, list), 'dirname_in_tabs': bool, 'display_size_in_main_column': bool, 'display_size_in_status_bar': bool, 'display_tags_in_all_columns': bool, - 'draw_bookmark_borders': bool, 'draw_borders': bool, 'draw_progress_bar_in_status_bar': bool, 'flushinput': bool, - 'hidden_filter': lambda x: isinstance(x, str) or hasattr(x, 'match'), - 'init_function': (type(None), type(lambda:0)), - 'load_default_rc': (bool, type(None)), + 'hidden_filter': (str, type(re.compile(""))), #COMPAT change to str-only 'max_console_history_size': (int, type(None)), 'max_history_size': (int, type(None)), 'mouse_enabled': bool, + 'padding_right': bool, 'preview_directories': bool, 'preview_files': bool, 'preview_script': (str, type(None)), - 'padding_right': bool, 'save_console_history': bool, 'scroll_offset': int, - 'shorten_title': int, # Note: False is an instance of int + 'shorten_title': int, # XXX Note: False is an instance of int 'show_cursor': bool, 'show_hidden_bookmarks': bool, 'show_hidden': bool, @@ -41,18 +38,24 @@ ALLOWED_SETTINGS = { 'sort_reverse': bool, 'sort': str, 'tilde_in_titlebar': bool, + 'unicode_ellipsis': bool, 'update_title': bool, 'use_preview_script': bool, - 'unicode_ellipsis': bool, 'xterm_alt_key': bool, } +DEFAULT_VALUES = { + bool: False, + type(None): None, + str: "", + int: 0, + list: [], +} class SettingObject(SignalDispatcher, FileManagerAware): def __init__(self): SignalDispatcher.__init__(self) self.__dict__['_settings'] = dict() - self.__dict__['_setting_sources'] = list() for name in ALLOWED_SETTINGS: self.signal_bind('setopt.'+name, self._raw_set_with_signal, priority=0.2) @@ -63,10 +66,11 @@ class SettingObject(SignalDispatcher, FileManagerAware): else: assert name in ALLOWED_SETTINGS, "No such setting: {0}!".format(name) if name not in self._settings: - getattr(self, name) + previous = None + else: + previous=self._settings[name] assert self._check_type(name, value) - kws = dict(setting=name, value=value, - previous=self._settings[name], fm=self.fm) + kws = dict(setting=name, value=value, previous=previous, fm=self.fm) self.signal_emit('setopt', **kws) self.signal_emit('setopt.'+name, **kws) @@ -78,14 +82,8 @@ class SettingObject(SignalDispatcher, FileManagerAware): try: return self._settings[name] except: - for struct in self._setting_sources: - try: value = getattr(struct, name) - except: pass - else: break - else: - raise Exception("The option `{0}' was not defined" \ - " in the defaults!".format(name)) - assert self._check_type(name, value) + type_ = self.types_of(name)[0] + value = DEFAULT_VALUES[type_] self._raw_set(name, value) self.__setattr__(name, value) return self._settings[name] @@ -110,11 +108,13 @@ class SettingObject(SignalDispatcher, FileManagerAware): typ = ALLOWED_SETTINGS[name] if isfunction(typ): assert typ(value), \ - "The option `" + name + "' has an incorrect type!" + "Warning: The option `" + name + "' has an incorrect type!" else: assert isinstance(value, typ), \ - "The option `" + name + "' has an incorrect type!"\ - " Got " + str(type(value)) + ", expected " + str(typ) + "!" + "Warning: The option `" + name + "' has an incorrect type!"\ + " Got " + str(type(value)) + ", expected " + str(typ) + "!" +\ + " Please check if your commands.py is up to date." if not \ + self.fm.ui.is_set_up else "" return True __getitem__ = __getattr__ diff --git a/ranger/core/actions.py b/ranger/core/actions.py index cbe74132..6df73cdf 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -23,6 +23,7 @@ from ranger.core.shared import FileManagerAware, EnvironmentAware, \ from ranger.core.tab import Tab from ranger.fsobject import File from ranger.core.loader import CommandLoader, CopyLoader +from ranger.container.settingobject import ALLOWED_SETTINGS MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>" @@ -66,6 +67,34 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): self.mode = mode self.ui.status.request_redraw() + def set_option_from_string(self, option_name, value): + if option_name not in ALLOWED_SETTINGS: + raise ValueError("The option named `%s' does not exist" % + option_name) + if not isinstance(value, str): + raise ValueError("The value for an option needs to be a string.") + self.settings[option_name] = self._parse_option_value(option_name, value) + + def _parse_option_value(self, name, value): + types = self.fm.settings.types_of(name) + if bool in types: + if value.lower() in ('false', 'off', '0'): + return False + elif value.lower() in ('true', 'on', '1'): + return True + if type(None) in types and value.lower() == 'none': + return None + if int in types: + try: + return int(value) + except ValueError: + pass + if str in types: + return value + if list in types: + return value.split(',') + raise ValueError("Invalid value `%s' for option `%s'!" % (name, value)) + def toggle_visual_mode(self, reverse=False): if self.mode == 'normal': self._visual_reverse = reverse diff --git a/ranger/core/fm.py b/ranger/core/fm.py index f554ab1b..3c100532 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -14,7 +14,7 @@ import socket import stat import sys -import ranger +import ranger.api from ranger.core.actions import Actions from ranger.core.tab import Tab from ranger.container.tags import Tags @@ -123,9 +123,6 @@ class FM(Actions, SignalDispatcher): self.notify(text, bad=True) self.run = Runner(ui=self.ui, logfunc=mylogfunc, fm=self) - if self.settings.init_function: - self.settings.init_function(self) - def destroy(self): debug = ranger.arg.debug if self.ui: @@ -185,14 +182,11 @@ class FM(Actions, SignalDispatcher): copy('config/commands.py', 'commands.py') if which == 'rc' or which == 'all': copy('config/rc.conf', 'rc.conf') - if which == 'options' or which == 'all': - copy('config/options.py', 'options.py') if which == 'scope' or which == 'all': copy('data/scope.sh', 'scope.sh') os.chmod(self.confpath('scope.sh'), os.stat(self.confpath('scope.sh')).st_mode | stat.S_IXUSR) - if which not in \ - ('all', 'rifle', 'scope', 'commands', 'rc', 'options'): + if which not in ('all', 'rifle', 'scope', 'commands', 'rc'): sys.stderr.write("Unknown config file `%s'\n" % which) def confpath(self, *paths): @@ -251,6 +245,8 @@ class FM(Actions, SignalDispatcher): has_throbber = hasattr(ui, 'throbber') zombies = self.run.zombies + ranger.api.hook_ready(self) + try: while True: loader.work() diff --git a/ranger/core/main.py b/ranger/core/main.py index eda11b5b..80b2e9a7 100644 --- a/ranger/core/main.py +++ b/ranger/core/main.py @@ -6,12 +6,14 @@ The main function responsible to initialize the FM object and stuff. """ import os.path +import sys + +load_default_config = True def main(): """initialize objects and run the filemanager""" import locale - import ranger - import sys + import ranger.api from ranger.core.shared import FileManagerAware, SettingsAware from ranger.core.fm import FM @@ -110,6 +112,7 @@ def main(): # Run the file manager fm.initialize() + ranger.api.hook_init(fm) fm.ui.initialize() if arg.selectfile: @@ -181,7 +184,7 @@ def parse_arguments(): help="don't touch/require any config files. ") parser.add_option('--copy-config', type='string', metavar='which', help="copy the default configs to the local config directory. " - "Possible values: all, rc, rifle, commands, options, scope") + "Possible values: all, rc, rifle, commands, scope") parser.add_option('--fail-unless-cd', action='store_true', help="experimental: return the exit code 1 if ranger is" \ "used to run a file (with `ranger filename`)") @@ -225,6 +228,7 @@ def parse_arguments(): def load_settings(fm, clean): + global load_default_config from ranger.core.actions import Actions import ranger.core.shared import ranger.api.commands @@ -241,18 +245,18 @@ def load_settings(fm, clean): allow_access_to_confdir(ranger.arg.confdir, True) # Load custom commands - try: - import commands - fm.commands.load_commands_from_module(commands) - except ImportError: - pass + if os.path.exists(fm.confpath('commands.py')): + try: + import commands + fm.commands.load_commands_from_module(commands) + except ImportError: + pass # Load rc.conf custom_conf = fm.confpath('rc.conf') default_conf = fm.relpath('config', 'rc.conf') - load_default_rc = fm.settings.load_default_rc - if load_default_rc: + if load_default_config: fm.source(default_conf) if os.access(custom_conf, os.R_OK): fm.source(custom_conf) @@ -281,6 +285,27 @@ def load_settings(fm, clean): fm.log.append(line) ranger.fm = None + # COMPAT: Load the outdated options.py + # options.py[oc] are deliberately ignored + if os.path.exists(fm.confpath("options.py")): + module = __import__('options') + from ranger.container.settingobject import ALLOWED_SETTINGS + for setting in ALLOWED_SETTINGS: + if hasattr(module, setting): + fm.settings[setting] = getattr(module, setting) + + sys.stderr.write( +"""****************************** +Warning: The configuration file 'options.py' is deprecated. +Please move all settings to the file 'rc.conf', converting lines like + "preview_files = False" +to + "set preview_files false" +If you had python code in the options.py that you'd like to keep, simply +copy & paste it to a .py file in ~/.config/ranger/plugins/. +Remove the options.py or discard stderr to get rid of this warning. +******************************\n""") + allow_access_to_confdir(ranger.arg.confdir, False) else: fm.source(fm.relpath('config', 'rc.conf')) diff --git a/ranger/core/shared.py b/ranger/core/shared.py index 26023e43..d7bf90b6 100644 --- a/ranger/core/shared.py +++ b/ranger/core/shared.py @@ -33,8 +33,7 @@ class SettingsAware(Awareness): @staticmethod def _setup(clean=True): - from ranger.container.settingobject import SettingObject, \ - ALLOWED_SETTINGS + from ranger.container.settingobject import SettingObject import ranger import sys settings = SettingObject() @@ -43,6 +42,9 @@ class SettingsAware(Awareness): settings.signal_bind('setopt.colorscheme', _colorscheme_name_to_class, priority=1) + settings.signal_bind('setopt.column_ratios', + _sanitize_setting_column_ratios, priority=1) + def after_setting_preview_script(signal): if isinstance(signal.value, str): signal.value = os.path.expanduser(signal.value) @@ -58,22 +60,12 @@ class SettingsAware(Awareness): settings.signal_bind('setopt.use_preview_script', after_setting_use_preview_script, priority=1) - if not clean: - # add the custom options to the list of setting sources - sys.path[0:0] = [ranger.arg.confdir] - try: - import options as my_options - except ImportError: - # XXX: This mistakenly ignores ImportErrors inside options.py - # It should only ignore missing options.py instead. - pass - else: - settings._setting_sources.append(my_options) - del sys.path[0] - - from ranger.config import options as default_options - settings._setting_sources.append(default_options) - assert all(hasattr(default_options, setting) \ - for setting in ALLOWED_SETTINGS), \ - "Ensure that all options are defined in the defaults!" SettingsAware.settings = settings + +def _sanitize_setting_column_ratios(signal): + if isinstance(signal.value, tuple): + signal.value = list(signal.value) + if not isinstance(signal.value, list) or len(signal.value) < 2: + signal.value = [1,1] + else: + signal.value = [int(i) if str(i).isdigit() else 1 for i in signal.value] diff --git a/ranger/ext/rifle.py b/ranger/ext/rifle.py index 157b1efb..4f551765 100755 --- a/ranger/ext/rifle.py +++ b/ranger/ext/rifle.py @@ -351,6 +351,8 @@ class Rifle(object): if term not in get_executables(): self.hook_logger("Can not determine terminal command. " "Please set $TERMCMD manually.") + # A fallback terminal that is likely installed: + term = 'xterm' os.environ['TERMCMD'] = term cmd = [os.environ['TERMCMD'], '-e'] + cmd if 'f' in flags or 't' in flags: diff --git a/ranger/gui/ansi.py b/ranger/gui/ansi.py index f328d9df..1b693c7c 100644 --- a/ranger/gui/ansi.py +++ b/ranger/gui/ansi.py @@ -10,12 +10,16 @@ from ranger.gui import color import re ansi_re = re.compile('(\x1b' + r'\[\d*(?:;\d+)*?[a-zA-Z])') +codesplit_re = re.compile('38;5;(\d+);|48;5;(\d+);|(\d*);') reset = '\x1b[0m' def split_ansi_from_text(ansi_text): return ansi_re.split(ansi_text) +# For information on the ANSI codes see +# githttp://en.wikipedia.org/wiki/ANSI_escape_code def text_with_fg_bg_attr(ansi_text): + fg, bg, attr = -1, -1, 0 for chunk in split_ansi_from_text(ansi_text): if chunk and chunk[0] == '\x1b': if chunk[-1] != 'm': @@ -25,20 +29,28 @@ def text_with_fg_bg_attr(ansi_text): # XXX I have no test case to determine what should happen here continue attr_args = match.group(1) - fg, bg, attr = -1, -1, 0 # Convert arguments to attributes/colors - for arg in attr_args.split(';'): + for x256fg, x256bg, arg in codesplit_re.findall(attr_args + ';'): + # first handle xterm256 codes try: - n = int(arg) - except: - if arg == '': - n = 0 - else: + if len(x256fg) > 0: # xterm256 foreground + fg = int(x256fg) continue - if n == 0: + elif len(x256bg) > 0: # xterm256 background + bg = int(x256bg) + continue + elif len(arg) > 0: # usual ansi code + n = int(arg) + else: # empty code means reset + n = 0 + except: + continue + + if n == 0: # reset colors and attributes fg, bg, attr = -1, -1, 0 - elif n == 1: + + elif n == 1: # enable attribute attr |= color.bold elif n == 4: attr |= color.underline @@ -48,7 +60,19 @@ def text_with_fg_bg_attr(ansi_text): attr |= color.reverse elif n == 8: attr |= color.invisible - elif n >= 30 and n <= 37: + + elif n == 22: # disable attribute + attr &= not color.bold + elif n == 24: + attr &= not color.underline + elif n == 25: + attr &= not color.blink + elif n == 27: + attr &= not color.reverse + elif n == 28: + attr &= not color.invisible + + elif n >= 30 and n <= 37: # 8 ansi foreground and background colors fg = n - 30 elif n == 39: fg = -1 @@ -56,7 +80,18 @@ def text_with_fg_bg_attr(ansi_text): bg = n - 40 elif n == 49: bg = -1 + + elif n >= 90 and n <= 97: # 8 aixterm high intensity colors (light but not bold) + fg = n - 90 + 8 + elif n == 99: + fg = -1 + elif n >= 100 and n <= 107: + bg = n - 100 + 8 + elif n == 109: + bg = -1 + yield (fg, bg, attr) + else: yield chunk diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py index b36048e2..34e59f55 100644 --- a/ranger/gui/colorscheme.py +++ b/ranger/gui/colorscheme.py @@ -33,23 +33,18 @@ import ranger from ranger.gui.color import get_color from ranger.gui.context import Context from ranger.core.main import allow_access_to_confdir -from ranger.core.shared import SettingsAware from ranger.ext.cached_function import cached_function from ranger.ext.iter_tools import flatten -# ColorScheme is not SettingsAware but it will gain access -# to the settings during the initialization. We can't import -# SettingsAware here because of circular imports. - -class ColorScheme(SettingsAware): +class ColorScheme(object): """ This is the class that colorschemes must inherit from. - it defines get() it defines the get() method, which returns the color tuple which fits to the given keys. """ + @cached_function def get(self, *keys): """ Returns the (fg, bg, attr) for the given keys. @@ -58,17 +53,11 @@ class ColorScheme(SettingsAware): colors for faster access. """ context = Context(keys) - - # add custom error messages for broken colorschemes color = self.use(context) - if self.settings.colorscheme_overlay: - result = self.settings.colorscheme_overlay(context, *color) - assert isinstance(result, (tuple, list)), \ - "Your colorscheme overlay doesn't return a tuple!" - assert all(isinstance(val, int) for val in result), \ - "Your colorscheme overlay doesn't return a tuple"\ - " containing 3 integers!" - color = result + if len(color) != 3 or not all(isinstance(value, int) \ + for value in color): + raise ValueError("Bad Value from colorscheme. Need " + "a tuple of (foreground_color, background_color, attribute).") return color @cached_function @@ -82,7 +71,8 @@ class ColorScheme(SettingsAware): return attr | color_pair(get_color(fg, bg)) def use(self, context): - """Use the colorscheme to determine the (fg, bg, attr) tuple. + """ + Use the colorscheme to determine the (fg, bg, attr) tuple. Override this method in your own colorscheme. """ @@ -95,6 +85,9 @@ def _colorscheme_name_to_class(signal): # is picked. if isinstance(signal.value, ColorScheme): return + if not signal.value: + signal.value = 'default' + scheme_name = signal.value usecustom = not ranger.arg.clean |