1
0
mirror of https://github.com/wting/autojump synced 2024-10-27 20:34:07 +00:00

reformat doc strings, move config into own function, add global variable for testing purposes

This commit is contained in:
William Ting 2012-05-12 16:31:37 -10:00
parent 79e644bd63
commit 13e385a0ef

View File

@ -35,49 +35,78 @@ MAX_STORED_PATHS = 1000
COMPLETION_SEPARATOR = '__'
ARGS = None
# load config from environmental variables
if 'AUTOJUMP_DATA_DIR' in os.environ:
CONFIG_DIR = os.environ.get('AUTOJUMP_DATA_DIR')
else:
xdg_data_dir = os.environ.get('XDG_DATA_HOME') or os.path.join(os.environ['HOME'], '.local', 'share')
CONFIG_DIR = os.path.join(xdg_data_dir, 'autojump')
CONFIG_DIR = None
DB_FILE = None
TESTING = False
KEEP_ALL_ENTRIES = False
if 'AUTOJUMP_KEEP_ALL_ENTRIES' in os.environ and os.environ.get('AUTOJUMP_KEEP_ALL_ENTRIES') == '1':
KEEP_ALL_ENTRIES = True
IGNORE_CASE = False
ALWAYS_IGNORE_CASE = False
if 'AUTOJUMP_IGNORE_CASE' in os.environ and os.environ.get('AUTOJUMP_IGNORE_CASE') == '1':
ALWAYS_IGNORE_CASE = True
def config(testing=False):
global TESTING, CONFIG_DIR, KEEP_ALL_ENTRIES, DB_FILE
TESTING = testing
if CONFIG_DIR == os.path.expanduser('~'):
DB_FILE = CONFIG_DIR + '/.autojump.txt'
else:
DB_FILE = CONFIG_DIR + '/autojump.txt'
# load config from environmental variables
if 'AUTOJUMP_DATA_DIR' in os.environ:
CONFIG_DIR = os.environ.get('AUTOJUMP_DATA_DIR')
else:
xdg_data_dir = os.environ.get('XDG_DATA_HOME') or os.path.join(os.environ['HOME'], '.local', 'share')
CONFIG_DIR = os.path.join(xdg_data_dir, 'autojump')
if 'AUTOJUMP_KEEP_ALL_ENTRIES' in os.environ and os.environ.get('AUTOJUMP_KEEP_ALL_ENTRIES') == '1':
KEEP_ALL_ENTRIES = True
if 'AUTOJUMP_IGNORE_CASE' in os.environ and os.environ.get('AUTOJUMP_IGNORE_CASE') == '1':
ALWAYS_IGNORE_CASE = True
if CONFIG_DIR == os.path.expanduser('~'):
DB_FILE = CONFIG_DIR + '/.autojump.txt'
else:
DB_FILE = CONFIG_DIR + '/autojump.txt'
class Database:
""" Object for interfacing with autojump database. """
"""
Object for interfacing with autojump database.
"""
def __init__(self, filename):
self.filename = filename
self.data = {}
self.load()
def add(self, path, increment=1):
""" Increment existing paths or initialize new ones to 0. """
def __len__(self):
return len(self.data)
def add(self, path, increment = 10):
"""
Increment existing paths or initialize new ones to 0.
"""
if path not in self.data:
self.data[path] = 10
self.data[path] = increment
else:
import math
self.data[path] = math.sqrt((self.data[path]**2)+100)
self.data[path] = math.sqrt((self.data[path]**2)+(increment**2))
def decay(self):
""" Decay database entries. """
"""
Decay database entries.
"""
for k in self.data.keys():
self.data[k] *= 0.9
def get_weight(self, path):
"""
Return path weight.
"""
if path in self.data:
return self.data[path]
else:
return 0
def load(self, error_recovery = False):
""" Try to open the database file, recovering from backup if needed. """
"""
Try to open the database file, recovering from backup if needed.
"""
try:
with open(self.filename, 'r') as aj_file:
for line in aj_file.readlines():
@ -116,7 +145,9 @@ class Database:
return {} # if everything fails, return an empty dictionary
def maintenance(self):
""" Trims and decays database entries when exceeding settings. """
"""
Trims and decays database entries when exceeding settings.
"""
if sum(self.data.values()) > MAX_KEYWEIGHT:
self.decay()
if len(self.data) > MAX_STORED_PATHS:
@ -124,7 +155,9 @@ class Database:
self.save()
def purge(self):
""" Deletes all entries that no longer exist on system. """
"""
Deletes all entries that no longer exist on system.
"""
removed = []
for path in self.data.keys():
if not os.path.exists(path):
@ -134,7 +167,9 @@ class Database:
return removed
def save(self):
""" Save database atomically and preserve backup. """
"""
Save database atomically and preserve backup.
"""
# check file existence and permissions
if ((not os.path.exists(self.filename)) or
os.name == 'nt' or
@ -166,17 +201,21 @@ class Database:
print("Error while creating backup autojump file. (%s)" %
ex, file=sys.stderr)
def trim(self):
""" If database has exceeded MAX_STORED_PATHS, removes bottom 10%. """
def trim(self, percent=0.1):
"""
If database has exceeded MAX_STORED_PATHS, removes bottom 10%.
"""
dirs = list(self.data.items())
dirs.sort(key=itemgetter(1))
remove_cnt = .1 * MAX_STORED_PATHS
remove_cnt = int(percent * len(dirs))
for path, _ in dirs[:remove_cnt]:
del self.data[path]
def get_db_file(filename = "autojump.txt"):
""" Retrieve full database path. """
"""
Retrieve full database path.
"""
# TODO: Remove when migration code is removed.
if CONFIG_DIR == os.path.expanduser("~"):
return CONFIG_DIR + "/." + filename
@ -184,9 +223,9 @@ def get_db_file(filename = "autojump.txt"):
return CONFIG_DIR + "/" + filename
def options():
""" Parse command line options. """
global ARGS
"""
Parse command line options.
"""
parser = argparse.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='DIR', nargs='*', default='',
@ -235,7 +274,9 @@ def options():
return False
def decode(text, encoding=None, errors="strict"):
""" Decoding step for Python 2 which does not default to unicode. """
"""
Decoding step for Python 2 which does not default to unicode.
"""
if sys.version_info[0] > 2:
return text
else:
@ -244,8 +285,10 @@ def decode(text, encoding=None, errors="strict"):
return text.decode(encoding, errors)
def output(unicode_text, encoding=None):
""" Wrapper for the print function, using the filesystem encoding by default
to minimize encoding mismatch problems in directory names. """
"""
Wrapper for the print function, using the filesystem encoding by default
to minimize encoding mismatch problems in directory names.
"""
if sys.version_info[0] > 2:
print(unicode_text)
else:
@ -254,16 +297,20 @@ def output(unicode_text, encoding=None):
print(unicode_text.encode(encoding))
def unico(text):
""" If Python 2, convert to a unicode object. """
"""
If Python 2, convert to a unicode object.
"""
if sys.version_info[0] > 2:
return text
else:
return unicode(text)
def match_last(pattern):
""" If the last pattern contains a full path, jump there.
"""
If the last pattern contains a full path, jump there.
The regexp is because we need to support stuff like
"j wo jo__3__/home/joel/workspace/joel" for zsh. """
"j wo jo__3__/home/joel/workspace/joel" for zsh.
"""
last_pattern_path = re.sub("(.*)"+COMPLETION_SEPARATOR, "", pattern[-1])
if (len(last_pattern_path) > 0 and
last_pattern_path[0] == "/" and
@ -274,8 +321,10 @@ def match_last(pattern):
return False
def match(path, pattern, only_end=False, ignore_case=False):
""" Check whether a path matches a particular pattern, and return
the remaining part of the string. """
"""
Check whether a path matches a particular pattern, and return
the remaining part of the string.
"""
if only_end:
match_path = "/".join(path.split('/')[-1-pattern.count('/'):])
else:
@ -293,7 +342,9 @@ def match(path, pattern, only_end=False, ignore_case=False):
return (False, path[find_idx+len(pattern):])
def find_matches(db, patterns, max_matches=1, ignore_case=False, fuzzy=False):
""" Find max_matches paths that match the pattern, and add them to the result_list. """
"""
Find max_matches paths that match the pattern, and add them to the result_list.
"""
try:
current_dir = decode(os.path.realpath(os.curdir))
except OSError:
@ -314,7 +365,7 @@ def find_matches(db, patterns, max_matches=1, ignore_case=False, fuzzy=False):
end = d[0].split('/')[-1]
# collisions: ignore lower weight paths
if end not in end_dirs and os.path.exists(d[0]):
if end not in end_dirs and (os.path.exists(d[0]) or TESTING):
end_dirs[end] = d[0]
# find the first match (heighest weight)
@ -340,7 +391,7 @@ def find_matches(db, patterns, max_matches=1, ignore_case=False, fuzzy=False):
found, tmp = match(tmp, p, False, ignore_case)
if not found: break
if found and os.path.exists(path):
if found and (os.path.exists(path) or TESTING):
if path not in results:
results.append(path)
if len(results) >= max_matches:
@ -348,8 +399,14 @@ def find_matches(db, patterns, max_matches=1, ignore_case=False, fuzzy=False):
return results
def shell_utility():
""" Run this when autojump is called as a shell utility. """
"""
Run this when autojump is called as a shell utility.
"""
if options(): return True
config()
global ARGS, COMPLETION_SEPARATOR, DB_FILE, \
ALWAYS_IGNORE_CASE, KEEP_ALL_ENTRIES
db = Database(DB_FILE)
# if no directories, add empty string