def hg(): ext = [] if yesno('mercurial_keyring', 'Install mercurial keyring?'): # TODO: this things needs python-devel and openssl-devel - should we # provide a suggestion to install those on non-OSX OS's? pipinstall('mercurial_keyring', trypips=['pip2', 'pip3', 'pip']) ext.append('mercurial_keyring') if yesno('hg_strip_ext', 'Enable hg strip extension?'): ext.append('strip') # include our hg config from ~/.hgrc lineinfile('~/.hgrc', '%%include %s/hg/hgrc' % HERE, where=WHERE_TOP) # because we can't put the absolute path to our dotfiles hg/ignore file in # our hg/hgrc file, we have to put the config entry into the main ~/.hgrc # using a blockinfile() lines = [ '[ui]', 'ignore.dotfiles = {}/hg/ignore'.format(HERE), ] if ext: lines.append('[extensions]') for name in ext: lines.append('%s = ' % name) blockinfile('~/.hgrc', lines, WHERE_END)
def getpippaths(): if IS_OSX: return {} # do we need to out a pip config such that py2/py3 binaries don't clobber each other? question = 'Force pip to install into separate py2/py3 bin dirs?' if not yesno('force_pip_bin_paths', question, None): return {} scripts = {} for version in (2, 3): # TODO: we probably should drop into vim somewhere and make sure g:my_pyX_paths is # defined in prefs.vim or else our stuff is gonna be broken # TODO: we also want these in our $PATH ... or not? pip = "pip%d" % version var = "g:my_py%d_paths" % version if not haveexecutable(pip): continue stdout = execute([pip, '--version'], stdout=True)[1].decode('utf-8').rstrip() assert re.search(r' \(python \d+\.\d+\)$', stdout) version = stdout.rsplit(' ', 1)[1][:-1] path = '%s/.local/python-%s-bin' % (HOME, version) scripts[pip] = path lineinfile('~/.vimrc', "let %s = ['%s']" % (var, path), where=WHERE_END) return scripts
def zsh_config(): lineinfile('~/.zshrc', 'source $HOME/.shellrc', where=WHERE_TOP) install_completions('~/.zshrc') lineinfile('~/.zshrc', 'shell_init_done # this line must be last', where=WHERE_END) antigen = InstallFromSource('https://github.com/zsh-users/antigen.git', '~/src/antigen.git') antigen.select_tag('v2.2.3') run(antigen)
def jerjerrod_addline(command, path, ignore=[]): # track projects in ~/src mkdir('~/.config') mkdir('~/.config/jerjerrod') # some sensible defaults for how I like to do things assert command in ("PROJECT", "WORKSPACE", "FORGET") flags = [] flags += ["IGNORE={}".format(p) for p in ignore] lineinfile('~/.config/jerjerrod/jerjerrod.conf', "{} {} {}".format(command, path, " ".join(flags)).rstrip())
def git_completion(): # TODO: would be good to use git submodules for these so we get pinned/stable versions # install completion utilities for bash url = 'https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash' download(url, '~/src/git-completion.bash') lineinfile('~/.bashrc', 'source $HOME/src/git-completion.bash', where=WHERE_END) # install completion utilities for zsh url = 'https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.zsh' mkdir('~/.zsh') download(url, '~/.zsh/_git')
def shellrc(): # this is to prevent a problem where the U+26A1 lightning character would # take up 2 characters of display width in Alacritty>zsh on my MSFT M1 mac, # screwing up the LHS prompt when it was visible. lightning_ok = yesno( 'alacritty_unicode_lightning_width_issues', 'OK to use "⚡" in zsh prompt?', recommended=True, ) symbol = '⚡' if lightning_ok else 'e' lineinfile( '~/.shellrc', f'ZSH_THEME_GIT_CHANGED_SYMBOL="{symbol}"', where=WHERE_TOP, ) lineinfile('~/.shellrc', 'source {}/init.sh'.format(HERE), where=WHERE_END)
def pythonpath(): """ Add ~/dotfiles/python/ to our ~/.local/python[2/3]/site-packages dirs """ pypath = "%s/python" % HERE # places to look for site-packages globs = [ # centos / ubuntu '~/.local/lib/python*/site-packages', # OS X '~/Library/Python/*/lib/python/site-packages', ] # try each of the glob patterns and see if we find any matches matches = [] for pattern in globs: matches.extend(glob.glob(os.path.expanduser(pattern))) for m in matches: lineinfile(os.path.join(m, 'phodge-dotfiles.pth'), pypath) if not len(matches): raise Exception("Didn't add %s anywhere" % pypath)
def fzf_install(): if not yesno('install_fzf', 'Install fzf?', want_full): return if haveexecutable('brew') and allow_installing_stuff: installpkg('fzf') brewpath = execute(['brew', '--prefix'], stdout=True)[1].decode('utf-8').strip() if brewpath == '/opt/homebrew': # brew puts the fzf files into versioned folders, so all we can do # is glob and sort (which isn't perfect because it would need to be # a semver-compatible sort) and pick the first one fzf_path = execute( [ 'bash', '-c', f'echo {brewpath}/Cellar/fzf/* | sort -r | head -n 1' ], stdout=True, )[1].decode('utf-8').strip() else: # this is how it was on my old mac fzf_path = brewpath + '/opt/fzf' else: # do it the long way import os.path fzf_repo = os.path.expanduser('~/src/fzf.git') fzf_install = InstallFromSource('https://github.com/junegunn/fzf.git', fzf_repo) fzf_install.select_tag('0.17.3') fzf_install.compile_cmd([ ['./install', '--bin'], ]) fzf_install.symlink('bin/fzf', '~/bin/fzf') run(fzf_install) execute(['./install', '--bin'], cwd=fzf_repo, stdout='TTY') fzf_path = fzf_repo lineinfile('~/.bashrc', 'source {}/shell/completion.bash'.format(fzf_path)) lineinfile('~/.bashrc', 'source {}/shell/key-bindings.bash'.format(fzf_path)) if wantzsh(): lineinfile('~/.zshrc', 'source {}/shell/completion.zsh'.format(fzf_path)) lineinfile('~/.zshrc', 'source {}/shell/key-bindings.zsh'.format(fzf_path))
def vim_config(): # install vim-plug into ~/.vim mkdir('~/.vim') mkdir('~/.nvim') mkdir('~/.config') mkdir('~/.config/nvim') symlink('~/.vimrc', '~/.config/nvim/init.vim') mkdir('~/.vim/autoload') download( 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim', '~/.vim/autoload/plug.vim') def mkdir_r(path): assert len(path) if os.path.islink(path): raise Exception( "Cannot mkdir_r(%r): path already exists but is a symlink" % path) # if the thing already exists but isn't a dir, then we can't create it if os.path.exists(path) and not os.path.isdir(path): raise Exception( "Cannot mkdir_r(%r): path already exists but is not a dir" % path) # create the parent then our target path parent = os.path.dirname(path) if len(parent) > 5: mkdir_r(parent) mkdir(path) def _static(url, dest): dest = HOME + '/.vimstatic/' + dest mkdir_r(os.path.dirname(dest)) download(url, dest) vprefs = HOME + '/.vim/prefs.vim' nprefs = HOME + '/.nvim/prefs.vim' # chuck in a reference to our shiny new vimrc.vim (this will end up below the rtp magic block) lineinfile('~/.vimrc', 'source %s/vimrc.vim' % HERE, where=WHERE_TOP) # do we want a debugger plugin in vim? for varname, varval in get_vim_options().items(): lineinfile( '~/.vim/prefs.vim', f'let {varname} = {"1" if varval else "0"} " set by phodge\'s dotfiles' .format(varname, '1' if varval else '0'), where=WHERE_END, ) # put our magic &rtp block at the top of our vimrc blockinfile('~/.vimrc', [ ' " reset rtp', ' set runtimepath&', ' " let other scripts know they\'re allowed to modify &rtp', ' let g:allow_rtp_modify = 1', ' " grab local preferences', ' if filereadable(%r)' % vprefs, ' source %s' % vprefs, ' endif', ' if has(\'nvim\') && filereadable(%r)' % nprefs, ' source %s' % nprefs, ' endif', ], '" {{{ START OF dotfiles runtimepath magic', '" }}} END OF dotfiles runtimepath magic', where=WHERE_TOP) # if the .vimrc.preferences file doesn't exist, create it now if not os.path.exists(vprefs): with open(vprefs, 'w') as f: f.write('let g:vim_peter = 1\n') # make sure we've made a choice about clipboard option in vprefs file @whenmissing(vprefs, 'clipboard') def addclipboard(): if allowinteractive(): if yesno(None, 'Use system clipboard in vim? (clipboard=unnamed)', None): rem = "Use system clipboard" val = 'unnamed' else: rem = "Don't try and use system clipboard" val = '' with open(vprefs, 'a') as f: f.write('" %s\n' % rem) f.write("set clipboard=%s\n" % val) # put a default value about whether we want the hacky mappings for when the # terminal type isn't set correctly @whenmissing(vprefs, 'g:hackymappings') def sethackymappings(): with open(vprefs, 'a') as f: f.write('" Use hacky mappings for F-keys and keypad?\n') f.write('let g:hackymappings = 0\n') # in most cases we don't want insight_php_tests @whenmissing(vprefs, 'g:insight_php_tests') def setinsightphptests(): with open(vprefs, 'a') as f: f.write('" Do we want to use insight to check PHP code?\n') f.write('let g:insight_php_tests = []\n') # lock down &runtimepath lineinfile('~/.vimrc', 'let g:allow_rtp_modify = 0', where=WHERE_END) # if we have jerjerrod installed, add an ALWAYSFLAG entry for git repos in ~/src/plugedit if False and wantjerjerrod(): mkdir('~/.config') mkdir('~/.config/jerjerrod') lineinfile('~/.config/jerjerrod/jerjerrod.conf', 'PROJECT ~/src/plugedit/*.git ALWAYSFLAG') # icinga syntax/filetype if yesno('want_vim_icinga_stuff', 'Install vim icinga2 syntax/ftplugin?', default=False): files = ['syntax/icinga2.vim', 'ftdetect/icinga2.vim'] for name in files: url = 'https://raw.githubusercontent.com/Icinga/icinga2/master/tools/syntax/vim/{}' _static(url.format(name), name) # <est> utility hasphp = haveexecutable('php') if yesno('install_est_utility', 'Install <vim-est>?', hasphp): est = InstallFromSource('https://github.com/phodge/vim-est.git', '~/src/vim-est.git') est.select_branch('master') est.symlink('bin/est', '~/bin/est') run(est)
def install_completions(rcfile): lineinfile(rcfile, 'want_click_completion homely') if wantjerjerrod(): lineinfile(rcfile, 'want_click_completion jerjerrod')
def _bashrc(): lineinfile('~/.bashrc', 'source $HOME/.shellrc', where=WHERE_TOP) install_completions('~/.bashrc') lineinfile('~/.bashrc', 'shell_init_done # this line must be last', where=WHERE_END)