mirror of
https://github.com/wting/autojump
synced 2024-10-27 20:34:07 +00:00
Added decaying with time, fixed powershell, fixed windows git bash, fixed jc and child directory descent
This commit is contained in:
parent
0d7b33247b
commit
481e5f37bb
185
bin/autojump
185
bin/autojump
@ -26,6 +26,8 @@ from itertools import chain
|
||||
from math import sqrt
|
||||
from operator import attrgetter
|
||||
from operator import itemgetter
|
||||
from sys import stderr
|
||||
import re
|
||||
|
||||
if sys.version_info[0] == 3:
|
||||
ifilter = filter
|
||||
@ -65,73 +67,39 @@ from autojump_utils import sanitize
|
||||
from autojump_utils import take
|
||||
from autojump_utils import unico
|
||||
|
||||
VERSION = '22.5.3'
|
||||
VERSION = "22.5.3"
|
||||
FUZZY_MATCH_THRESHOLD = 0.6
|
||||
TAB_ENTRIES_COUNT = 9
|
||||
TAB_SEPARATOR = '__'
|
||||
TAB_SEPARATOR = "__"
|
||||
|
||||
|
||||
def set_defaults():
|
||||
config = {}
|
||||
|
||||
if is_osx():
|
||||
data_home = os.path.join(os.path.expanduser('~'), 'Library')
|
||||
data_home = os.path.join(os.path.expanduser("~"), "Library")
|
||||
elif is_windows():
|
||||
data_home = os.getenv('APPDATA')
|
||||
data_home = os.getenv("APPDATA")
|
||||
else:
|
||||
data_home = os.getenv(
|
||||
'XDG_DATA_HOME',
|
||||
os.path.join(
|
||||
os.path.expanduser('~'),
|
||||
'.local',
|
||||
'share',
|
||||
),
|
||||
)
|
||||
config['data_path'] = os.path.join(data_home, 'autojump', 'autojump.txt')
|
||||
config['backup_path'] = os.path.join(data_home, 'autojump', 'autojump.txt.bak')
|
||||
data_home = os.getenv("XDG_DATA_HOME", os.path.join(os.path.expanduser("~"), ".local", "share"))
|
||||
config["data_path"] = os.path.join(data_home, "autojump", "autojump.txt")
|
||||
config["backup_path"] = os.path.join(data_home, "autojump", "autojump.txt.bak")
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = ArgumentParser(
|
||||
description='Automatically jump to directory passed as an argument.',
|
||||
epilog='Please see autojump(1) man pages for full documentation.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'directory', metavar='DIRECTORY', nargs='*', default='',
|
||||
help='directory to jump to',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-a', '--add', metavar='DIRECTORY',
|
||||
help='add path',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i', '--increase', metavar='WEIGHT', nargs='?', type=int,
|
||||
const=10, default=False,
|
||||
help='increase current directory weight',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-d', '--decrease', metavar='WEIGHT', nargs='?', type=int,
|
||||
const=15, default=False,
|
||||
help='decrease current directory weight',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--complete', action='store_true', default=False,
|
||||
help='used for tab completion',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--purge', action='store_true', default=False,
|
||||
help='remove non-existent paths from database',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-s', '--stat', action='store_true', default=False,
|
||||
help='show database entries and their key weights',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-v', '--version', action='version', version='%(prog)s v' +
|
||||
VERSION, help='show version information',
|
||||
description="Automatically jump to directory passed as an argument.", epilog="Please see autojump(1) man pages for full documentation."
|
||||
)
|
||||
parser.add_argument("directory", metavar="DIRECTORY", nargs="*", default="", help="directory to jump to")
|
||||
parser.add_argument("-a", "--add", metavar="DIRECTORY", help="add path")
|
||||
parser.add_argument("-i", "--increase", metavar="WEIGHT", nargs="?", type=int, const=10, default=False, help="increase current directory weight")
|
||||
parser.add_argument("-d", "--decrease", metavar="WEIGHT", nargs="?", type=int, const=15, default=False, help="decrease current directory weight")
|
||||
parser.add_argument("--complete", action="store_true", default=False, help="used for tab completion")
|
||||
parser.add_argument("--purge", action="store_true", default=False, help="remove non-existent paths from database")
|
||||
parser.add_argument("-s", "--stat", action="store_true", default=False, help="show database entries and their key weights")
|
||||
parser.add_argument("-v", "--version", action="version", version="%(prog)s v" + VERSION, help="show version information")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@ -145,12 +113,14 @@ def add_path(data, path, weight=10):
|
||||
path.
|
||||
"""
|
||||
path = unico(path).rstrip(os.sep)
|
||||
if path == os.path.expanduser('~'):
|
||||
if path == os.path.expanduser("~"):
|
||||
return data, Entry(path, 0)
|
||||
slash_only_path = re.sub(re.escape(os.sep), "/", path)
|
||||
orig_weight = data.get(slash_only_path, 0)
|
||||
data[slash_only_path] = sqrt((orig_weight ** 2) + (weight ** 2))
|
||||
stderr.write(f"Original weight: {orig_weight} plus weight {weight} = {data[slash_only_path]}")
|
||||
|
||||
data[path] = sqrt((data.get(path, 0) ** 2) + (weight ** 2))
|
||||
|
||||
return data, Entry(path, data[path])
|
||||
return data, Entry(path, data[slash_only_path])
|
||||
|
||||
|
||||
def decrease_path(data, path, weight=15):
|
||||
@ -171,7 +141,7 @@ def detect_smartcase(needles):
|
||||
def find_matches(entries, needles, check_entries=True):
|
||||
"""Return an iterator to matching entries."""
|
||||
# TODO(wting|2014-02-24): replace assertion with unit test
|
||||
assert isinstance(needles, list), 'Needles must be a list.'
|
||||
assert isinstance(needles, list), "Needles must be a list."
|
||||
ignore_case = detect_smartcase(needles)
|
||||
|
||||
try:
|
||||
@ -188,19 +158,11 @@ def find_matches(entries, needles, check_entries=True):
|
||||
else:
|
||||
path_exists = lambda _: True
|
||||
|
||||
data = sorted(
|
||||
entries,
|
||||
key=attrgetter('weight', 'path'),
|
||||
reverse=True,
|
||||
)
|
||||
data = sorted(entries, key=attrgetter("weight", "path"), reverse=True)
|
||||
|
||||
return ifilter(
|
||||
lambda entry: not is_cwd(entry) and path_exists(entry),
|
||||
chain(
|
||||
match_consecutive(needles, data, ignore_case),
|
||||
match_fuzzy(needles, data, ignore_case),
|
||||
match_anywhere(needles, data, ignore_case),
|
||||
),
|
||||
chain(match_consecutive(needles, data, ignore_case), match_fuzzy(needles, data, ignore_case), match_anywhere(needles, data, ignore_case)),
|
||||
)
|
||||
|
||||
|
||||
@ -211,35 +173,12 @@ def handle_tab_completion(needle, entries):
|
||||
print_local(tab_path)
|
||||
elif tab_index:
|
||||
get_ith_path = lambda i, iterable: last(take(i, iterable)).path
|
||||
print_local(get_ith_path(
|
||||
tab_index,
|
||||
find_matches(entries, [tab_needle], check_entries=False),
|
||||
))
|
||||
print_local(get_ith_path(tab_index, find_matches(entries, [tab_needle], check_entries=False)))
|
||||
elif tab_needle:
|
||||
# found partial tab completion entry
|
||||
print_tab_menu(
|
||||
tab_needle,
|
||||
take(
|
||||
TAB_ENTRIES_COUNT, find_matches(
|
||||
entries,
|
||||
[tab_needle],
|
||||
check_entries=False,
|
||||
),
|
||||
),
|
||||
TAB_SEPARATOR,
|
||||
)
|
||||
print_tab_menu(tab_needle, take(TAB_ENTRIES_COUNT, find_matches(entries, [tab_needle], check_entries=False)), TAB_SEPARATOR)
|
||||
else:
|
||||
print_tab_menu(
|
||||
needle,
|
||||
take(
|
||||
TAB_ENTRIES_COUNT, find_matches(
|
||||
entries,
|
||||
[needle],
|
||||
check_entries=False,
|
||||
),
|
||||
),
|
||||
TAB_SEPARATOR,
|
||||
)
|
||||
print_tab_menu(needle, take(TAB_ENTRIES_COUNT, find_matches(entries, [needle], check_entries=False)), TAB_SEPARATOR)
|
||||
|
||||
|
||||
def purge_missing_paths(entries):
|
||||
@ -252,26 +191,24 @@ def print_stats(data, data_path):
|
||||
for path, weight in sorted(data.items(), key=itemgetter(1)):
|
||||
print_entry(Entry(path, weight))
|
||||
|
||||
print('________________________________________\n')
|
||||
print('%d:\t total weight' % sum(data.values()))
|
||||
print('%d:\t number of entries' % len(data))
|
||||
print("________________________________________\n")
|
||||
print("%d:\t total weight" % sum(data.values()))
|
||||
print("%d:\t number of entries" % len(data))
|
||||
|
||||
try:
|
||||
print_local(
|
||||
'%.2f:\t current directory weight' % data.get(os.getcwdu(), 0),
|
||||
)
|
||||
print_local("%.2f:\t current directory weight" % data.get(os.getcwdu(), 0))
|
||||
except OSError:
|
||||
# current directory no longer exists
|
||||
pass
|
||||
|
||||
print('\ndata:\t %s' % data_path)
|
||||
print("\ndata:\t %s" % data_path)
|
||||
|
||||
|
||||
def main(args): # noqa
|
||||
if not is_autojump_sourced() and not is_windows():
|
||||
print("Please source the correct autojump file in your shell's")
|
||||
print('startup file. For more information, please reinstall autojump')
|
||||
print('and read the post installation instructions.')
|
||||
print("startup file. For more information, please reinstall autojump")
|
||||
print("and read the post installation instructions.")
|
||||
return 1
|
||||
|
||||
config = set_defaults()
|
||||
@ -280,10 +217,7 @@ def main(args): # noqa
|
||||
if args.add:
|
||||
save(config, first(add_path(load(config), args.add)))
|
||||
elif args.complete:
|
||||
handle_tab_completion(
|
||||
needle=first(chain(sanitize(args.directory), [''])),
|
||||
entries=entriefy(load(config)),
|
||||
)
|
||||
handle_tab_completion(needle=first(chain(sanitize(args.directory), [""])), entries=entriefy(load(config)))
|
||||
elif args.decrease:
|
||||
data, entry = decrease_path(load(config), get_pwd(), args.decrease)
|
||||
save(config, data)
|
||||
@ -296,47 +230,48 @@ def main(args): # noqa
|
||||
old_data = load(config)
|
||||
new_data = dictify(purge_missing_paths(entriefy(old_data)))
|
||||
save(config, new_data)
|
||||
print('Purged %d entries.' % (len(old_data) - len(new_data)))
|
||||
print("Purged %d entries." % (len(old_data) - len(new_data)))
|
||||
elif args.stat:
|
||||
print_stats(load(config), config['data_path'])
|
||||
print_stats(load(config), config["data_path"])
|
||||
elif not args.directory:
|
||||
# Return best match.
|
||||
entries = entriefy(load(config))
|
||||
print_local(first(chain(
|
||||
imap(attrgetter('path'), find_matches(entries, [''])),
|
||||
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)
|
||||
tab_needle, tab_index, tab_path = \
|
||||
get_tab_entry_info(first(needles), TAB_SEPARATOR)
|
||||
tab_needle, tab_index, tab_path = get_tab_entry_info(first(needles), TAB_SEPARATOR)
|
||||
|
||||
# Handle `j foo__`, assuming first index.
|
||||
if not tab_path and not tab_index \
|
||||
and tab_needle and needles[0] == tab_needle + TAB_SEPARATOR:
|
||||
if not tab_path and not tab_index and tab_needle and needles[0] == tab_needle + TAB_SEPARATOR:
|
||||
tab_index = 1
|
||||
|
||||
if tab_path:
|
||||
print_local(tab_path)
|
||||
elif tab_index:
|
||||
get_ith_path = lambda i, iterable: last(take(i, iterable)).path
|
||||
print_local(
|
||||
get_ith_path(
|
||||
tab_index,
|
||||
find_matches(entries, [tab_needle]),
|
||||
),
|
||||
)
|
||||
print_local(get_ith_path(tab_index, find_matches(entries, [tab_needle])))
|
||||
else:
|
||||
print_local(first(chain(
|
||||
imap(attrgetter('path'), find_matches(entries, needles)),
|
||||
print_local(
|
||||
first(
|
||||
chain(
|
||||
imap(attrgetter("path"), find_matches(entries, needles)),
|
||||
# always return a path to calling shell functions
|
||||
['.'],
|
||||
)))
|
||||
["."],
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(parse_arguments()))
|
||||
|
@ -1,59 +1,59 @@
|
||||
export AUTOJUMP_SOURCED=1
|
||||
if [[ -z $AUTOJUMP_SOURCED ]]; then
|
||||
export AUTOJUMP_SOURCED=1
|
||||
|
||||
# set user installation paths
|
||||
if [[ -d ~/.autojump/ ]]; then
|
||||
export PATH=~/.autojump/bin:"${PATH}"
|
||||
fi
|
||||
# Script include
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# set user installation paths
|
||||
export PATH="${SCRIPT_DIR}:${PATH}"
|
||||
|
||||
|
||||
# set error file location
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
# set error file location
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
export AUTOJUMP_ERROR_PATH=~/Library/autojump/errors.log
|
||||
elif [[ -n "${XDG_DATA_HOME}" ]]; then
|
||||
elif [[ -n "${XDG_DATA_HOME}" ]]; then
|
||||
export AUTOJUMP_ERROR_PATH="${XDG_DATA_HOME}/autojump/errors.log"
|
||||
else
|
||||
else
|
||||
export AUTOJUMP_ERROR_PATH=~/.local/share/autojump/errors.log
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ! -d "$(dirname ${AUTOJUMP_ERROR_PATH})" ]]; then
|
||||
if [[ ! -d "$(dirname ${AUTOJUMP_ERROR_PATH})" ]]; then
|
||||
mkdir -p "$(dirname ${AUTOJUMP_ERROR_PATH})"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# enable tab completion
|
||||
_autojump() {
|
||||
# enable tab completion
|
||||
_autojump() {
|
||||
local cur
|
||||
cur=${COMP_WORDS[*]:1}
|
||||
comps=$(autojump --complete $cur)
|
||||
while read i; do
|
||||
echo "$comps" | while read i; do
|
||||
COMPREPLY=("${COMPREPLY[@]}" "${i}")
|
||||
done <<EOF
|
||||
$comps
|
||||
EOF
|
||||
}
|
||||
complete -F _autojump j
|
||||
done
|
||||
}
|
||||
complete -F _autojump j
|
||||
|
||||
|
||||
# change pwd hook
|
||||
autojump_add_to_database() {
|
||||
# change pwd hook
|
||||
autojump_add_to_database() {
|
||||
if [[ -f "${AUTOJUMP_ERROR_PATH}" ]]; then
|
||||
(autojump --add "$(pwd)" >/dev/null 2>>${AUTOJUMP_ERROR_PATH} &) &>/dev/null
|
||||
else
|
||||
(autojump --add "$(pwd)" >/dev/null &) &>/dev/null
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
case $PROMPT_COMMAND in
|
||||
case $PROMPT_COMMAND in
|
||||
*autojump*)
|
||||
;;
|
||||
*)
|
||||
PROMPT_COMMAND="${PROMPT_COMMAND:+$(echo "${PROMPT_COMMAND}" | awk '{gsub(/; *$/,"")}1') ; }autojump_add_to_database"
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
|
||||
|
||||
# default autojump command
|
||||
j() {
|
||||
# default autojump command
|
||||
j() {
|
||||
if [[ ${1} == -* ]] && [[ ${1} != "--" ]]; then
|
||||
autojump ${@}
|
||||
return
|
||||
@ -73,22 +73,22 @@ j() {
|
||||
echo "Try \`autojump --help\` for more information."
|
||||
false
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# jump to child directory (subdirectory of current path)
|
||||
jc() {
|
||||
# jump to child directory (subdirectory of current path)
|
||||
jc() {
|
||||
if [[ ${1} == -* ]] && [[ ${1} != "--" ]]; then
|
||||
autojump ${@}
|
||||
return
|
||||
else
|
||||
j $(pwd) ${@}
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# open autojump results in file browser
|
||||
jo() {
|
||||
# open autojump results in file browser
|
||||
jo() {
|
||||
if [[ ${1} == -* ]] && [[ ${1} != "--" ]]; then
|
||||
autojump ${@}
|
||||
return
|
||||
@ -116,15 +116,25 @@ jo() {
|
||||
echo "Try \`autojump --help\` for more information."
|
||||
false
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# open autojump results (child directory) in file browser
|
||||
jco() {
|
||||
# open autojump results (child directory) in file browser
|
||||
jco() {
|
||||
if [[ ${1} == -* ]] && [[ ${1} != "--" ]]; then
|
||||
autojump ${@}
|
||||
return
|
||||
else
|
||||
jo $(pwd) ${@}
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
# Jump around a git repo
|
||||
g() {
|
||||
REPO_ROOT=`git rev-parse --show-toplevel`
|
||||
j "$REPO_ROOT" "$@"
|
||||
}
|
||||
|
||||
else
|
||||
echo "ERROR: autojump was sourced twice"
|
||||
fi
|
||||
|
@ -3,6 +3,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from codecs import open
|
||||
@ -26,7 +27,7 @@ else:
|
||||
|
||||
|
||||
BACKUP_THRESHOLD = 24 * 60 * 60
|
||||
Entry = namedtuple('Entry', ['path', 'weight'])
|
||||
Entry = namedtuple("Entry", ["path", "weight"])
|
||||
|
||||
|
||||
def dictify(entries):
|
||||
@ -51,21 +52,16 @@ def entriefy(data):
|
||||
|
||||
def load(config):
|
||||
"""Returns a dictonary (key=path, value=weight) loaded from data file."""
|
||||
xdg_aj_home = os.path.join(
|
||||
os.path.expanduser('~'),
|
||||
'.local',
|
||||
'share',
|
||||
'autojump',
|
||||
)
|
||||
xdg_aj_home = os.path.join(os.path.expanduser("~"), ".local", "share", "autojump")
|
||||
|
||||
if is_osx() and os.path.exists(xdg_aj_home):
|
||||
migrate_osx_xdg_data(config)
|
||||
|
||||
if not os.path.exists(config['data_path']):
|
||||
if not os.path.exists(config["data_path"]):
|
||||
return {}
|
||||
|
||||
# example: u'10.0\t/home/user\n' -> ['10.0', u'/home/user']
|
||||
parse = lambda line: line.strip().split('\t')
|
||||
parse = lambda line: line.strip().split("\t")
|
||||
|
||||
correct_length = lambda x: len(x) == 2
|
||||
|
||||
@ -73,24 +69,15 @@ def load(config):
|
||||
tupleize = lambda x: (x[1], float(x[0]))
|
||||
|
||||
try:
|
||||
with open(
|
||||
config['data_path'],
|
||||
'r', encoding='utf-8',
|
||||
errors='replace',
|
||||
) as f:
|
||||
return dict(
|
||||
imap(
|
||||
tupleize,
|
||||
ifilter(correct_length, imap(parse, f)),
|
||||
),
|
||||
)
|
||||
with open(config["data_path"], "r", encoding="utf-8", errors="replace") as f:
|
||||
return dict(imap(tupleize, ifilter(correct_length, imap(parse, f))))
|
||||
except (IOError, EOFError):
|
||||
return load_backup(config)
|
||||
|
||||
|
||||
def load_backup(config):
|
||||
if os.path.exists(config['backup_path']):
|
||||
move_file(config['backup_path'], config['data_path'])
|
||||
if os.path.exists(config["backup_path"]):
|
||||
move_file(config["backup_path"], config["data_path"])
|
||||
return load(config)
|
||||
return {}
|
||||
|
||||
@ -100,17 +87,17 @@ def migrate_osx_xdg_data(config):
|
||||
Older versions incorrectly used Linux XDG_DATA_HOME paths on OS X. This
|
||||
migrates autojump files from ~/.local/share/autojump to ~/Library/autojump
|
||||
"""
|
||||
assert is_osx(), 'This function should only be run on OS X.'
|
||||
assert is_osx(), "This function should only be run on OS X."
|
||||
|
||||
xdg_data_home = os.path.join(os.path.expanduser('~'), '.local', 'share')
|
||||
xdg_aj_home = os.path.join(xdg_data_home, 'autojump')
|
||||
data_path = os.path.join(xdg_aj_home, 'autojump.txt')
|
||||
backup_path = os.path.join(xdg_aj_home, 'autojump.txt.bak')
|
||||
xdg_data_home = os.path.join(os.path.expanduser("~"), ".local", "share")
|
||||
xdg_aj_home = os.path.join(xdg_data_home, "autojump")
|
||||
data_path = os.path.join(xdg_aj_home, "autojump.txt")
|
||||
backup_path = os.path.join(xdg_aj_home, "autojump.txt.bak")
|
||||
|
||||
if os.path.exists(data_path):
|
||||
move_file(data_path, config['data_path'])
|
||||
move_file(data_path, config["data_path"])
|
||||
if os.path.exists(backup_path):
|
||||
move_file(backup_path, config['backup_path'])
|
||||
move_file(backup_path, config["backup_path"])
|
||||
|
||||
# cleanup
|
||||
shutil.rmtree(xdg_aj_home)
|
||||
@ -120,7 +107,7 @@ def migrate_osx_xdg_data(config):
|
||||
|
||||
def save(config, data):
|
||||
"""Save data and create backup, creating a new data file if necessary."""
|
||||
data_dir = os.path.dirname(config['data_path'])
|
||||
data_dir = os.path.dirname(config["data_path"])
|
||||
create_dir(data_dir)
|
||||
|
||||
# atomically save by writing to temporary file and moving to destination
|
||||
@ -129,20 +116,21 @@ def save(config, data):
|
||||
# Windows cannot reuse the same open file name
|
||||
temp.close()
|
||||
|
||||
with open(temp.name, 'w', encoding='utf-8', errors='replace') as f:
|
||||
with open(temp.name, "w", encoding="utf-8", errors="replace") as f:
|
||||
for path, weight in data.items():
|
||||
f.write(unico('%s\t%s\n' % (weight, path)))
|
||||
weight_with_age = weight * 0.999
|
||||
slash_only_path = re.sub(re.escape(os.sep), "/", path)
|
||||
f.write(unico("%s\t%s\n" % (weight_with_age, slash_only_path)))
|
||||
|
||||
f.flush()
|
||||
os.fsync(f)
|
||||
except IOError as ex:
|
||||
print('Error saving autojump data (disk full?)' % ex, file=sys.stderr)
|
||||
print("Error saving autojump data (disk full?)" % ex, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# move temp_file -> autojump.txt
|
||||
move_file(temp.name, config['data_path'])
|
||||
move_file(temp.name, config["data_path"])
|
||||
|
||||
# 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
|
||||
shutil.copy(config['data_path'], config['backup_path'])
|
||||
if not os.path.exists(config["backup_path"]) or (time() - os.path.getmtime(config["backup_path"]) > BACKUP_THRESHOLD): # noqa
|
||||
shutil.copy(config["data_path"], config["backup_path"])
|
||||
|
@ -3,11 +3,11 @@
|
||||
import os
|
||||
import re
|
||||
from difflib import SequenceMatcher
|
||||
from sys import stderr
|
||||
|
||||
from autojump_utils import is_python3
|
||||
from autojump_utils import last
|
||||
|
||||
|
||||
if is_python3(): # pragma: no cover
|
||||
ifilter = filter
|
||||
imap = map
|
||||
@ -36,13 +36,9 @@ def match_anywhere(needles, haystack, ignore_case=False):
|
||||
(path='/foo/baz', weight=10),
|
||||
]
|
||||
"""
|
||||
regex_needle = '.*' + '.*'.join(imap(re.escape, needles)) + '.*'
|
||||
regex_needle = ".*" + ".*".join(imap(re.escape, needles)) + ".*"
|
||||
regex_flags = re.IGNORECASE | re.UNICODE if ignore_case else re.UNICODE
|
||||
found = lambda haystack: re.search(
|
||||
regex_needle,
|
||||
haystack.path,
|
||||
flags=regex_flags,
|
||||
)
|
||||
found = lambda haystack: re.search(regex_needle, haystack.path, flags=regex_flags)
|
||||
return ifilter(found, haystack)
|
||||
|
||||
|
||||
@ -75,16 +71,21 @@ def match_consecutive(needles, haystack, ignore_case=False):
|
||||
(path='/foo/baz', weight=10),
|
||||
]
|
||||
"""
|
||||
regex_no_sep = '[^' + os.sep + ']*'
|
||||
regex_no_sep_end = regex_no_sep + '$'
|
||||
regex_one_sep = regex_no_sep + os.sep + regex_no_sep
|
||||
regex_needle = regex_one_sep.join(imap(re.escape, needles)) + regex_no_sep_end
|
||||
regex_needle = ""
|
||||
for needle in needles:
|
||||
slash_only_needle = re.sub(re.escape(os.sep), "/", needle)
|
||||
if regex_needle == "":
|
||||
regex_needle = slash_only_needle
|
||||
else:
|
||||
regex_needle += "[^/]*/.*" + slash_only_needle
|
||||
regex_needle += "[^/]*$"
|
||||
regex_flags = re.IGNORECASE | re.UNICODE if ignore_case else re.UNICODE
|
||||
found = lambda entry: re.search(
|
||||
regex_needle,
|
||||
entry.path,
|
||||
flags=regex_flags,
|
||||
)
|
||||
stderr.write("Regex: " + regex_needle + "\n")
|
||||
|
||||
def found(entry):
|
||||
slash_only_path = re.sub(re.escape(os.sep), "/", entry.path)
|
||||
return re.search(regex_needle, slash_only_path, flags=regex_flags)
|
||||
|
||||
return ifilter(found, haystack)
|
||||
|
||||
|
||||
@ -115,15 +116,9 @@ def match_fuzzy(needles, haystack, ignore_case=False, threshold=0.6):
|
||||
end_dir = lambda path: last(os.path.split(path))
|
||||
if ignore_case:
|
||||
needle = last(needles).lower()
|
||||
match_percent = lambda entry: SequenceMatcher(
|
||||
a=needle,
|
||||
b=end_dir(entry.path.lower()),
|
||||
).ratio()
|
||||
match_percent = lambda entry: SequenceMatcher(a=needle, b=end_dir(entry.path.lower())).ratio()
|
||||
else:
|
||||
needle = last(needles)
|
||||
match_percent = lambda entry: SequenceMatcher(
|
||||
a=needle,
|
||||
b=end_dir(entry.path),
|
||||
).ratio()
|
||||
match_percent = lambda entry: SequenceMatcher(a=needle, b=end_dir(entry.path)).ratio()
|
||||
meets_threshold = lambda entry: match_percent(entry) >= threshold
|
||||
return ifilter(meets_threshold, haystack)
|
||||
|
Loading…
Reference in New Issue
Block a user