From 903f79333a6899e57d2b3e791a3e49f6f6b5b1a8 Mon Sep 17 00:00:00 2001 From: Johnny Kuan Date: Sun, 4 May 2014 02:58:23 -0400 Subject: [PATCH 01/12] minimal tcsh support --- bin/autojump.tcsh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 bin/autojump.tcsh diff --git a/bin/autojump.tcsh b/bin/autojump.tcsh new file mode 100644 index 0000000..5e1f78f --- /dev/null +++ b/bin/autojump.tcsh @@ -0,0 +1,12 @@ +# set user installation paths +if (-d ~/.autojump/bin) then + set path = (~/.autojump/bin path) +endif + +# prepend autojump to cwdcmd (run after every change of working directory) +if (`alias cwdcmd` !~ *autojump*) then + alias cwdcmd 'autojump --add $cwd >/dev/null;' `alias cwdcmd` +endif + +#default autojump command +alias j 'cd `autojump \!:1`' From 225cdb2a8be839055c89c750316bf0020171c6b8 Mon Sep 17 00:00:00 2001 From: Johnny Kuan Date: Mon, 5 May 2014 02:50:51 -0400 Subject: [PATCH 02/12] fix to allow directories starting with hyphens --- bin/autojump.tcsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/autojump.tcsh b/bin/autojump.tcsh index 5e1f78f..a520be0 100644 --- a/bin/autojump.tcsh +++ b/bin/autojump.tcsh @@ -9,4 +9,4 @@ if (`alias cwdcmd` !~ *autojump*) then endif #default autojump command -alias j 'cd `autojump \!:1`' +alias j 'cd `autojump -- \!:1`' From 015deece870452d36fa7e43e82c664ae8dcf4acc Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 25 Jun 2014 16:18:28 +0200 Subject: [PATCH 03/12] Completion and jumping for empty needles This adds support for `j ` and `j` without a needle to jump to the first/best match. Fixes https://github.com/joelthelion/autojump/issues/269 --- bin/autojump | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bin/autojump b/bin/autojump index 0ad7ab9..d2577f8 100755 --- a/bin/autojump +++ b/bin/autojump @@ -193,9 +193,6 @@ def find_matches(entries, needles, check_entries=True): def handle_tab_completion(needle, entries): - if not needle: - sys.exit(0) - tab_needle, tab_index, tab_path = get_tab_entry_info(needle, TAB_SEPARATOR) if tab_path: @@ -364,7 +361,7 @@ def main(args): # noqa save(config, first(add_path(load(config), args.add))) elif args.complete: handle_tab_completion( - needle=first(sanitize(args.directory)), + needle=first(chain(sanitize(args.directory), [''])), entries=entriefy(load(config))) elif args.decrease: data, entry = decrease_path(load(config), get_pwd(), args.decrease) @@ -382,8 +379,12 @@ def main(args): # noqa elif args.stat: print_stats(load(config), config['data_path']) elif not args.directory: - # always return a path to calling shell functions - print_local('.') + # Return best match. + entries = entriefy(load(config)) + print_local(first(chain( + imap(attrgetter('path'), find_matches(entries, [''])), + # always return a path to calling shell functions + ['.']))) else: entries = entriefy(load(config)) needles = sanitize(args.directory) From 68b457184df975ee392b99806b8f98d8f2edc2e7 Mon Sep 17 00:00:00 2001 From: Felix Laurie von Massenbach Date: Thu, 26 Jun 2014 02:00:17 +0100 Subject: [PATCH 04/12] Fix bad encoding. In python3, string.encode returns a byte array like: b'14.1:\t/home/felix/devel/autojump' This stops autojump from functioning at all. --- bin/autojump_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/autojump_utils.py b/bin/autojump_utils.py index 48f2185..bac2f37 100644 --- a/bin/autojump_utils.py +++ b/bin/autojump_utils.py @@ -30,6 +30,8 @@ def create_dir(path): def encode_local(string): """Converts string into user's preferred encoding.""" + if is_python3(): + return string return string.encode(sys.getfilesystemencoding() or 'utf-8') From 2100f993b3b9b1cf5ae0f943589e6125194846ff Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 12:38:31 -0700 Subject: [PATCH 05/12] formatting cleanup --- bin/autojump | 2 +- bin/autojump_data.py | 2 +- install.py | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bin/autojump b/bin/autojump index d2577f8..a44e86b 100755 --- a/bin/autojump +++ b/bin/autojump @@ -282,7 +282,7 @@ def match_consecutive(needles, haystack, ignore_case=False): regex_no_sep_end = regex_no_sep + '$' regex_one_sep = regex_no_sep + sep + regex_no_sep # can't use compiled regex because of flags - regex_needle = regex_one_sep.join(needles).replace('\\', '\\\\') + regex_no_sep_end + regex_needle = regex_one_sep.join(needles).replace('\\', '\\\\') + regex_no_sep_end # noqa regex_flags = re.IGNORECASE | re.UNICODE if ignore_case else re.UNICODE found = lambda entry: re.search( regex_needle, diff --git a/bin/autojump_data.py b/bin/autojump_data.py index f367a59..da86c90 100644 --- a/bin/autojump_data.py +++ b/bin/autojump_data.py @@ -137,5 +137,5 @@ def save(config, data): # create backup file if it doesn't exist or is older than BACKUP_THRESHOLD if not os.path.exists(config['backup_path']) or \ - (time() - os.path.getmtime(config['backup_path']) > BACKUP_THRESHOLD): #noqa + (time() - os.path.getmtime(config['backup_path']) > BACKUP_THRESHOLD): # noqa shutil.copy(config['data_path'], config['backup_path']) diff --git a/install.py b/install.py index 0e8d95a..9fc3713 100755 --- a/install.py +++ b/install.py @@ -206,7 +206,6 @@ def main(args): if args.custom_install: modify_autojump_sh(etc_dir, args.dryrun) - print_post_installation_message(etc_dir, bin_dir) From 3465bb1f8430749e6535738943801cae26ce09ee Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 12:33:53 -0700 Subject: [PATCH 06/12] Migrate from Yelp/Testify to py.test. Closes #300. --- .travis.yml | 5 +- Makefile | 2 +- dev-requirements.txt | 3 +- tests/autojump_utils_test.py | 290 +++++++++++++---------------------- 4 files changed, 113 insertions(+), 187 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8940265..c3b58e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,12 @@ language: python python: - 2.6 - 2.7 + - 3.2 + - 3.3 + - 3.4 install: - - pip install --use-mirrors testify + - pip install --use-mirrors pytest script: - make test diff --git a/Makefile b/Makefile index 82a111b..0d8af9d 100644 --- a/Makefile +++ b/Makefile @@ -40,4 +40,4 @@ tar: test: @find . -type f -iname "*.pyc" -delete - testify -v tests -x disabled + py.test -rsxX -q diff --git a/dev-requirements.txt b/dev-requirements.txt index a8430c6..817c7a4 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,2 +1,3 @@ flake8>=2.0.0 -testify +mock +pytest diff --git a/tests/autojump_utils_test.py b/tests/autojump_utils_test.py index 815347a..fe040bb 100644 --- a/tests/autojump_utils_test.py +++ b/tests/autojump_utils_test.py @@ -1,39 +1,23 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from random import randrange -from shutil import rmtree -from tempfile import gettempdir -from tempfile import mkdtemp import os import sys import mock -from testify import TestCase -from testify import assert_equal -from testify import assert_false -from testify import assert_raises -from testify import assert_true -from testify import class_setup -from testify import class_teardown -from testify import run -from testify import setup -from testify import suite -from testify import teardown +import pytest +# Python 3 compatibility if sys.version_info[0] == 3: os.getcwdu = os.getcwd sys.path.append(os.path.join(os.getcwd(), 'bin')) import autojump_utils -from autojump_utils import create_dir from autojump_utils import encode_local from autojump_utils import first -from autojump_utils import get_pwd from autojump_utils import get_tab_entry_info from autojump_utils import has_uppercase from autojump_utils import in_bash from autojump_utils import last -from autojump_utils import move_file from autojump_utils import sanitize from autojump_utils import second from autojump_utils import surround_quotes @@ -41,170 +25,108 @@ from autojump_utils import take from autojump_utils import unico -class StringUnitTests(TestCase): - @mock.patch.object(sys, 'getfilesystemencoding', return_value='ascii') - def test_encode_local_ascii(self, _): - assert_equal(encode_local(u'foo'), b'foo') - - @suite('disabled', reason='#246') - def test_encode_local_ascii_fails(self): - with assert_raises(UnicodeDecodeError): - with mock.patch.object( - sys, - 'getfilesystemencoding', - return_value='ascii'): - encode_local(u'日本語') - - @mock.patch.object(sys, 'getfilesystemencoding', return_value=None) - def test_encode_local_empty(self, _): - assert_equal(encode_local(b'foo'), u'foo') - - @mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8') - def test_encode_local_unicode(self, _): - assert_equal(encode_local(b'foo'), u'foo') - assert_equal(encode_local(u'foo'), u'foo') - - def test_has_uppercase(self): - assert_true(has_uppercase('Foo')) - assert_true(has_uppercase('foO')) - assert_false(has_uppercase('foo')) - assert_false(has_uppercase('')) - - @mock.patch.object(autojump_utils, 'in_bash', return_value=True) - def test_surround_quotes_in_bash(self, _): - assert_equal(surround_quotes('foo'), '"foo"') - - @mock.patch.object(autojump_utils, 'in_bash', return_value=False) - def test_dont_surround_quotes_not_in_bash(self, _): - assert_equal(surround_quotes('foo'), 'foo') - - def test_sanitize(self): - assert_equal(sanitize([]), []) - assert_equal(sanitize([r'/foo/bar/', r'/']), [u'/foo/bar', u'/']) - - def test_unico(self): - assert_equal(unico(b'blah'), u'blah') - assert_equal(unico(b'日本語'), u'日本語') - assert_equal(unico(u'でもおれは中国人だ。'), u'でもおれは中国人だ。') - - -class IterationUnitTests(TestCase): - def test_first(self): - assert_equal(first(xrange(5)), 0) - assert_equal(first([]), None) - - def test_second(self): - assert_equal(second(xrange(5)), 1) - assert_equal(second([]), None) - - def test_last(self): - assert_equal(last(xrange(4)), 3) - assert_equal(last([]), None) - - def test_take(self): - assert_equal(list(take(1, xrange(3))), [0]) - assert_equal(list(take(2, xrange(3))), [0, 1]) - assert_equal(list(take(4, xrange(3))), [0, 1, 2]) - assert_equal(list(take(10, [])), []) - - -class EnvironmentalVariableIntegrationTests(TestCase): - @setup - def create_tmp_dir(self): - self.tmp_dir = mkdtemp() - - @teardown - def delete_tmp_dir(self): - try: - rmtree(self.tmp_dir) - except OSError: - pass - - def test_in_bash(self): - os.environ['SHELL'] = '/bin/bash' - assert_true(in_bash()) +# strings +@mock.patch.object(sys, 'getfilesystemencoding', return_value='ascii') +def test_encode_local_ascii(_): + assert encode_local(u'foo') == b'foo' + + +@pytest.mark.xfail(reason='issue #246') +def test_encode_local_ascii_fails(): + with pytest.raises(UnicodeDecodeError): + with mock.patch.object( + sys, + 'getfilesystemencoding', + return_value='ascii'): + encode_local(u'日本語') + + +@mock.patch.object(sys, 'getfilesystemencoding', return_value=None) +def test_encode_local_empty(_): + assert encode_local(b'foo') == u'foo' + + +@mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8') +def test_encode_local_unicode(_): + assert encode_local(b'foo') == u'foo' + assert encode_local(u'foo') == u'foo' + + +def test_has_uppercase(): + assert has_uppercase('Foo') + assert has_uppercase('foO') + assert not has_uppercase('foo') + assert not has_uppercase('') + + +@mock.patch.object(autojump_utils, 'in_bash', return_value=True) +def test_surround_quotes_in_bash(_): + assert surround_quotes('foo') == '"foo"' + + +@mock.patch.object(autojump_utils, 'in_bash', return_value=False) +def test_dont_surround_quotes_not_in_bash(_): + assert surround_quotes('foo') == 'foo' + + +def test_sanitize(): + assert sanitize([]) == [] + assert sanitize([r'/foo/bar/', r'/']) == [u'/foo/bar', u'/'] + + +def test_unico(): + assert unico(b'blah') == u'blah' + assert unico(b'日本語') == u'日本語' + assert unico(u'でもおれは中国人だ。') == u'でもおれは中国人だ。' + + +# iteration +def test_first(): + assert first(xrange(5)) == 0 + assert first([]) is None + + +def test_second(): + assert second(xrange(5)) == 1 + assert second([]) is None + + +def test_last(): + assert last(xrange(4)) == 3 + assert last([]) is None + + +def test_take(): + assert list(take(1, xrange(3))) == [0] + assert list(take(2, xrange(3))) == [0, 1] + assert list(take(4, xrange(3))) == [0, 1, 2] + assert list(take(10, [])) == [] + + +# environment variables +def test_in_bash(): + for path in ['/bin/bash', '/usr/bin/bash']: + os.environ['SHELL'] = path + assert in_bash() + + for path in ['/bin/zsh', '/usr/bin/zsh']: os.environ['SHELL'] = '/usr/bin/zsh' - assert_false(in_bash()) - - def test_good_get_pwd(self): - os.chdir(self.tmp_dir) - assert_equal(get_pwd(), self.tmp_dir) - - def test_bad_get_pwd(self): - os.chdir(self.tmp_dir) - rmtree(self.tmp_dir) - assert_raises(OSError, get_pwd) - - -class FileSystemIntegrationTests(TestCase): - @class_setup - def init(self): - self.tmp_dir = os.path.join(gettempdir(), 'autojump') - os.makedirs(self.tmp_dir) - - @class_teardown - def cleanup(self): - try: - rmtree(self.tmp_dir) - except OSError: - pass - - def get_random_path(self): - path = gettempdir() - - while os.path.exists(path): - random_string = '%30x' % randrange(16 ** 30) - path = os.path.join(self.tmp_dir, random_string) - - return path - - def get_random_file(self): - path = self.get_random_path() - with open(path, 'w+') as f: - f.write('filler\n') - - return path - - def test_create_dir(self): - path = self.get_random_path() - create_dir(path) - assert_true(os.path.exists(path)) - - # should not raise OSError if directory already exists - create_dir(path) - assert_true(os.path.exists(path)) - - def test_move_file(self): - src = self.get_random_file() - dst = self.get_random_path() - assert_true(os.path.exists(src)) - assert_false(os.path.exists(dst)) - move_file(src, dst) - assert_false(os.path.exists(src)) - assert_true(os.path.exists(dst)) - - -class HelperFunctionsUnitTests(TestCase): - def test_get_needle(self): - assert_equal( - get_tab_entry_info('foo__', '__'), - ('foo', None, None)) - - def test_get_index(self): - assert_equal( - get_tab_entry_info('foo__2', '__'), - ('foo', 2, None)) - - def test_get_path(self): - assert_equal( - get_tab_entry_info('foo__3__/foo/bar', '__'), - ('foo', 3, '/foo/bar')) - - def test_get_none(self): - assert_equal( - get_tab_entry_info('gibberish content', '__'), - (None, None, None)) - - -if __name__ == "__main__": - run() + assert not in_bash() + + +# helper functions +def test_get_needle(): + assert get_tab_entry_info('foo__', '__') == ('foo', None, None) + + +def test_get_index(): + assert get_tab_entry_info('foo__2', '__') == ('foo', 2, None) + + +def test_get_path(): + assert get_tab_entry_info('foo__3__/foo/bar', '__') \ + == ('foo', 3, '/foo/bar') + + +def test_get_none(): + assert get_tab_entry_info('gibberish content', '__') == (None, None, None) From 969fb4e6ed5c074d01b9794357e0d18e1c802c22 Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 16:57:00 -0700 Subject: [PATCH 07/12] Add tox for testing with different Python versions. --- .gitignore | 1 + .travis.yml | 19 +++++++++++-------- Makefile | 6 +++--- dev-requirements.txt | 3 ++- setup.cfg | 5 ----- tox.ini | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 49 insertions(+), 17 deletions(-) delete mode 100644 setup.cfg create mode 100644 tox.ini diff --git a/.gitignore b/.gitignore index f1713db..adbb218 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *~ *.tar.gz *.patch +.tox tags diff --git a/.travis.yml b/.travis.yml index c3b58e6..f04fa15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,17 @@ language: python -python: - - 2.6 - - 2.7 - - 3.2 - - 3.3 - - 3.4 +python: 2.7 + +env: + - TOX_ENV=py26 + - TOX_ENV=py27 + - TOX_ENV=py32 + - TOX_ENV=py33 + - TOX_ENV=py34 + - TOX_ENV=flake8 install: - - pip install --use-mirrors pytest + - pip install tox script: - - make test + - tox -e $TOX_ENV diff --git a/Makefile b/Makefile index 0d8af9d..a357f26 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ docs: pandoc -s -w markdown docs/header.md docs/install.md docs/body.md -o README.md lint: - @flake8 ./ --config=setup.cfg + @flake8 ./ --config=tox.ini release: docs # Check for tag existence @@ -38,6 +38,6 @@ tar: git archive --format=tar --prefix autojump_v$(VERSION)/ $(TAGNAME) | gzip > autojump_v$(VERSION).tar.gz sha1sum autojump_v$(VERSION).tar.gz -test: +test: lint @find . -type f -iname "*.pyc" -delete - py.test -rsxX -q + tox diff --git a/dev-requirements.txt b/dev-requirements.txt index 817c7a4..2c84e24 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,3 +1,4 @@ -flake8>=2.0.0 +flake8 mock pytest +tox diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f917c4a..0000000 --- a/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[flake8] -filename = *.py,autojump -ignore = E126,E128 -max-line-length = 79 -max-complexity = 10 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..971d67a --- /dev/null +++ b/tox.ini @@ -0,0 +1,32 @@ +[tox] +envlist = + py26, + py27, + py32, + py33, + py34 +# ignore missing setup.py +skipsdist = True + +[testenv] +deps = -rdev-requirements.txt +commands = py.test -rsxX -q + +[testenv:flake8] +deps = flake8 +commands = flake8 . + +[flake8] +filename = + *.py, + autojump +ignore = + E126, + E128 +max-line-length = 79 +max-complexity = 10 +show-pep8 = True + +[pytest] +addopts = -rsxX -q +norecursedirs = .git .tox docs From e30d7d392e42dcffdb60c9da7bf9f9449128aa8e Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 17:26:02 -0700 Subject: [PATCH 08/12] Duplicate fbf932 changes in proper locations and rebuild docs. --- README.md | 8 ++++---- docs/autojump.1 | 4 ++-- docs/header.md | 4 ++-- docs/install.md | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cd5643c..26b499e 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ can be used with `autojump` can be used with `j` and vice versa. jo music -- Opening a file manager to a child directory is also supported: + Opening a file manager to a child directory is also supported: jco images @@ -54,7 +54,7 @@ can be used with `autojump` can be used with `j` and vice versa. a different entry. In the above example, `j w in` would then change directory to /home/user/work/inbox. -For more options refer to the help: +For more options refer to help: autojump --help @@ -98,7 +98,7 @@ MacPorts also available: Windows ------- -Windows support is enabled by [clink](https://code.google.com/p/clink/), +Windows support is enabled by [clink](https://code.google.com/p/clink/) which should be installed prior to installing autojump. ### MANUAL @@ -107,7 +107,7 @@ Grab a copy of autojump: git clone git://github.com/joelthelion/autojump.git -Run the installation script and follow the on screen instructions. +Run the installation script and follow on screen instructions. cd autojump ./install.py or ./uninstall.py diff --git a/docs/autojump.1 b/docs/autojump.1 index d3c8d25..188194f 100644 --- a/docs/autojump.1 +++ b/docs/autojump.1 @@ -25,7 +25,7 @@ j\ foo .fi .RE .IP \[bu] 2 -Jump To A Child Directory +Jump To A Child Directory: .RS 2 .PP Sometimes it\[aq]s convenient to jump to a child directory @@ -52,7 +52,7 @@ jo\ music \f[] .fi .PP -Opening a file manager to a child directory is also supported. +Opening a file manager to a child directory is also supported: .IP .nf \f[C] diff --git a/docs/header.md b/docs/header.md index 09fc42c..379af3b 100644 --- a/docs/header.md +++ b/docs/header.md @@ -21,7 +21,7 @@ be used with `autojump` can be used with `j` and vice versa. j foo -- Jump To A Child Directory +- Jump To A Child Directory: Sometimes it's convenient to jump to a child directory (sub-directory of current directory) rather than typing out the full name. @@ -35,7 +35,7 @@ be used with `autojump` can be used with `j` and vice versa. jo music - Opening a file manager to a child directory is also supported. + Opening a file manager to a child directory is also supported: jco images diff --git a/docs/install.md b/docs/install.md index a617b3c..715dfa8 100644 --- a/docs/install.md +++ b/docs/install.md @@ -47,4 +47,4 @@ Grab a copy of autojump: Run the installation script and follow on screen instructions. cd autojump - ./install.py or ./uinstall.py + ./install.py or ./uninstall.py From 567ae121ab72b0a2eb60e88637eed51a51935229 Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 19:06:16 -0700 Subject: [PATCH 09/12] Add install / uninstall / documentation for tcsh shell. --- README.md | 7 ++++++- docs/install.md | 7 ++++++- install.py | 3 ++- tests/autojump_utils_test.py | 1 - uninstall.py | 2 ++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 26b499e..2e31378 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,12 @@ INSTALLATION ### REQUIREMENTS - Python v2.6+ -- Bash v4.0+, zsh, fish, or clink (Windows) +- Supported shells: + - bash v4.0+ + - zsh + - fish + - tcsh (experimental) + - clink on Windows (experimental) ### AUTOMATIC diff --git a/docs/install.md b/docs/install.md index 715dfa8..3ad6a98 100644 --- a/docs/install.md +++ b/docs/install.md @@ -3,7 +3,12 @@ ### REQUIREMENTS - Python v2.6+ -- Bash v4.0+, zsh, fish, or clink (Windows) +- Supported shells: + - bash v4.0+ + - zsh + - fish + - tcsh (experimental) + - clink (Windows, experimental) ### AUTOMATIC diff --git a/install.py b/install.py index 9fc3713..a8d68c9 100755 --- a/install.py +++ b/install.py @@ -10,7 +10,7 @@ import sys sys.path.append('bin') from autojump_argparse import ArgumentParser -SUPPORTED_SHELLS = ('bash', 'zsh', 'fish') +SUPPORTED_SHELLS = ('bash', 'zsh', 'fish', 'tcsh') def cp(src, dest, dryrun=False): @@ -157,6 +157,7 @@ def print_post_installation_message(etc_dir, bin_dir): print('\n\t' + source_msg) if get_shell() == 'zsh': print("\n\tautoload -U compinit && compinit -u") + print("\nPlease restart terminal(s) before running autojump.\n") diff --git a/tests/autojump_utils_test.py b/tests/autojump_utils_test.py index fe040bb..d6ed105 100644 --- a/tests/autojump_utils_test.py +++ b/tests/autojump_utils_test.py @@ -6,7 +6,6 @@ import sys import mock import pytest -# Python 3 compatibility if sys.version_info[0] == 3: os.getcwdu = os.getcwd sys.path.append(os.path.join(os.getcwd(), 'bin')) diff --git a/uninstall.py b/uninstall.py index 3e41fc6..ab76317 100755 --- a/uninstall.py +++ b/uninstall.py @@ -78,6 +78,7 @@ def remove_custom_installation(args, dryrun=False): rm(os.path.join(etc_dir, 'autojump.sh'), dryrun) rm(os.path.join(etc_dir, 'autojump.bash'), dryrun) rm(os.path.join(etc_dir, 'autojump.fish'), dryrun) + rm(os.path.join(etc_dir, 'autojump.tcsh'), dryrun) rm(os.path.join(etc_dir, 'autojump.zsh'), dryrun) rm(os.path.join(zshshare_dir, '_j'), dryrun) rmdir(icon_dir, dryrun) @@ -114,6 +115,7 @@ def remove_system_installation(dryrun=False): rm(os.path.join(etc_dir, 'autojump.sh'), dryrun) rm(os.path.join(etc_dir, 'autojump.bash'), dryrun) rm(os.path.join(etc_dir, 'autojump.fish'), dryrun) + rm(os.path.join(etc_dir, 'autojump.tcsh'), dryrun) rm(os.path.join(etc_dir, 'autojump.zsh'), dryrun) rm(os.path.join(zshshare_dir, '_j'), dryrun) rmdir(icon_dir, dryrun) From 921b52e9d57617e6b1843499650aecd55b561839 Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 19:34:45 -0700 Subject: [PATCH 10/12] Add a u() wrapper to enable testing to work in both Python2 and Python3. --- tests/autojump_utils_test.py | 37 +++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/autojump_utils_test.py b/tests/autojump_utils_test.py index d6ed105..811adbf 100644 --- a/tests/autojump_utils_test.py +++ b/tests/autojump_utils_test.py @@ -6,16 +6,14 @@ import sys import mock import pytest -if sys.version_info[0] == 3: - os.getcwdu = os.getcwd sys.path.append(os.path.join(os.getcwd(), 'bin')) - import autojump_utils from autojump_utils import encode_local from autojump_utils import first from autojump_utils import get_tab_entry_info from autojump_utils import has_uppercase from autojump_utils import in_bash +from autojump_utils import is_python3 from autojump_utils import last from autojump_utils import sanitize from autojump_utils import second @@ -24,10 +22,23 @@ from autojump_utils import take from autojump_utils import unico +if is_python3(): + os.getcwdu = os.getcwd + + +def u(string): + """ + This is a unicode() wrapper since u'string' fails in Python3. + """ + if is_python3(): + return string + return unicode(string, encoding='utf-8', errors='strict') + + # strings @mock.patch.object(sys, 'getfilesystemencoding', return_value='ascii') def test_encode_local_ascii(_): - assert encode_local(u'foo') == b'foo' + assert encode_local(u('foo')) == b'foo' @pytest.mark.xfail(reason='issue #246') @@ -37,18 +48,18 @@ def test_encode_local_ascii_fails(): sys, 'getfilesystemencoding', return_value='ascii'): - encode_local(u'日本語') + encode_local(u('日本語')) @mock.patch.object(sys, 'getfilesystemencoding', return_value=None) def test_encode_local_empty(_): - assert encode_local(b'foo') == u'foo' + assert encode_local(b'foo') == u('foo') @mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8') -def test_encode_local_unicode(_): - assert encode_local(b'foo') == u'foo' - assert encode_local(u'foo') == u'foo' +def test_encode_local_u(_): + assert encode_local(b'foo') == u('foo') + assert encode_local(u('foo')) == u('foo') def test_has_uppercase(): @@ -70,13 +81,13 @@ def test_dont_surround_quotes_not_in_bash(_): def test_sanitize(): assert sanitize([]) == [] - assert sanitize([r'/foo/bar/', r'/']) == [u'/foo/bar', u'/'] + assert sanitize([r'/foo/bar/', r'/']) == [u('/foo/bar'), u('/')] def test_unico(): - assert unico(b'blah') == u'blah' - assert unico(b'日本語') == u'日本語' - assert unico(u'でもおれは中国人だ。') == u'でもおれは中国人だ。' + assert unico(str('blah')) == u('blah') + assert unico(str('日本語')) == u('日本語') + assert unico(u('でもおれは中国人だ。')) == u('でもおれは中国人だ。') # iteration From 62c0877479289fda46e4517944644236a3bf5875 Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 19:37:32 -0700 Subject: [PATCH 11/12] Add xrange() and fix second() for Python3. --- bin/autojump_utils.py | 8 ++++++-- tests/autojump_utils_test.py | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/bin/autojump_utils.py b/bin/autojump_utils.py index bac2f37..949b4fd 100644 --- a/bin/autojump_utils.py +++ b/bin/autojump_utils.py @@ -172,8 +172,12 @@ def sanitize(directories): def second(xs): it = iter(xs) try: - it.next() - return it.next() + if is_python2(): + it.next() + return it.next() + elif is_python3(): + next(it) + return next(it) except StopIteration: return None diff --git a/tests/autojump_utils_test.py b/tests/autojump_utils_test.py index 811adbf..42dd7f5 100644 --- a/tests/autojump_utils_test.py +++ b/tests/autojump_utils_test.py @@ -24,6 +24,7 @@ from autojump_utils import unico if is_python3(): os.getcwdu = os.getcwd + xrange = range def u(string): From f23727ed0f4ed267e5cb2e707ea94e76f2b9ac15 Mon Sep 17 00:00:00 2001 From: William Ting Date: Sat, 28 Jun 2014 20:16:06 -0700 Subject: [PATCH 12/12] Disable Unicode tests for Python 3. Closes #299. Due to the mixed testing between Python 2 and 3 and different string implementations, there's no easy way to test Unicode stuff. --- tests/autojump_utils_test.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/autojump_utils_test.py b/tests/autojump_utils_test.py index 42dd7f5..147feb5 100644 --- a/tests/autojump_utils_test.py +++ b/tests/autojump_utils_test.py @@ -29,7 +29,7 @@ if is_python3(): def u(string): """ - This is a unicode() wrapper since u'string' fails in Python3. + This is a unicode() wrapper since u'string' is a Python3 compiler error. """ if is_python3(): return string @@ -37,28 +37,29 @@ def u(string): # strings +@pytest.mark.skipif(is_python3(), reason="Unicode sucks.") @mock.patch.object(sys, 'getfilesystemencoding', return_value='ascii') def test_encode_local_ascii(_): assert encode_local(u('foo')) == b'foo' -@pytest.mark.xfail(reason='issue #246') -def test_encode_local_ascii_fails(): +@pytest.mark.skipif(is_python3(), reason="Unicode sucks.") +@pytest.mark.xfail(reason="disabled due to pytest bug: https://bitbucket.org/hpk42/pytest/issue/534/pytest-fails-to-catch-unicodedecodeerrors") # noqa +@mock.patch.object(sys, 'getfilesystemencoding', return_value='ascii') +def test_encode_local_ascii_fails(_): with pytest.raises(UnicodeDecodeError): - with mock.patch.object( - sys, - 'getfilesystemencoding', - return_value='ascii'): - encode_local(u('日本語')) + encode_local(u('日本語')) +@pytest.mark.skipif(is_python3(), reason="Unicode sucks.") @mock.patch.object(sys, 'getfilesystemencoding', return_value=None) def test_encode_local_empty(_): assert encode_local(b'foo') == u('foo') +@pytest.mark.skipif(is_python3(), reason="Unicode sucks.") @mock.patch.object(sys, 'getfilesystemencoding', return_value='utf-8') -def test_encode_local_u(_): +def test_encode_local_unicode(_): assert encode_local(b'foo') == u('foo') assert encode_local(u('foo')) == u('foo') @@ -85,6 +86,7 @@ def test_sanitize(): assert sanitize([r'/foo/bar/', r'/']) == [u('/foo/bar'), u('/')] +@pytest.mark.skipif(is_python3(), reason="Unicode sucks.") def test_unico(): assert unico(str('blah')) == u('blah') assert unico(str('日本語')) == u('日本語')