summary refs log blame commit diff stats
path: root/test/tc_direction.py
blob: 16c26dab4f05cedd9b05fd86063a126a7e583c8d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                       





                                                          












































                                                                  




                                                         
 




                                                                     
                                                                                


                                                                     
 


                                      
                                                                                                          
                                                 
                                                                                                               
 


                          
# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os.path
import sys
rangerpath = os.path.join(os.path.dirname(__file__), '..')
if sys.path[1] != rangerpath:
	sys.path[1:1] = [rangerpath]

import unittest
from ranger.ext.direction import Direction
from ranger.ext.openstruct import OpenStruct

class TestDirections(unittest.TestCase):
	def test_symmetry(self):
		d1 = Direction(right=4, down=7, relative=True)
		d2 = Direction(left=-4, up=-7, absolute=False)

		def subtest(d):
			self.assertEqual(4, d.right())
			self.assertEqual(7, d.down())
			self.assertEqual(-4, d.left())
			self.assertEqual(-7, d.up())
			self.assertEqual(True, d.relative())
			self.assertEqual(False, d.absolute())

			self.assertTrue(d.horizontal())
			self.assertTrue(d.vertical())

		subtest(d1)
		subtest(d2)

	def test_conflicts(self):
		d3 = Direction(right=5, left=2, up=3, down=6,
				absolute=True, relative=True)
		self.assertEqual(d3.right(), -d3.left())
		self.assertEqual(d3.left(), -d3.right())
		self.assertEqual(d3.up(), -d3.down())
		self.assertEqual(d3.down(), -d3.up())
		self.assertEqual(d3.absolute(), not d3.relative())
		self.assertEqual(d3.relative(), not d3.absolute())

	def test_copy(self):
		d = Direction(right=5)
		c = d.copy()
		self.assertEqual(c.right(), d.right())
		d['right'] += 3
		self.assertNotEqual(c.right(), d.right())
		c['right'] += 3
		self.assertEqual(c.right(), d.right())

		self.assertFalse(d.vertical())
		self.assertTrue(d.horizontal())

#	Doesn't work in python2?
#	def test_duck_typing(self):
#		dct = dict(right=7, down=-3)
#		self.assertEqual(-7, Direction.left(dct))
#		self.assertEqual(3, Direction.up(dct))

	def test_move(self):
		d = Direction(pages=True)
		self.assertEqual(3, d.move(direction=3))
		self.assertEqual(5, d.move(direction=3, current=2))
		self.assertEqual(15, d.move(direction=3, pagesize=5))
		self.assertEqual(9, d.move(direction=3, pagesize=5, maximum=10))
		self.assertEqual(18, d.move(direction=9, override=2))
		d2 = Direction(absolute=True)
		self.assertEqual(5, d2.move(direction=9, override=5))

	def test_select(self):
		d = Direction(down=3)
		lst = list(range(100))
		self.assertEqual((6, [3,4,5,6]), d.select(current=3, pagesize=10, override=None, lst=lst))
		d = Direction(down=3, pages=True)
		self.assertEqual((9, [3,4,5,6,7,8,9]), d.select(current=3, pagesize=2, override=None, lst=lst))

if __name__ == '__main__':
	unittest.main()
