1 # Copyright (C) 2009, 2010, 2011 Roman Zimbelmann <romanz@lavabit.com>
2 # This software is distributed under the terms of the GNU GPL version 3.
5 The main function responsible to initialize the FM object and stuff.
11 load_default_config
= True
14 """initialize objects and run the filemanager"""
17 from ranger
.core
.shared
import FileManagerAware
, SettingsAware
18 from ranger
.core
.fm
import FM
20 if not sys
.stdin
.isatty():
21 sys
.stderr
.write("Error: Must run ranger from terminal\n")
25 locale
.setlocale(locale
.LC_ALL
, '')
27 print("Warning: Unable to set locale. Expect encoding problems.")
29 # so that programs can know that ranger spawned them:
30 level
= 'RANGER_LEVEL'
31 if level
in os
.environ
and os
.environ
[level
].isdigit():
32 os
.environ
[level
] = str(int(os
.environ
[level
]) + 1)
34 os
.environ
[level
] = '1'
36 if not 'SHELL' in os
.environ
:
37 os
.environ
['SHELL'] = 'bash'
39 ranger
.arg
= arg
= parse_arguments()
40 if arg
.copy_config
is not None:
42 fm
.copy_config_files(arg
.copy_config
)
43 return 1 if arg
.fail_unless_cd
else 0 # COMPAT
44 if arg
.list_tagged_files
:
47 f
= open(fm
.confpath('tagged'), 'r')
51 for line
in f
.readlines():
52 if len(line
) > 2 and line
[1] == ':':
53 if line
[0] in arg
.list_tagged_files
:
54 sys
.stdout
.write(line
[2:])
55 elif len(line
) > 0 and '*' in arg
.list_tagged_files
:
56 sys
.stdout
.write(line
)
57 return 1 if arg
.fail_unless_cd
else 0 # COMPAT
59 SettingsAware
._setup
(clean
=arg
.clean
)
62 arg
.selectfile
= os
.path
.abspath(arg
.selectfile
)
63 arg
.targets
.insert(0, os
.path
.dirname(arg
.selectfile
))
65 targets
= arg
.targets
or ['.']
68 if target
.startswith('file://'):
70 if not os
.access(target
, os
.F_OK
):
71 print("File or directory doesn't exist: %s" % target
)
73 elif os
.path
.isfile(target
):
74 def print_function(string
):
76 from ranger
.ext
.rifle
import Rifle
78 if not arg
.clean
and os
.path
.isfile(fm
.confpath('rifle.conf')):
79 rifleconf
= fm
.confpath('rifle.conf')
81 rifleconf
= fm
.relpath('config/rifle.conf')
82 rifle
= Rifle(rifleconf
)
84 rifle
.execute(targets
, number
=ranger
.arg
.mode
, flags
=ranger
.arg
.flags
)
85 return 1 if arg
.fail_unless_cd
else 0 # COMPAT
87 crash_traceback
= None
90 fm
= FM(paths
=targets
)
91 FileManagerAware
.fm
= fm
92 load_settings(fm
, arg
.clean
)
94 if arg
.list_unused_keys
:
95 from ranger
.ext
.keybinding_parser
import (special_keys
,
96 reversed_special_keys
)
97 maps
= fm
.ui
.keymaps
['browser']
98 for key
in sorted(special_keys
.values(), key
=lambda x
: str(x
)):
100 print("<%s>" % reversed_special_keys
[key
])
101 for key
in range(33, 127):
104 return 1 if arg
.fail_unless_cd
else 0 # COMPAT
106 if fm
.username
== 'root':
107 fm
.settings
.preview_files
= False
108 fm
.settings
.use_preview_script
= False
110 from ranger
.ext
import curses_interrupt_handler
111 curses_interrupt_handler
.install_interrupt_handler()
113 # Run the file manager
115 ranger
.api
.hook_init(fm
)
119 fm
.select_file(arg
.selectfile
)
122 for command
in arg
.cmd
:
123 fm
.execute_console(command
)
125 if ranger
.arg
.profile
:
130 cProfile
.run('ranger.__fm.loop()', '/tmp/ranger_profile')
131 profile
= pstats
.Stats('/tmp/ranger_profile', stream
=sys
.stderr
)
136 crash_traceback
= traceback
.format_exc()
137 except SystemExit as error
:
142 filepath
= fm
.thisfile
.path
if fm
.thisfile
else "None"
147 except (AttributeError, NameError):
149 if ranger
.arg
.profile
and profile
:
150 profile
.strip_dirs().sort_stats('cumulative').print_callees()
152 print("ranger version: %s, executed with python %s" %
153 (ranger
.__version
__, sys
.version
.split()[0]))
154 print("Locale: %s" % '.'.join(str(s
) for s
in locale
.getlocale()))
156 print("Current file: %s" % filepath
)
159 print(crash_traceback
)
160 print("ranger crashed. " \
161 "Please report this traceback at:")
162 print("http://savannah.nongnu.org/bugs/?group=ranger&func=additem")
167 def parse_arguments():
168 """Parse the program arguments"""
169 from optparse
import OptionParser
, SUPPRESS_HELP
170 from os
.path
import expanduser
171 from ranger
import CONFDIR
, USAGE
, VERSION
172 from ranger
.ext
.openstruct
import OpenStruct
174 if 'XDG_CONFIG_HOME' in os
.environ
and os
.environ
['XDG_CONFIG_HOME']:
175 default_confdir
= os
.environ
['XDG_CONFIG_HOME'] + '/ranger'
177 default_confdir
= CONFDIR
179 parser
= OptionParser(usage
=USAGE
, version
=VERSION
)
181 parser
.add_option('-d', '--debug', action
='store_true',
182 help="activate debug mode")
183 parser
.add_option('-c', '--clean', action
='store_true',
184 help="don't touch/require any config files. ")
185 parser
.add_option('--copy-config', type='string', metavar
='which',
186 help="copy the default configs to the local config directory. "
187 "Possible values: all, rc, rifle, commands, scope")
188 parser
.add_option('--fail-unless-cd', action
='store_true',
189 help=SUPPRESS_HELP
) # COMPAT
190 parser
.add_option('-r', '--confdir', type='string',
191 metavar
='dir', default
=default_confdir
,
192 help="the configuration directory. (%default)")
193 parser
.add_option('-m', '--mode', type='int', default
=0, metavar
='n',
194 help="if a filename is supplied, run it with this mode")
195 parser
.add_option('-f', '--flags', type='string', default
='',
197 help="if a filename is supplied, run it with these flags.")
198 parser
.add_option('--choosefile', type='string', metavar
='TARGET',
199 help="Makes ranger act like a file chooser. When opening "
200 "a file, it will quit and write the name of the selected "
202 parser
.add_option('--choosefiles', type='string', metavar
='TARGET',
203 help="Makes ranger act like a file chooser for multiple files "
204 "at once. When opening a file, it will quit and write the name "
205 "of all selected files to TARGET.")
206 parser
.add_option('--choosedir', type='string', metavar
='TARGET',
207 help="Makes ranger act like a directory chooser. When ranger quits"
208 ", it will write the name of the last visited directory to TARGET")
209 parser
.add_option('--list-unused-keys', action
='store_true',
210 help="List common keys which are not bound to any action.")
211 parser
.add_option('--selectfile', type='string', metavar
='filepath',
212 help="Open ranger with supplied file selected.")
213 parser
.add_option('--list-tagged-files', type='string', default
=None,
215 help="List all files which are tagged with the given tag, default: *")
216 parser
.add_option('--profile', action
='store_true',
217 help="Print statistics of CPU usage on exit.")
218 parser
.add_option('--cmd', action
='append', type='string', metavar
='COMMAND',
219 help="Execute COMMAND after the configuration has been read. "
220 "Use this option multiple times to run multiple commands.")
222 options
, positional
= parser
.parse_args()
223 arg
= OpenStruct(options
.__dict
__, targets
=positional
)
224 arg
.confdir
= expanduser(arg
.confdir
)
226 if arg
.fail_unless_cd
: # COMPAT
227 sys
.stderr
.write("Warning: The option --fail-unless-cd is deprecated.\n"
228 "It was used to faciliate using ranger as a file launcher.\n"
229 "Now, please use the standalone file launcher 'rifle' instead.\n")
234 def load_settings(fm
, clean
):
235 global load_default_config
236 from ranger
.core
.actions
import Actions
237 import ranger
.core
.shared
238 import ranger
.api
.commands
239 from ranger
.config
import commands
241 # Load default commands
242 fm
.commands
= ranger
.api
.commands
.CommandContainer()
243 exclude
= ['settings']
244 include
= [name
for name
in dir(Actions
) if name
not in exclude
]
245 fm
.commands
.load_commands_from_object(fm
, include
)
246 fm
.commands
.load_commands_from_module(commands
)
249 allow_access_to_confdir(ranger
.arg
.confdir
, True)
251 # Load custom commands
252 if os
.path
.exists(fm
.confpath('commands.py')):
255 fm
.commands
.load_commands_from_module(commands
)
259 allow_access_to_confdir(ranger
.arg
.confdir
, False)
262 custom_conf
= fm
.confpath('rc.conf')
263 default_conf
= fm
.relpath('config', 'rc.conf')
265 if load_default_config
:
266 fm
.source(default_conf
)
267 if os
.access(custom_conf
, os
.R_OK
):
268 fm
.source(custom_conf
)
270 allow_access_to_confdir(ranger
.arg
.confdir
, True)
272 # XXX Load plugins (experimental)
274 plugindir
= fm
.confpath('plugins')
275 plugins
= [p
[:-3] for p
in os
.listdir(plugindir
) \
276 if p
.endswith('.py') and not p
.startswith('_')]
280 if not os
.path
.exists(fm
.confpath('plugins', '__init__.py')):
281 f
= open(fm
.confpath('plugins', '__init__.py'), 'w')
285 for plugin
in sorted(plugins
):
287 module
= __import__('plugins', fromlist
=[plugin
])
288 fm
.log
.append("Loaded plugin '%s'." % module
)
289 except Exception as e
:
290 fm
.log
.append("Error in plugin '%s'" % plugin
)
292 for line
in traceback
.format_exception_only(type(e
), e
):
296 # COMPAT: Load the outdated options.py
297 # options.py[oc] are deliberately ignored
298 if os
.path
.exists(fm
.confpath("options.py")):
299 module
= __import__('options')
300 from ranger
.container
.settingobject
import ALLOWED_SETTINGS
301 for setting
in ALLOWED_SETTINGS
:
302 if hasattr(module
, setting
):
303 fm
.settings
[setting
] = getattr(module
, setting
)
306 """******************************
307 Warning: The configuration file 'options.py' is deprecated.
308 Please move all settings to the file 'rc.conf', converting lines like
309 "preview_files = False"
311 "set preview_files false"
312 If you had python code in the options.py that you'd like to keep, simply
313 copy & paste it to a .py file in ~/.config/ranger/plugins/.
314 Remove the options.py or discard stderr to get rid of this warning.
315 ******************************\n""")
317 allow_access_to_confdir(ranger
.arg
.confdir
, False)
319 fm
.source(fm
.relpath('config', 'rc.conf'))
322 def allow_access_to_confdir(confdir
, allow
):
324 from errno
import EEXIST
329 except OSError as err
:
330 if err
.errno
!= EEXIST
: # EEXIST means it already exists
331 print("This configuration directory could not be created:")
333 print("To run ranger without the need for configuration")
334 print("files, use the --clean option.")
336 if not confdir
in sys
.path
:
337 sys
.path
[0:0] = [confdir
]
339 if sys
.path
[0] == confdir
: