1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3from __future__ import print_function 4 5import os 6import platform 7import shutil 8import sys 9 10sys.path.append('bin') 11from autojump_argparse import ArgumentParser # noqa 12 13SUPPORTED_SHELLS = ('bash', 'zsh', 'fish', 'tcsh') 14 15 16def cp(src, dest, dryrun=False): 17 print('copying file: %s -> %s' % (src, dest)) 18 if not dryrun: 19 shutil.copy(src, dest) 20 21 22def get_shell(): 23 return os.path.basename(os.getenv('SHELL', '')) 24 25 26def mkdir(path, dryrun=False): 27 print('creating directory:', path) 28 if not dryrun and not os.path.exists(path): 29 os.makedirs(path) 30 31 32def modify_autojump_sh(etc_dir, share_dir, dryrun=False): 33 """Append custom installation path to autojump.sh""" 34 custom_install = '\ 35 \n# check custom install \ 36 \nif [ -s %s/autojump.${shell} ]; then \ 37 \n source %s/autojump.${shell} \ 38 \nfi\n' % (share_dir, share_dir) 39 40 with open(os.path.join(etc_dir, 'autojump.sh'), 'a') as f: 41 f.write(custom_install) 42 43 44def modify_autojump_lua(clink_dir, bin_dir, dryrun=False): 45 """Prepend custom AUTOJUMP_BIN_DIR definition to autojump.lua""" 46 custom_install = "local AUTOJUMP_BIN_DIR = \"%s\"\n" % bin_dir.replace( 47 '\\', 48 '\\\\', 49 ) 50 clink_file = os.path.join(clink_dir, 'autojump.lua') 51 with open(clink_file, 'r') as f: 52 original = f.read() 53 with open(clink_file, 'w') as f: 54 f.write(custom_install + original) 55 56 57def parse_arguments(): # noqa 58 if platform.system() == 'Windows': 59 default_user_destdir = os.path.join( 60 os.getenv('LOCALAPPDATA', ''), 61 'autojump', 62 ) 63 else: 64 default_user_destdir = os.path.join( 65 os.path.expanduser('~'), 66 '.autojump', 67 ) 68 default_user_prefix = '' 69 default_user_zshshare = 'functions' 70 default_system_destdir = '/' 71 default_system_prefix = '/usr/local' 72 default_system_zshshare = '/usr/share/zsh/site-functions' 73 default_clink_dir = os.path.join(os.getenv('LOCALAPPDATA', ''), 'clink') 74 75 parser = ArgumentParser( 76 description='Installs autojump globally for root users, otherwise \ 77 installs in current user\'s home directory.' 78 ) 79 parser.add_argument( 80 '-n', '--dryrun', action='store_true', default=False, 81 help='simulate installation', 82 ) 83 parser.add_argument( 84 '-f', '--force', action='store_true', default=False, 85 help='skip root user, shell type, Python version checks', 86 ) 87 parser.add_argument( 88 '-d', '--destdir', metavar='DIR', default=default_user_destdir, 89 help='set destination to DIR', 90 ) 91 parser.add_argument( 92 '-p', '--prefix', metavar='DIR', default=default_user_prefix, 93 help='set prefix to DIR', 94 ) 95 parser.add_argument( 96 '-z', '--zshshare', metavar='DIR', default=default_user_zshshare, 97 help='set zsh share destination to DIR', 98 ) 99 parser.add_argument( 100 '-c', '--clinkdir', metavar='DIR', default=default_clink_dir, 101 help='set clink directory location to DIR (Windows only)', 102 ) 103 parser.add_argument( 104 '-s', '--system', action='store_true', default=False, 105 help='install system wide for all users', 106 ) 107 108 args = parser.parse_args() 109 110 if not args.force: 111 if sys.version_info[0] == 2 and sys.version_info[1] < 6: 112 print('Python v2.6+ or v3.0+ required.', file=sys.stderr) 113 sys.exit(1) 114 if args.system: 115 if platform.system() == 'Windows': 116 print( 117 'System-wide installation is not supported on Windows.', 118 file=sys.stderr, 119 ) 120 sys.exit(1) 121 elif os.geteuid() != 0: 122 print( 123 'Please rerun as root for system-wide installation.', 124 file=sys.stderr, 125 ) 126 sys.exit(1) 127 128 if platform.system() != 'Windows' \ 129 and get_shell() not in SUPPORTED_SHELLS: 130 print( 131 'Unsupported shell: %s' % os.getenv('SHELL'), 132 file=sys.stderr, 133 ) 134 sys.exit(1) 135 136 if args.destdir != default_user_destdir \ 137 or args.prefix != default_user_prefix \ 138 or args.zshshare != default_user_zshshare: 139 args.custom_install = True 140 else: 141 args.custom_install = False 142 143 if args.system: 144 if args.custom_install: 145 print( 146 'Custom paths incompatible with --system option.', 147 file=sys.stderr, 148 ) 149 sys.exit(1) 150 151 args.destdir = default_system_destdir 152 args.prefix = default_system_prefix 153 args.zshshare = default_system_zshshare 154 155 return args 156 157 158def show_post_installation_message(etc_dir, share_dir, bin_dir): 159 if platform.system() == 'Windows': 160 print('\nPlease manually add %s to your user path' % bin_dir) 161 else: 162 if get_shell() == 'fish': 163 aj_shell = '%s/autojump.fish' % share_dir 164 source_msg = 'if test -f %s; . %s; end' % (aj_shell, aj_shell) 165 rcfile = '~/.config/fish/config.fish' 166 else: 167 aj_shell = '%s/autojump.sh' % etc_dir 168 source_msg = '[[ -s %s ]] && source %s' % (aj_shell, aj_shell) 169 170 if platform.system() == 'Darwin' and get_shell() == 'bash': 171 rcfile = '~/.profile' 172 else: 173 rcfile = '~/.%src' % get_shell() 174 175 print('\nPlease manually add the following line(s) to %s:' % rcfile) 176 print('\n\t' + source_msg) 177 if get_shell() == 'zsh': 178 print('\n\tautoload -U compinit && compinit -u') 179 180 print('\nPlease restart terminal(s) before running autojump.\n') 181 182 183def main(args): 184 if args.dryrun: 185 print('Installing autojump to %s (DRYRUN)...' % args.destdir) 186 else: 187 print('Installing autojump to %s ...' % args.destdir) 188 189 bin_dir = os.path.join(args.destdir, args.prefix, 'bin') 190 etc_dir = os.path.join(args.destdir, 'etc', 'profile.d') 191 doc_dir = os.path.join(args.destdir, args.prefix, 'share', 'man', 'man1') 192 share_dir = os.path.join(args.destdir, args.prefix, 'share', 'autojump') 193 zshshare_dir = os.path.join(args.destdir, args.zshshare) 194 195 mkdir(bin_dir, args.dryrun) 196 mkdir(doc_dir, args.dryrun) 197 mkdir(etc_dir, args.dryrun) 198 mkdir(share_dir, args.dryrun) 199 200 cp('./bin/autojump', bin_dir, args.dryrun) 201 cp('./bin/autojump_argparse.py', bin_dir, args.dryrun) 202 cp('./bin/autojump_data.py', bin_dir, args.dryrun) 203 cp('./bin/autojump_match.py', bin_dir, args.dryrun) 204 cp('./bin/autojump_utils.py', bin_dir, args.dryrun) 205 cp('./bin/icon.png', share_dir, args.dryrun) 206 cp('./docs/autojump.1', doc_dir, args.dryrun) 207 208 if platform.system() == 'Windows': 209 cp('./bin/autojump.lua', args.clinkdir, args.dryrun) 210 cp('./bin/autojump.bat', bin_dir, args.dryrun) 211 cp('./bin/j.bat', bin_dir, args.dryrun) 212 cp('./bin/jc.bat', bin_dir, args.dryrun) 213 cp('./bin/jo.bat', bin_dir, args.dryrun) 214 cp('./bin/jco.bat', bin_dir, args.dryrun) 215 216 if args.custom_install: 217 modify_autojump_lua(args.clinkdir, bin_dir, args.dryrun) 218 else: 219 mkdir(etc_dir, args.dryrun) 220 mkdir(share_dir, args.dryrun) 221 mkdir(zshshare_dir, args.dryrun) 222 223 cp('./bin/autojump.sh', etc_dir, args.dryrun) 224 cp('./bin/autojump.bash', share_dir, args.dryrun) 225 cp('./bin/autojump.fish', share_dir, args.dryrun) 226 cp('./bin/autojump.zsh', share_dir, args.dryrun) 227 cp('./bin/_j', zshshare_dir, args.dryrun) 228 229 if args.custom_install: 230 modify_autojump_sh(etc_dir, share_dir, args.dryrun) 231 232 show_post_installation_message(etc_dir, share_dir, bin_dir) 233 234 235if __name__ == '__main__': 236 sys.exit(main(parse_arguments())) 237