ss="mi">1)) # --------------------------------------------------------- history map('H', fm.history_go(-1)) map('L', fm.history_go(1)) # ----------------------------------------------- tagging / marking map('t', fm.tag_toggle()) map('T', fm.tag_remove()) map(' ', fm.mark(toggle=True)) map('v', fm.mark(all=True, toggle=True)) map('V', fm.mark(all=True, val=False)) # ------------------------------------------ file system operations map('yy', 'y<dir>', fm.copy()) map('dd', 'd<dir>', fm.cut()) map('ud', fm.uncut()) map('pp', fm.paste()) map('po', fm.paste(overwrite=True)) map('pl', fm.paste_symlink()) map('p<bg>', fm.hint('press *p* once again to confirm pasting' \ ', or *l* to create symlinks')) # ---------------------------------------------------- run programs map('S', fm.execute_command(os.environ['SHELL'])) map('E', fm.edit_file()) map('.term', fm.execute_command('x-terminal-emulator', flags='d')) map('du', fm.execute_command('du --max-depth=1 -h | less')) # -------------------------------------------------- toggle options map('z<bg>', fm.hint("show_*h*idden *p*review_files *P*review_dirs " \ "*d*irs_first flush*i*nput *m*ouse")) map('zh', fm.toggle_boolean_option('show_hidden')) map('zp', fm.toggle_boolean_option('preview_files')) map('zP', fm.toggle_boolean_option('preview_directories')) map('zi', fm.toggle_boolean_option('flushinput')) map('zd', fm.toggle_boolean_option('sort_directories_first')) map('zc', fm.toggle_boolean_option('collapse_preview')) map('zs', fm.toggle_boolean_option('sort_case_insensitive')) map('zm', fm.toggle_boolean_option('mouse_enabled')) # ------------------------------------------------------------ sort map('o<bg>', 'O<bg>', fm.hint("*s*ize *b*ase*n*ame *m*time" \ " *t*ype *r*everse")) sort_dict = { 's': 'size', 'b': 'basename', 'n': 'basename', 'm': 'mtime', 't': 'type', } for key, val in sort_dict.items(): for key, is_capital in ((key, False), (key.upper(), True)): # reverse if any of the two letters is capital map('o' + key, fm.sort(func=val, reverse=is_capital)) map('O' + key, fm.sort(func=val, reverse=True)) map('or', 'Or', 'oR', 'OR', lambda arg: \ arg.fm.sort(reverse=not arg.fm.settings.sort_reverse)) # ----------------------------------------------- console shortcuts @map("A") def append_to_filename(arg): command = 'rename ' + arg.fm.env.cf.basename arg.fm.open_console(cmode.COMMAND, command) map('cw', fm.open_console(cmode.COMMAND, 'rename ')) map('cd', fm.open_console(cmode.COMMAND, 'cd ')) map('f', fm.open_console(cmode.COMMAND_QUICK, 'find ')) map('bf', fm.open_console(cmode.COMMAND, 'filter ')) map('d<bg>', fm.hint('d*u* (disk usage) d*d* (cut)')) map('@', fm.open_console(cmode.OPEN, '@')) map('#', fm.open_console(cmode.OPEN, 'p!')) # --------------------------------------------- jump to directories map('gh', fm.cd('~')) map('ge', fm.cd('/etc')) map('gu', fm.cd('/usr')) map('gd', fm.cd('/dev')) map('gl', fm.cd('/lib')) map('go', fm.cd('/opt')) map('gv', fm.cd('/var')) map('gr', 'g/', fm.cd('/')) map('gm', fm.cd('/media')) map('gn', fm.cd('/mnt')) map('gs', fm.cd('/srv')) map('gR', fm.cd(RANGERDIR)) # ------------------------------------------------------------ tabs map('gc', '<C-W>', fm.tab_close()) map('gt', '<TAB>', fm.tab_move(1)) map('gT', '<S-TAB>', fm.tab_move(-1)) map('gn', '<C-N>', fm.tab_new()) for n in range(1, 10): map('g' + str(n), fm.tab_open(n)) map('<A-' + str(n) + '>', fm.tab_open(n)) # ------------------------------------------------------- searching map('/', fm.open_console(cmode.SEARCH)) map('n', fm.search()) map('N', fm.search(forward=False)) map('ct', fm.search(order='tag')) map('cc', fm.search(order='ctime')) map('cm', fm.search(order='mimetype')) map('cs', fm.search(order='size')) map('c<bg>', fm.hint('*c*time *m*imetype *s*ize')) # ------------------------------------------------------- bookmarks for key in ALLOWED_BOOKMARK_KEYS: map("`" + key, "'" + key, fm.enter_bookmark(key)) map("m" + key, fm.set_bookmark(key)) map("um" + key, fm.unset_bookmark(key)) map("`<bg>", "'<bg>", "m<bg>", fm.draw_bookmarks()) # ---------------------------------------------------- change views map('i', fm.display_file()) map('<C-P>', fm.display_log()) map('?', '<F1>', fm.display_help()) map('w', lambda arg: arg.fm.ui.open_taskview()) # ------------------------------------------------ system functions map('ZZ', 'ZQ', fm.exit()) map('<C-R>', fm.reset()) map('R', fm.reload_cwd()) @map('<C-C>') def ctrl_c(arg): try: item = arg.fm.loader.queue[0] except: arg.fm.notify("Type Q or :quit<Enter> to exit Ranger") else: arg.fm.notify("Aborting: " + item.get_description()) arg.fm.loader.remove(index=0) map(':', ';', fm.open_console(cmode.COMMAND)) map('>', fm.open_console(cmode.COMMAND_QUICK)) map('!', fm.open_console(cmode.OPEN, prompt='!')) map('s', fm.open_console(cmode.OPEN, prompt='$')) map('r', fm.open_console(cmode.OPEN_QUICK)) # =================================================================== # == Define keys for the pager # =================================================================== map = pager_keys = KeyMapWithDirections() map.merge(global_keys) map.merge(vim_aliases) # -------------------------------------------------------- movement map('<left>', wdg.move(left=4)) map('<right>', wdg.move(right=4)) map('<C-D>', 'd', wdg.move(down=0.5, pages=True)) map('<C-U>', 'u', wdg.move(up=0.5, pages=True)) map('<C-F>', 'f', '<pagedown>', wdg.move(down=1, pages=True)) map('<C-B>', 'b', '<pageup>', wdg.move(up=1, pages=True)) map('<space>', wdg.move(down=0.8, pages=True)) map('<cr>', wdg.move(down=1)) # ---------------------------------------------------------- others map('E', fm.edit_file()) map('?', fm.display_help()) # --------------------------------------------------- bind the keys # There are two different kinds of pagers, each have a different # method for exiting: map = keymanager.get_context('pager') map.merge(pager_keys) map('q', 'i', '<esc>', lambda arg: arg.fm.ui.close_pager()) map = keymanager.get_context('embedded_pager') map.merge(pager_keys) map('q', 'i', '<esc>', lambda arg: arg.fm.ui.close_embedded_pager()) # =================================================================== # == Define keys for the taskview # =================================================================== map = keymanager.get_context('taskview') map.merge(global_keys) map.merge(vim_aliases) map('K', wdg.task_move(0)) map('J', wdg.task_move(-1)) map('dd', wdg.task_remove()) map('?', fm.display_help()) map('w', 'q', ESC, ctrl('d'), ctrl('c'), lambda arg: arg.fm.ui.close_taskview()) # =================================================================== # == Define keys for the console # =================================================================== map = keymanager.get_context('console') map.merge(global_keys) map.merge(readline_aliases) map('<up>', wdg.history_move(-1)) map('<down>', wdg.history_move(1)) map('<home>', wdg.move(right=0, absolute=True)) map('<end>', wdg.move(right=-1, absolute=True)) map('<tab>', wdg.tab()) map('<s-tab>', wdg.tab(-1)) map('<c-c>', '<esc>', wdg.close()) map('<CR>', '<c-j>', wdg.execute()) map('<F1>', lambda arg: arg.fm.display_command_help(arg.wdg)) map('<backspace>', wdg.delete(-1)) map('<delete>', wdg.delete(1)) map('<C-W>', wdg.delete_word()) map('<C-K>', wdg.delete_rest(1)) map('<C-U>', wdg.delete_rest(-1)) map('<C-Y>', wdg.paste()) # Any key which is still undefined will simply be typed in. @map('<any>') def type_key(arg): arg.wdg.type_key(arg.match) # Allow typing in numbers: def type_chr(n): return lambda arg: arg.wdg.type_key(str(n)) for number in range(10): map(str(number), type_chr(number)) # Unmap some global keys so we can type them: map.unmap('Q') map.directions.unmap('%')