diff --git a/.bash_profile b/.bash_profile new file mode 100644 index 0000000..58ab2ce --- /dev/null +++ b/.bash_profile @@ -0,0 +1,29 @@ + +# If not running interactively, don't do anything +[ -z "$PS1" ] && return + +#PATH=$PATH:$HOME/bin:/opt/local/bin:/opt/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin: + +# colors +export CLICOLOR=1 +export LSCOLORS=dxfxcxbxegedabagacad + +# history +export HISTCONTROL=erasedups +export HISTFILESIZE=10000 +export HISTSIZE=10000 +shopt -s histappend + +# prompt +export PS1="\[\033[36m\]\u\[\033[m\]@\[\033[32m\]\h:\[\033[33;1m\]\w\[\033[m\]\$ " +export CLICOLOR=1 +export LSCOLORS=ExFxBxDxCxegedabagacad + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# make less more friendly for non-text input files, see lesspipe(1) +[ -x /usr/bin/lesspipe ] && eval "$(lesspipe)" + +[[ -f "$HOME/.dotfiles/.commonrc" ]] && source "$HOME/.dotfiles/.commonrc" diff --git a/.commonrc b/.commonrc new file mode 100755 index 0000000..127653a --- /dev/null +++ b/.commonrc @@ -0,0 +1,2 @@ + +[[ -f "$HOME/.dotfiles/aliases" ]] && source "$HOME/.dotfiles/aliases" diff --git a/.dfminstall b/.dfminstall index 6454cf7..6443aa2 100644 --- a/.dfminstall +++ b/.dfminstall @@ -1 +1,6 @@ +bin recurse +bin/dfm chmod 0755 + README.md skip +aliases skip +tmux.start.sh skip diff --git a/.screenrc b/.screenrc new file mode 100644 index 0000000..c71992e --- /dev/null +++ b/.screenrc @@ -0,0 +1,6 @@ +hardstatus off +hardstatus alwayslastline +hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W} %c %{g}]' +defscrollback 100000 +termcapinfo xterm* ti@:te@ +startup_message off diff --git a/.shellrc.load b/.shellrc.load new file mode 100644 index 0000000..0acf1f6 --- /dev/null +++ b/.shellrc.load @@ -0,0 +1,9 @@ +# include what you want + +export PATH=$PATH:$HOME/bin + +# add this to the .bashrc or .zshrc (done automatically by dfm): +# . $HOME/.shellrc.load + +#### +# put any bash/zsh customizations in here \ No newline at end of file diff --git a/.tmux.conf b/.tmux.conf new file mode 100644 index 0000000..3cf2602 --- /dev/null +++ b/.tmux.conf @@ -0,0 +1,147 @@ +###################### +### DESIGN CHANGES ### +###################### + +# panes +set -g pane-border-fg black +set -g pane-active-border-fg brightred + +## Status bar design +# status line +set -g status-utf8 on +set -g status-justify left +set -g status-bg default +set -g status-fg colour12 +set -g status-interval 2 + +# messaging +set -g message-fg black +set -g message-bg yellow +set -g message-command-fg blue +set -g message-command-bg black + +#window mode +setw -g mode-bg colour6 +setw -g mode-fg colour0 + +# window status +setw -g window-status-format " #F#I:#W#F " +setw -g window-status-current-format " #F#I:#W#F " +setw -g window-status-format "#[fg=magenta]#[bg=black] #I #[bg=cyan]#[fg=colour8] #W " +setw -g window-status-current-format "#[bg=brightmagenta]#[fg=colour8] #I #[fg=colour8]#[bg=colour14] #W " +setw -g window-status-current-bg colour0 +setw -g window-status-current-fg colour11 +setw -g window-status-current-attr dim +setw -g window-status-bg green +setw -g window-status-fg black +setw -g window-status-attr reverse + +# Info on left (I don't have a session display for now) +set -g status-left '' + +# loud or quiet? +set-option -g visual-activity off +set-option -g visual-bell off +set-option -g visual-silence off +set-window-option -g monitor-activity off +set-option -g bell-action none + +set -g default-terminal "screen-256color" + +# The modes { +setw -g clock-mode-colour colour135 +setw -g mode-attr bold +setw -g mode-fg colour196 +setw -g mode-bg colour238 + +# } +# The panes { + +set -g pane-border-bg colour235 +set -g pane-border-fg colour238 +set -g pane-active-border-bg colour236 +set -g pane-active-border-fg colour51 + +# } +# The statusbar { + +set -g status-position bottom +set -g status-bg colour234 +set -g status-fg colour137 +set -g status-attr dim +set -g status-left '' +set -g status-right '#[fg=colour233,bg=colour241,bold] %d/%m #[fg=colour233,bg=colour245,bold] %H:%M:%S ' +set -g status-right-length 50 +set -g status-left-length 20 + +setw -g window-status-current-fg colour81 +setw -g window-status-current-bg colour238 +setw -g window-status-current-attr bold +setw -g window-status-current-format ' #I#[fg=colour250]:#[fg=colour255]#W#[fg=colour50]#F ' + +setw -g window-status-fg colour138 +setw -g window-status-bg colour235 +setw -g window-status-attr none +setw -g window-status-format ' #I#[fg=colour237]:#[fg=colour250]#W#[fg=colour244]#F ' + +setw -g window-status-bell-attr bold +setw -g window-status-bell-fg colour255 +setw -g window-status-bell-bg colour1 + +# } +# The messages { + +set -g message-attr bold +set -g message-fg colour232 +set -g message-bg colour166 + +# } + +#################################################### +### Settings MF +#################################################### + +set -g default-terminal "xterm" + +set -g mode-mouse on +set -g mouse-select-pane on +set -g mouse-resize-pane +set -g mouse-select-window on + +set-option -g detach-on-destroy off + +# Scroll History +#set -g history-limit 30000 + +# Set ability to capture on start and restore on exit window data when running an application +setw -g alternate-screen on + +# Lower escape timing from 500ms to 50ms for quicker response to scroll-buffer access. +set -s escape-time 50 + +# Use vim keybindings in copy mode +setw -g mode-keys vi + +# Setup 'v' to begin selection as in Vim +bind-key -t vi-copy v begin-selection +bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy" + +# Update default binding of `Enter` to also use copy-pipe +unbind -t vi-copy Enter +bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy" + +# split panes using | and - +bind | split-window -h +bind - split-window -v +unbind '"' +unbind % + +# Start windows and panes at 1, not 0 +set -g base-index 1 +setw -g pane-base-index 1 + +# reload config file (change file location to your the tmux.conf you want to use) +bind r source-file ~/.tmux.conf + +#set-option -g status-right '#[fg=white,nobright][ #[fg=black,bright]#(uptime | rev | cut -d":" -f1 | rev | sed s/,//g )#[fg=white,nobright] ]' + diff --git a/.vim/.netrwhist b/.vim/.netrwhist new file mode 100644 index 0000000..f260cf9 --- /dev/null +++ b/.vim/.netrwhist @@ -0,0 +1,6 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhist_cnt =4 +let g:netrw_dirhist_1='/data/etc/nginx/sites-enabled' +let g:netrw_dirhist_2='/data/www/die-erben-ashans.de/html/map_' +let g:netrw_dirhist_3='/root/.ssh' +let g:netrw_dirhist_4='/data/www/die-erben-ashans.de/html/wcf/lib/data/user/usermap' diff --git a/.vim/colors/hybrid-light.vim b/.vim/colors/hybrid-light.vim new file mode 100644 index 0000000..9151a92 --- /dev/null +++ b/.vim/colors/hybrid-light.vim @@ -0,0 +1,328 @@ +" File: hybrid-light.vim +" Maintainer: Andrew Wong (w0ng) +" URL: https://github.com/w0ng/vim-hybrid +" Modified: 27 Jan 2013 06:05 AM AEST +" License: MIT + +" Description:"{{{ +" ---------------------------------------------------------------------------- +" A clone of Solarized light with a custom colour palette. Currently a WIP. + +"}}} +" Initialisation:"{{{ +" ---------------------------------------------------------------------------- +if !has("gui_running") && &t_Co < 256 + finish +endif + +set background=light +hi clear + +if exists("syntax_on") + syntax reset +endif + +let colors_name = "hybrid-light" + +"}}} +" GUI And Cterm Palettes:"{{{ +" ---------------------------------------------------------------------------- +if has("gui_running") + let s:vmode = "gui" + let s:background = "#e4e4e4" + let s:foreground = "#000000" + let s:selection = "#bcbcbc" + let s:line = "#d0d0d0" + let s:comment = "#5f5f5f" + let s:red = "#5f0000" + let s:orange = "#875f00" + let s:yellow = "#5f5f00" + let s:green = "#005f00" + let s:aqua = "#005f5f" + let s:blue = "#00005f" + let s:purple = "#5f005f" + let s:window = "#9e9e9e" + let s:darkcolumn = "#808080" + let s:addbg = "#d7ffd7" + let s:changebg = "#d7d7ff" + let s:delbg = "#ffd7d7" +else + let s:vmode = "cterm" + let s:background = "254" + let s:foreground = "16" + let s:selection = "250" + let s:line = "252" + let s:comment = "59" + let s:red = "52" + let s:orange = "94" + let s:yellow = "58" + let s:green = "22" + let s:aqua = "23" + let s:blue = "17" + let s:purple = "53" + let s:window = "247" + let s:darkcolumn = "244" + let s:addbg = "194" + let s:changebg = "189" + let s:delbg = "224" +endif + +"}}} +" Formatting Options:"{{{ +" ---------------------------------------------------------------------------- +let s:none = "NONE" +let s:t_none = "NONE" +let s:n = "NONE" +let s:c = ",undercurl" +let s:r = ",reverse" +let s:s = ",standout" +let s:b = ",bold" +let s:u = ",underline" +let s:i = ",italic" + +"}}} +" Highlighting Primitives:"{{{ +" ---------------------------------------------------------------------------- +exe "let s:bg_none = ' ".s:vmode."bg=".s:none ."'" +exe "let s:bg_foreground = ' ".s:vmode."bg=".s:foreground."'" +exe "let s:bg_background = ' ".s:vmode."bg=".s:background."'" +exe "let s:bg_selection = ' ".s:vmode."bg=".s:selection ."'" +exe "let s:bg_line = ' ".s:vmode."bg=".s:line ."'" +exe "let s:bg_comment = ' ".s:vmode."bg=".s:comment ."'" +exe "let s:bg_red = ' ".s:vmode."bg=".s:red ."'" +exe "let s:bg_orange = ' ".s:vmode."bg=".s:orange ."'" +exe "let s:bg_yellow = ' ".s:vmode."bg=".s:yellow ."'" +exe "let s:bg_green = ' ".s:vmode."bg=".s:green ."'" +exe "let s:bg_aqua = ' ".s:vmode."bg=".s:aqua ."'" +exe "let s:bg_blue = ' ".s:vmode."bg=".s:blue ."'" +exe "let s:bg_purple = ' ".s:vmode."bg=".s:purple ."'" +exe "let s:bg_window = ' ".s:vmode."bg=".s:window ."'" +exe "let s:bg_darkcolumn = ' ".s:vmode."bg=".s:darkcolumn."'" +exe "let s:bg_addbg = ' ".s:vmode."bg=".s:addbg ."'" +exe "let s:bg_changebg = ' ".s:vmode."bg=".s:changebg ."'" +exe "let s:bg_delbg = ' ".s:vmode."bg=".s:delbg ."'" + +exe "let s:fg_none = ' ".s:vmode."fg=".s:none ."'" +exe "let s:fg_foreground = ' ".s:vmode."fg=".s:foreground."'" +exe "let s:fg_background = ' ".s:vmode."fg=".s:background."'" +exe "let s:fg_selection = ' ".s:vmode."fg=".s:selection ."'" +exe "let s:fg_line = ' ".s:vmode."fg=".s:line ."'" +exe "let s:fg_comment = ' ".s:vmode."fg=".s:comment ."'" +exe "let s:fg_red = ' ".s:vmode."fg=".s:red ."'" +exe "let s:fg_orange = ' ".s:vmode."fg=".s:orange ."'" +exe "let s:fg_yellow = ' ".s:vmode."fg=".s:yellow ."'" +exe "let s:fg_green = ' ".s:vmode."fg=".s:green ."'" +exe "let s:fg_aqua = ' ".s:vmode."fg=".s:aqua ."'" +exe "let s:fg_blue = ' ".s:vmode."fg=".s:blue ."'" +exe "let s:fg_purple = ' ".s:vmode."fg=".s:purple ."'" +exe "let s:fg_window = ' ".s:vmode."fg=".s:window ."'" +exe "let s:fg_darkcolumn = ' ".s:vmode."fg=".s:darkcolumn."'" +exe "let s:fg_addbg = ' ".s:vmode."fg=".s:addbg ."'" +exe "let s:fg_changebg = ' ".s:vmode."fg=".s:changebg ."'" +exe "let s:fg_delbg = ' ".s:vmode."fg=".s:delbg ."'" + +exe "let s:fmt_none = ' ".s:vmode."=NONE". " term=NONE" ."'" +exe "let s:fmt_bold = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b ."'" +exe "let s:fmt_bldi = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b ."'" +exe "let s:fmt_undr = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u ."'" +exe "let s:fmt_undb = ' ".s:vmode."=NONE".s:u.s:b. " term=NONE".s:u.s:b."'" +exe "let s:fmt_undi = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u ."'" +exe "let s:fmt_curl = ' ".s:vmode."=NONE".s:c. " term=NONE".s:c ."'" +exe "let s:fmt_ital = ' ".s:vmode."=NONE".s:i. " term=NONE".s:i ."'" +exe "let s:fmt_stnd = ' ".s:vmode."=NONE".s:s. " term=NONE".s:s ."'" +exe "let s:fmt_revr = ' ".s:vmode."=NONE".s:r. " term=NONE".s:r ."'" +exe "let s:fmt_revb = ' ".s:vmode."=NONE".s:r.s:b. " term=NONE".s:r.s:b."'" + +if has("gui_running") + exe "let s:sp_none = ' guisp=".s:none ."'" + exe "let s:sp_foreground = ' guisp=".s:foreground."'" + exe "let s:sp_background = ' guisp=".s:background."'" + exe "let s:sp_selection = ' guisp=".s:selection ."'" + exe "let s:sp_line = ' guisp=".s:line ."'" + exe "let s:sp_comment = ' guisp=".s:comment ."'" + exe "let s:sp_red = ' guisp=".s:red ."'" + exe "let s:sp_orange = ' guisp=".s:orange ."'" + exe "let s:sp_yellow = ' guisp=".s:yellow ."'" + exe "let s:sp_green = ' guisp=".s:green ."'" + exe "let s:sp_aqua = ' guisp=".s:aqua ."'" + exe "let s:sp_blue = ' guisp=".s:blue ."'" + exe "let s:sp_purple = ' guisp=".s:purple ."'" + exe "let s:sp_window = ' guisp=".s:window ."'" + exe "let s:sp_addbg = ' guisp=".s:addbg ."'" + exe "let s:sp_changebg = ' guisp=".s:changebg ."'" + exe "let s:sp_delbg = ' guisp=".s:delbg ."'" +else + let s:sp_none = "" + let s:sp_foreground = "" + let s:sp_background = "" + let s:sp_selection = "" + let s:sp_line = "" + let s:sp_comment = "" + let s:sp_red = "" + let s:sp_orange = "" + let s:sp_yellow = "" + let s:sp_green = "" + let s:sp_aqua = "" + let s:sp_blue = "" + let s:sp_purple = "" + let s:sp_window = "" + let s:sp_addbg = "" + let s:sp_changebg = "" + let s:sp_delbg = "" +endif + +"}}} +" Vim Highlighting: (see :help highlight-groups)"{{{ +" ---------------------------------------------------------------------------- +exe "hi! ColorColumn" .s:fg_none .s:bg_line .s:fmt_none +" Conceal" +" Cursor" +" CursorIM" +exe "hi! CursorColumn" .s:fg_none .s:bg_line .s:fmt_none +exe "hi! CursorLine" .s:fg_none .s:bg_line .s:fmt_none +exe "hi! Directory" .s:fg_blue .s:bg_none .s:fmt_none +exe "hi! DiffAdd" .s:fg_green .s:bg_addbg .s:fmt_none +exe "hi! DiffChange" .s:fg_purple .s:bg_changebg .s:fmt_none +exe "hi! DiffDelete" .s:fg_red .s:bg_delbg .s:fmt_none +exe "hi! DiffText" .s:fg_background .s:bg_purple .s:fmt_none +exe "hi! ErrorMsg" .s:fg_background .s:bg_red .s:fmt_stnd +exe "hi! VertSplit" .s:fg_window .s:bg_none .s:fmt_none +exe "hi! Folded" .s:fg_background .s:bg_darkcolumn .s:fmt_none +exe "hi! FoldColumn" .s:fg_none .s:bg_darkcolumn .s:fmt_none +exe "hi! SignColumn" .s:fg_none .s:bg_darkcolumn .s:fmt_none +" Incsearch" +exe "hi! LineNr" .s:fg_comment .s:bg_line .s:fmt_none +exe "hi! CursorLineNr" .s:fg_orange .s:bg_none .s:fmt_bold +exe "hi! MatchParen" .s:fg_background .s:bg_aqua .s:fmt_none +exe "hi! ModeMsg" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! MoreMsg" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! NonText" .s:fg_selection .s:bg_none .s:fmt_none +exe "hi! Normal" .s:fg_foreground .s:bg_background .s:fmt_none +exe "hi! Pmenu" .s:fg_foreground .s:bg_selection .s:fmt_none +exe "hi! PmenuSel" .s:fg_foreground .s:bg_selection .s:fmt_revr +" PmenuSbar" +" PmenuThumb" +exe "hi! Question" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! Search" .s:fg_background .s:bg_yellow .s:fmt_none +exe "hi! SpecialKey" .s:fg_selection .s:bg_none .s:fmt_none +exe "hi! SpellBad" .s:fg_red .s:bg_none .s:fmt_undr +exe "hi! SpellCap" .s:fg_blue .s:bg_none .s:fmt_undr +exe "hi! SpellLocal" .s:fg_aqua .s:bg_none .s:fmt_undr +exe "hi! SpellRare" .s:fg_purple .s:bg_none .s:fmt_undr +exe "hi! StatusLine" .s:fg_comment .s:bg_background .s:fmt_revr +exe "hi! StatusLineNC" .s:fg_window .s:bg_foreground .s:fmt_revr +exe "hi! TabLine" .s:fg_foreground .s:bg_darkcolumn .s:fmt_revr +" TabLineFill" +" TabLineSel" +exe "hi! Title" .s:fg_yellow .s:bg_none .s:fmt_none +exe "hi! Visual" .s:fg_none .s:bg_selection .s:fmt_none +" VisualNos" +exe "hi! WarningMsg" .s:fg_red .s:bg_none .s:fmt_none +" WildMenu" + +"}}} +" Generic Syntax Highlighting: (see :help group-name)"{{{ +" ---------------------------------------------------------------------------- +exe "hi! Comment" .s:fg_comment .s:bg_none .s:fmt_none + +exe "hi! Constant" .s:fg_aqua .s:bg_none .s:fmt_none +"exe "hi! String" .s:fg_green .s:bg_none .s:fmt_none +" Character" +" Number" +" Boolean" +" Float" + +exe "hi! Identifier" .s:fg_blue .s:bg_none .s:fmt_none +"exe "hi! Function" .s:fg_yellow .s:bg_none .s:fmt_none + +exe "hi! Statement" .s:fg_green .s:bg_none .s:fmt_none +" Conditional" +" Repeat" +" Label" +"exe "hi! Operator" .s:fg_foreground .s:bg_none .s:fmt_none +" Keyword" +" Exception" + +exe "hi! PreProc" .s:fg_orange .s:bg_none .s:fmt_none +" Include" +" Define" +" Macro" +" PreCondit" + +exe "hi! Type" .s:fg_yellow .s:bg_none .s:fmt_none +" StorageClass" +"exe "hi! Structure" .s:fg_aqua .s:bg_none .s:fmt_none +" Typedef" + +exe "hi! Special" .s:fg_red .s:bg_none .s:fmt_none +" SpecialChar" +" Tag" +" Delimiter" +" SpecialComment" +" Debug" +" +exe "hi! Underlined" .s:fg_purple .s:bg_none .s:fmt_none + +exe "hi! Ignore" .s:fg_none .s:bg_none .s:fmt_none + +exe "hi! Error" .s:fg_red .s:bg_none .s:fmt_undr + +exe "hi! Todo" .s:fg_comment .s:bg_addbg .s:fmt_none + +" Quickfix window +exe "hi! qfLineNr" .s:fg_yellow .s:bg_none .s:fmt_none +" qfFileName" +" qfLineNr" +" qfError" + +"}}} +" Diff Syntax Highlighting:"{{{ +" ---------------------------------------------------------------------------- +" Diff +" diffOldFile +" diffNewFile +" diffFile +" diffOnly +" diffIdentical +" diffDiffer +" diffBDiffer +" diffIsA +" diffNoEOL +" diffCommon +hi! link diffRemoved Special +" diffChanged +hi! link diffAdded Statement +" diffLine +" diffSubname +" diffComment + +"}}} +" Legal:"{{{ +" ---------------------------------------------------------------------------- +" Copyright (c) 2011 Ethan Schoonover +" Copyright (c) 2013 w0ng +" +" Permission is hereby granted, free of charge, to any per‐ +" son obtaining a copy of this software and associated doc‐ +" umentation files (the “Software”), to deal in the Soft‐ +" ware without restriction, including without limitation +" the rights to use, copy, modify, merge, publish, distrib‐ +" ute, sublicense, and/or sell copies of the Software, and +" to permit persons to whom the Software is furnished to do +" so, subject to the following conditions: +" +" The above copyright notice and this permission notice +" shall be included in all copies or substantial portions +" of the Software. +" +" THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY +" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +" THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICU‐ +" LAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CON‐ +" TRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON‐ +" NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +" THE SOFTWARE. + +" }}} diff --git a/.vim/colors/hybrid.vim b/.vim/colors/hybrid.vim new file mode 100644 index 0000000..a55800a --- /dev/null +++ b/.vim/colors/hybrid.vim @@ -0,0 +1,448 @@ +" File: hybrid.vim +" Maintainer: Andrew Wong (w0ng) +" URL: https://github.com/w0ng/vim-hybrid +" Modified: 27 Jan 2013 07:33 AM AEST +" License: MIT + +" Description:"{{{ +" ---------------------------------------------------------------------------- +" The RGB colour palette is taken from Tomorrow-Night.vim: +" https://github.com/chriskempson/vim-tomorrow-theme +" +" The syntax highlighting scheme is taken from jellybeans.vim: +" https://github.com/nanotech/jellybeans.vim +" +" The code taken from solarized.vim +" https://github.com/altercation/vim-colors-solarized + +"}}} +" Requirements And Recommendations:"{{{ +" ---------------------------------------------------------------------------- +" This colourscheme is intended for use on: +" - gVim 7.3 for Linux, Mac and Windows. +" - Vim 7.3 for Linux, using a 256 colour enabled terminal. +" +" By default, Vim will use the closest matching cterm equivalent of the RGB +" colours. +" +" However, Due to the limited 256 palette, colours in Vim and gVim will still +" be noticeably different. In order to get a uniform appearance and the way +" that this colourscheme was intended, it is HIGHLY recommended that you: +" +" 1. Add these colours to ~/.Xresources: +" +" https://gist.github.com/3278077 +" +" 2. Use Xresources colours by setting in ~/.vimrc: +" +" let g:hybrid_use_Xresources = 1 +" colorscheme hybrid +" +" For iTerm2 users: +" 1. Install this color preset on your iTerm2: +" +" https://gist.github.com/luan/6362811 +" +" 2. Use iTerm colours by setting in ~/.vimrc: +" +" let g:hybrid_use_iTerm_colors = 1 +" colorscheme hybrid +" + +"}}} +" Initialisation:"{{{ +" ---------------------------------------------------------------------------- +if !has("gui_running") && &t_Co < 256 + finish +endif + +if !exists("g:hybrid_use_Xresources") + let g:hybrid_use_Xresources = 0 +endif + +if !exists("g:hybrid_use_iTerm_colors") + let g:hybrid_use_iTerm_colors = 0 +endif + +set background=dark +hi clear + +if exists("syntax_on") + syntax reset +endif + +let colors_name = "hybrid" + +"}}} +" GUI And Cterm Palettes:"{{{ +" ---------------------------------------------------------------------------- +if has("gui_running") + let s:vmode = "gui" + let s:background = "#1d1f21" + let s:foreground = "#c5c8c6" + let s:selection = "#373b41" + let s:line = "#282a2e" + let s:comment = "#707880" + let s:red = "#cc6666" + let s:orange = "#de935f" + let s:yellow = "#f0c674" + let s:green = "#b5bd68" + let s:aqua = "#8abeb7" + let s:blue = "#81a2be" + let s:purple = "#b294bb" + let s:window = "#303030" + let s:darkcolumn = "#1c1c1c" + let s:addbg = "#5F875F" + let s:addfg = "#d7ffaf" + let s:changebg = "#5F5F87" + let s:changefg = "#d7d7ff" + let s:darkblue = "#00005f" + let s:darkcyan = "#005f5f" + let s:darkred = "#5f0000" + let s:darkpurple = "#5f005f" +else + let s:vmode = "cterm" + let s:background = "234" + let s:window = "236" + let s:darkcolumn = "234" + let s:addbg = "65" + let s:addfg = "193" + let s:changebg = "60" + let s:changefg = "189" + let s:darkblue = "17" + let s:darkcyan = "24" + let s:darkred = "52" + let s:darkpurple = "53" + if g:hybrid_use_Xresources == 1 + let s:foreground = "15" " White + let s:selection = "8" " DarkGrey + let s:line = "0" " Black + let s:comment = "7" " LightGrey + let s:red = "9" " LightRed + let s:orange = "3" " DarkYellow + let s:yellow = "11" " LightYellow + let s:green = "10" " LightGreen + let s:aqua = "14" " LightCyan + let s:blue = "12" " LightBlue + let s:purple = "13" " LightMagenta + elseif g:hybrid_use_iTerm_colors == 1 + let s:background = "NONE" + let s:foreground = "7" + let s:selection = "0" + let s:line = "0" + let s:comment = "15" + let s:red = "1" + let s:orange = "11" + let s:yellow = "3" + let s:green = "2" + let s:aqua = "6" + let s:blue = "4" + let s:purple = "5" + else + let s:foreground = "250" + let s:selection = "237" + let s:line = "235" + let s:comment = "243" + let s:red = "167" + let s:orange = "173" + let s:yellow = "221" + let s:green = "143" + let s:aqua = "109" + let s:blue = "110" + let s:purple = "139" + endif +endif + +"}}} +" Formatting Options:"{{{ +" ---------------------------------------------------------------------------- +let s:none = "NONE" +let s:t_none = "NONE" +let s:n = "NONE" +let s:c = ",undercurl" +let s:r = ",reverse" +let s:s = ",standout" +let s:b = ",bold" +let s:u = ",underline" +let s:i = ",italic" + +"}}} +" Highlighting Primitives:"{{{ +" ---------------------------------------------------------------------------- +exe "let s:bg_none = ' ".s:vmode."bg=".s:none ."'" +exe "let s:bg_foreground = ' ".s:vmode."bg=".s:foreground."'" +exe "let s:bg_background = ' ".s:vmode."bg=".s:background."'" +exe "let s:bg_selection = ' ".s:vmode."bg=".s:selection ."'" +exe "let s:bg_line = ' ".s:vmode."bg=".s:line ."'" +exe "let s:bg_comment = ' ".s:vmode."bg=".s:comment ."'" +exe "let s:bg_red = ' ".s:vmode."bg=".s:red ."'" +exe "let s:bg_orange = ' ".s:vmode."bg=".s:orange ."'" +exe "let s:bg_yellow = ' ".s:vmode."bg=".s:yellow ."'" +exe "let s:bg_green = ' ".s:vmode."bg=".s:green ."'" +exe "let s:bg_aqua = ' ".s:vmode."bg=".s:aqua ."'" +exe "let s:bg_blue = ' ".s:vmode."bg=".s:blue ."'" +exe "let s:bg_purple = ' ".s:vmode."bg=".s:purple ."'" +exe "let s:bg_window = ' ".s:vmode."bg=".s:window ."'" +exe "let s:bg_darkcolumn = ' ".s:vmode."bg=".s:darkcolumn."'" +exe "let s:bg_addbg = ' ".s:vmode."bg=".s:addbg ."'" +exe "let s:bg_addfg = ' ".s:vmode."bg=".s:addfg ."'" +exe "let s:bg_changebg = ' ".s:vmode."bg=".s:changebg ."'" +exe "let s:bg_changefg = ' ".s:vmode."bg=".s:changefg ."'" +exe "let s:bg_darkblue = ' ".s:vmode."bg=".s:darkblue ."'" +exe "let s:bg_darkcyan = ' ".s:vmode."bg=".s:darkcyan ."'" +exe "let s:bg_darkred = ' ".s:vmode."bg=".s:darkred ."'" +exe "let s:bg_darkpurple = ' ".s:vmode."bg=".s:darkpurple."'" + +exe "let s:fg_none = ' ".s:vmode."fg=".s:none ."'" +exe "let s:fg_foreground = ' ".s:vmode."fg=".s:foreground."'" +exe "let s:fg_background = ' ".s:vmode."fg=".s:background."'" +exe "let s:fg_selection = ' ".s:vmode."fg=".s:selection ."'" +exe "let s:fg_line = ' ".s:vmode."fg=".s:line ."'" +exe "let s:fg_comment = ' ".s:vmode."fg=".s:comment ."'" +exe "let s:fg_red = ' ".s:vmode."fg=".s:red ."'" +exe "let s:fg_orange = ' ".s:vmode."fg=".s:orange ."'" +exe "let s:fg_yellow = ' ".s:vmode."fg=".s:yellow ."'" +exe "let s:fg_green = ' ".s:vmode."fg=".s:green ."'" +exe "let s:fg_aqua = ' ".s:vmode."fg=".s:aqua ."'" +exe "let s:fg_blue = ' ".s:vmode."fg=".s:blue ."'" +exe "let s:fg_purple = ' ".s:vmode."fg=".s:purple ."'" +exe "let s:fg_window = ' ".s:vmode."fg=".s:window ."'" +exe "let s:fg_darkcolumn = ' ".s:vmode."fg=".s:darkcolumn."'" +exe "let s:fg_addbg = ' ".s:vmode."fg=".s:addbg ."'" +exe "let s:fg_addfg = ' ".s:vmode."fg=".s:addfg ."'" +exe "let s:fg_changebg = ' ".s:vmode."fg=".s:changebg ."'" +exe "let s:fg_changefg = ' ".s:vmode."fg=".s:changefg ."'" +exe "let s:fg_darkblue = ' ".s:vmode."fg=".s:darkblue ."'" +exe "let s:fg_darkcyan = ' ".s:vmode."fg=".s:darkcyan ."'" +exe "let s:fg_darkred = ' ".s:vmode."fg=".s:darkred ."'" +exe "let s:fg_darkpurple = ' ".s:vmode."fg=".s:darkpurple."'" + +exe "let s:fmt_none = ' ".s:vmode."=NONE". " term=NONE" ."'" +exe "let s:fmt_bold = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b ."'" +exe "let s:fmt_bldi = ' ".s:vmode."=NONE".s:b. " term=NONE".s:b ."'" +exe "let s:fmt_undr = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u ."'" +exe "let s:fmt_undb = ' ".s:vmode."=NONE".s:u.s:b. " term=NONE".s:u.s:b."'" +exe "let s:fmt_undi = ' ".s:vmode."=NONE".s:u. " term=NONE".s:u ."'" +exe "let s:fmt_curl = ' ".s:vmode."=NONE".s:c. " term=NONE".s:c ."'" +exe "let s:fmt_ital = ' ".s:vmode."=NONE".s:i. " term=NONE".s:i ."'" +exe "let s:fmt_stnd = ' ".s:vmode."=NONE".s:s. " term=NONE".s:s ."'" +exe "let s:fmt_revr = ' ".s:vmode."=NONE".s:r. " term=NONE".s:r ."'" +exe "let s:fmt_revb = ' ".s:vmode."=NONE".s:r.s:b. " term=NONE".s:r.s:b."'" + +if has("gui_running") + exe "let s:sp_none = ' guisp=".s:none ."'" + exe "let s:sp_foreground = ' guisp=".s:foreground."'" + exe "let s:sp_background = ' guisp=".s:background."'" + exe "let s:sp_selection = ' guisp=".s:selection ."'" + exe "let s:sp_line = ' guisp=".s:line ."'" + exe "let s:sp_comment = ' guisp=".s:comment ."'" + exe "let s:sp_red = ' guisp=".s:red ."'" + exe "let s:sp_orange = ' guisp=".s:orange ."'" + exe "let s:sp_yellow = ' guisp=".s:yellow ."'" + exe "let s:sp_green = ' guisp=".s:green ."'" + exe "let s:sp_aqua = ' guisp=".s:aqua ."'" + exe "let s:sp_blue = ' guisp=".s:blue ."'" + exe "let s:sp_purple = ' guisp=".s:purple ."'" + exe "let s:sp_window = ' guisp=".s:window ."'" + exe "let s:sp_addbg = ' guisp=".s:addbg ."'" + exe "let s:sp_addfg = ' guisp=".s:addfg ."'" + exe "let s:sp_changebg = ' guisp=".s:changebg ."'" + exe "let s:sp_changefg = ' guisp=".s:changefg ."'" + exe "let s:sp_darkblue = ' guisp=".s:darkblue ."'" + exe "let s:sp_darkcyan = ' guisp=".s:darkcyan ."'" + exe "let s:sp_darkred = ' guisp=".s:darkred ."'" + exe "let s:sp_darkpurple = ' guisp=".s:darkpurple."'" +else + let s:sp_none = "" + let s:sp_foreground = "" + let s:sp_background = "" + let s:sp_selection = "" + let s:sp_line = "" + let s:sp_comment = "" + let s:sp_red = "" + let s:sp_orange = "" + let s:sp_yellow = "" + let s:sp_green = "" + let s:sp_aqua = "" + let s:sp_blue = "" + let s:sp_purple = "" + let s:sp_window = "" + let s:sp_addbg = "" + let s:sp_addfg = "" + let s:sp_changebg = "" + let s:sp_changefg = "" + let s:sp_darkblue = "" + let s:sp_darkcyan = "" + let s:sp_darkred = "" + let s:sp_darkpurple = "" +endif + +"}}} +" Vim Highlighting: (see :help highlight-groups)"{{{ +" ---------------------------------------------------------------------------- +exe "hi! ColorColumn" .s:fg_none .s:bg_line .s:fmt_none +" Conceal" +" Cursor" +" CursorIM" +exe "hi! CursorColumn" .s:fg_none .s:bg_line .s:fmt_none +exe "hi! CursorLine" .s:fg_none .s:bg_line .s:fmt_none +exe "hi! Directory" .s:fg_blue .s:bg_none .s:fmt_none +exe "hi! DiffAdd" .s:fg_addfg .s:bg_addbg .s:fmt_none +exe "hi! DiffChange" .s:fg_changefg .s:bg_changebg .s:fmt_none +exe "hi! DiffDelete" .s:fg_background .s:bg_red .s:fmt_none +exe "hi! DiffText" .s:fg_background .s:bg_blue .s:fmt_none +exe "hi! ErrorMsg" .s:fg_background .s:bg_red .s:fmt_stnd +exe "hi! VertSplit" .s:fg_window .s:bg_none .s:fmt_none +exe "hi! Folded" .s:fg_comment .s:bg_darkcolumn .s:fmt_none +exe "hi! FoldColumn" .s:fg_none .s:bg_darkcolumn .s:fmt_none +exe "hi! SignColumn" .s:fg_none .s:bg_darkcolumn .s:fmt_none +" Incsearch" +exe "hi! LineNr" .s:fg_selection .s:bg_none .s:fmt_none +exe "hi! CursorLineNr" .s:fg_yellow .s:bg_none .s:fmt_bold +exe "hi! MatchParen" .s:fg_background .s:bg_changebg .s:fmt_none +exe "hi! ModeMsg" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! MoreMsg" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! NonText" .s:fg_selection .s:bg_none .s:fmt_none +exe "hi! Pmenu" .s:fg_foreground .s:bg_selection .s:fmt_none +exe "hi! PmenuSel" .s:fg_foreground .s:bg_selection .s:fmt_revr +" PmenuSbar" +" PmenuThumb" +exe "hi! Question" .s:fg_green .s:bg_none .s:fmt_none +exe "hi! Search" .s:fg_background .s:bg_yellow .s:fmt_none +exe "hi! SpecialKey" .s:fg_selection .s:bg_none .s:fmt_none +exe "hi! SpellCap" .s:fg_blue .s:bg_darkblue .s:fmt_undr +exe "hi! SpellLocal" .s:fg_aqua .s:bg_darkcyan .s:fmt_undr +exe "hi! SpellBad" .s:fg_red .s:bg_darkred .s:fmt_undr +exe "hi! SpellRare" .s:fg_purple .s:bg_darkpurple .s:fmt_undr +exe "hi! StatusLine" .s:fg_comment .s:bg_background .s:fmt_revr +exe "hi! StatusLineNC" .s:fg_window .s:bg_comment .s:fmt_revr +exe "hi! TabLine" .s:fg_foreground .s:bg_darkcolumn .s:fmt_revr +" TabLineFill" +" TabLineSel" +exe "hi! Title" .s:fg_yellow .s:bg_none .s:fmt_none +exe "hi! Visual" .s:fg_none .s:bg_selection .s:fmt_none +" VisualNos" +exe "hi! WarningMsg" .s:fg_red .s:bg_none .s:fmt_none +" WildMenu" + +" Use Xresources for background colour +if has('gui_running') || (g:hybrid_use_Xresources != 1 && g:hybrid_use_iTerm_colors != 1) + exe "hi! Normal" .s:fg_foreground .s:bg_background .s:fmt_none +else + exe "hi! Normal" .s:fg_foreground .s:bg_none .s:fmt_none +endif + +"}}} +" Generic Syntax Highlighting: (see :help group-name)"{{{ +" ---------------------------------------------------------------------------- +exe "hi! Comment" .s:fg_comment .s:bg_none .s:fmt_none + +exe "hi! Constant" .s:fg_red .s:bg_none .s:fmt_none +exe "hi! String" .s:fg_green .s:bg_none .s:fmt_none +" Character" +" Number" +" Boolean" +" Float" + +exe "hi! Identifier" .s:fg_purple .s:bg_none .s:fmt_none +exe "hi! Function" .s:fg_yellow .s:bg_none .s:fmt_none + +exe "hi! Statement" .s:fg_blue .s:bg_none .s:fmt_none +" Conditional" +" Repeat" +" Label" +exe "hi! Operator" .s:fg_aqua .s:bg_none .s:fmt_none +" Keyword" +" Exception" + +exe "hi! PreProc" .s:fg_aqua .s:bg_none .s:fmt_none +" Include" +" Define" +" Macro" +" PreCondit" + +exe "hi! Type" .s:fg_orange .s:bg_none .s:fmt_none +" StorageClass" +exe "hi! Structure" .s:fg_aqua .s:bg_none .s:fmt_none +" Typedef" + +exe "hi! Special" .s:fg_green .s:bg_none .s:fmt_none +" SpecialChar" +" Tag" +" Delimiter" +" SpecialComment" +" Debug" +" +exe "hi! Underlined" .s:fg_blue .s:bg_none .s:fmt_none + +exe "hi! Ignore" .s:fg_none .s:bg_none .s:fmt_none + +exe "hi! Error" .s:fg_red .s:bg_darkred .s:fmt_undr + +exe "hi! Todo" .s:fg_addfg .s:bg_none .s:fmt_none + +" Quickfix window highlighting +exe "hi! qfLineNr" .s:fg_yellow .s:bg_none .s:fmt_none +" qfFileName" +" qfLineNr" +" qfError" + +"}}} +" Diff Syntax Highlighting:"{{{ +" ---------------------------------------------------------------------------- +" Diff +" diffOldFile +" diffNewFile +" diffFile +" diffOnly +" diffIdentical +" diffDiffer +" diffBDiffer +" diffIsA +" diffNoEOL +" diffCommon +hi! link diffRemoved Constant +" diffChanged +hi! link diffAdded Special +" diffLine +" diffSubname +" diffComment + +"}}} +" Legal:"{{{ +" ---------------------------------------------------------------------------- +" Copyright (c) 2011 Ethan Schoonover +" Copyright (c) 2009-2012 NanoTech +" Copyright (c) 2012 w0ng +" +" Permission is hereby granted, free of charge, to any per‐ +" son obtaining a copy of this software and associated doc‐ +" umentation files (the “Software”), to deal in the Soft‐ +" ware without restriction, including without limitation +" the rights to use, copy, modify, merge, publish, distrib‐ +" ute, sublicense, and/or sell copies of the Software, and +" to permit persons to whom the Software is furnished to do +" so, subject to the following conditions: +" +" The above copyright notice and this permission notice +" shall be included in all copies or substantial portions +" of the Software. +" +" THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY +" KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +" THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICU‐ +" LAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CON‐ +" TRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON‐ +" NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +" THE SOFTWARE. + +" }}} + +" My tweaks (scwood) +hi ColorColumn cterm=NONE ctermbg=233 ctermfg=NONE +hi StatusLine cterm=none ctermbg=235 ctermfg=015 +hi StatusLineNC cterm=none ctermbg=235 ctermfg=NONE +hi CursorLine cterm=NONE ctermbg=236 ctermfg=NONE +let g:indentLine_color_term = 237 diff --git a/.vim/plugin/toggle_mouse.vim b/.vim/plugin/toggle_mouse.vim new file mode 100644 index 0000000..3c880d1 --- /dev/null +++ b/.vim/plugin/toggle_mouse.vim @@ -0,0 +1,36 @@ +" +" Toggle mouse plugin for quickly toggling mouse between Vim and terminal +" Maintainer: Vincent Driessen +" Version: Vim 7 (may work with lower Vim versions, but not tested) +" URL: http://github.com/nvie/vim-togglemouse +" +" Only do this when not done yet for this buffer +if exists("b:loaded_toggle_mouse_plugin") + finish +endif +let b:loaded_toggle_mouse_plugin = 1 + +fun! s:ToggleMouse() + if !exists("s:old_mouse") + let s:old_mouse = "a" + endif + + if &mouse == "" + let &mouse = s:old_mouse + echo "Mouse is for Vim (" . &mouse . ")" + else + let s:old_mouse = &mouse + let &mouse="" + echo "Mouse is for terminal" + endif +endfunction + +" Add mappings, unless the user didn't want this. +" The default mapping is registered under to by default, unless the user +" remapped it already (or a mapping exists already for ) +if !exists("no_plugin_maps") && !exists("no_toggle_mouse_maps") + if !hasmapto('ToggleMouse()') + noremap :call ToggleMouse() + inoremap :call ToggleMouse()a + endif +endif diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..28111b1 --- /dev/null +++ b/.vimrc @@ -0,0 +1,400 @@ +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Maintainer: +" Amir Salihefendic +" http://amix.dk - amix@amix.dk +" +" Version: +" 5.0 - 29/05/12 15:43:36 +" +" Blog_post: +" http://amix.dk/blog/post/19691#The-ultimate-Vim-configuration-on-Github +" +" Awesome_version: +" Get this config, nice color schemes and lots of plugins! +" +" Install the awesome version from: +" +" https://github.com/amix/vimrc +" +" Syntax_highlighted: +" http://amix.dk/vim/vimrc.html +" +" Raw_version: +" http://amix.dk/vim/vimrc.txt +" +" Sections: +" -> General +" -> VIM user interface +" -> Colors and Fonts +" -> Files and backups +" -> Text, tab and indent related +" -> Visual mode related +" -> Moving around, tabs and buffers +" -> Status line +" -> Editing mappings +" -> vimgrep searching and cope displaying +" -> Spell checking +" -> Misc +" -> Helper functions +" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => General +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Sets how many lines of history VIM has to remember +set history=700 + +" Enable filetype plugins +filetype plugin on +filetype indent on + +" Set to auto read when a file is changed from the outside +set autoread + +" With a map leader it's possible to do extra key combinations +" like w saves the current file +let mapleader = "," +let g:mapleader = "," + +" Fast saving +nmap w :w! + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => VIM user interface +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Set 7 lines to the cursor - when moving vertically using j/k +set so=7 + +" Turn on the WiLd menu +set wildmenu + +" Ignore compiled files +set wildignore=*.o,*~,*.pyc + +"Always show current position +set ruler + +" Height of the command bar +set cmdheight=1 + +" A buffer becomes hidden when it is abandoned +set hid + +" Configure backspace so it acts as it should act +set backspace=eol,start,indent +set whichwrap+=<,>,h,l + +" Ignore case when searching +set ignorecase + +" When searching try to be smart about cases +set smartcase + +" Highlight search results +set hlsearch + +" Makes search act like search in modern browsers +set incsearch + +" Don't redraw while executing macros (good performance config) +set lazyredraw + +" For regular expressions turn magic on +set magic + +" Show matching brackets when text indicator is over them +set showmatch +" How many tenths of a second to blink when matching brackets +set mat=2 + +" No annoying sound on errors +set noerrorbells +set novisualbell +set t_vb= +set tm=500 + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Colors and Fonts +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Enable syntax highlighting +syntax enable + +"colorscheme desert +colorscheme hybrid-light +"set background=dark + +" Set extra options when running in GUI mode +if has("gui_running") + set guioptions-=T + set guioptions+=e + set t_Co=256 + set guitablabel=%M\ %t +endif + +" Set utf8 as standard encoding and en_US as the standard language +set encoding=utf8 + +" Use Unix as the standard file type +set ffs=unix,dos,mac + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Files, backups and undo +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Turn backup off, since most stuff is in SVN, git et.c anyway... +set nobackup +set nowb +set noswapfile + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Text, tab and indent related +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Use spaces instead of tabs +set expandtab + +" Be smart when using tabs ;) +set smarttab + +" 1 tab == 4 spaces +set shiftwidth=3 +set tabstop=3 + +" Linebreak on 500 characters +set lbr +set tw=500 + +"set ai "Auto indent +set si "Smart indent +set wrap "Wrap lines + + +"""""""""""""""""""""""""""""" +" => Visual mode related +"""""""""""""""""""""""""""""" +" Visual mode pressing * or # searches for the current selection +" Super useful! From an idea by Michael Naumann +vnoremap * :call VisualSelection('f') +vnoremap # :call VisualSelection('b') + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Moving around, tabs, windows and buffers +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Treat long lines as break lines (useful when moving around in them) +map j gj +map k gk + +" Map to / (search) and Ctrl- to ? (backwards search) +map / +map ? + +" Disable highlight when is pressed +map :noh + +" Smart way to move between windows +map j +map k +map h +map l + +" Close the current buffer +map bd :Bclose + +" Close all the buffers +map ba :1,1000 bd! + +" Useful mappings for managing tabs +map tn :tabnew +map to :tabonly +map tc :tabclose +map tm :tabmove + +" Opens a new tab with the current buffer's path +" Super useful when editing files in the same directory +map te :tabedit =expand("%:p:h")/ + +" Switch CWD to the directory of the open buffer +map cd :cd %:p:h:pwd + +" Specify the behavior when switching between buffers +try + set switchbuf=useopen,usetab,newtab + set stal=2 +catch +endtry + +" Return to last edit position when opening files (You want this!) +autocmd BufReadPost * + \ if line("'\"") > 0 && line("'\"") <= line("$") | + \ exe "normal! g`\"" | + \ endif +" Remember info about open buffers on close +set viminfo^=% + + +"""""""""""""""""""""""""""""" +" => Status line +"""""""""""""""""""""""""""""" +" Always show the status line +set laststatus=2 + +" Format the status line +set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Editing mappings +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Remap VIM 0 to first non-blank character +map 0 ^ + +" Move a line of text using ALT+[jk] or Comamnd+[jk] on mac +nmap mz:m+`z +nmap mz:m-2`z +vmap :m'>+`mzgv`yo`z +vmap :m'<-2`>my` + nmap + vmap + vmap +endif + +" Delete trailing white space on save, useful for Python and CoffeeScript ;) +func! DeleteTrailingWS() + exe "normal mz" + %s/\s\+$//ge + exe "normal `z" +endfunc +autocmd BufWrite *.py :call DeleteTrailingWS() +autocmd BufWrite *.coffee :call DeleteTrailingWS() + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => vimgrep searching and cope displaying +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" When you press gv you vimgrep after the selected text +vnoremap gv :call VisualSelection('gv') + +" Open vimgrep and put the cursor in the right position +map g :vimgrep // **/*. + +" Vimgreps in the current file +map :vimgrep // % + +" When you press r you can search and replace the selected text +vnoremap r :call VisualSelection('replace') + +" Do :help cope if you are unsure what cope is. It's super useful! +" +" When you search with vimgrep, display your results in cope by doing: +" cc +" +" To go to the next search result do: +" n +" +" To go to the previous search results do: +" p +" +map cc :botright cope +map co ggVGy:tabnew:set syntax=qfpgg +map n :cn +map p :cp + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Spell checking +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Pressing ,ss will toggle and untoggle spell checking +map ss :setlocal spell! + +" Shortcuts using +map sn ]s +map sp [s +map sa zg +map s? z= + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Misc +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" Remove the Windows ^M - when the encodings gets messed up +noremap m mmHmt:%s///ge'tzt'm + +" Quickly open a buffer for scripbble +map q :e ~/buffer + +" Toggle paste mode on and off +map pp :setlocal paste! +set pastetoggle= + + +" Define Mouse Mode +"set mouse=a + + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" => Helper functions +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +function! CmdLine(str) + exe "menu Foo.Bar :" . a:str + emenu Foo.Bar + unmenu Foo +endfunction + +function! VisualSelection(direction) range + let l:saved_reg = @" + execute "normal! vgvy" + + let l:pattern = escape(@", '\\/.*$^~[]') + let l:pattern = substitute(l:pattern, "\n$", "", "") + + if a:direction == 'b' + execute "normal ?" . l:pattern . "^M" + elseif a:direction == 'gv' + call CmdLine("vimgrep " . '/'. l:pattern . '/' . ' **/*.') + elseif a:direction == 'replace' + call CmdLine("%s" . '/'. l:pattern . '/') + elseif a:direction == 'f' + execute "normal /" . l:pattern . "^M" + endif + + let @/ = l:pattern + let @" = l:saved_reg +endfunction + + +" Returns true if paste mode is enabled +function! HasPaste() + if &paste + return 'PASTE MODE ' + en + return '' +endfunction + +" Don't close window, when deleting a buffer +command! Bclose call BufcloseCloseIt() +function! BufcloseCloseIt() + let l:currentBufNum = bufnr("%") + let l:alternateBufNum = bufnr("#") + + if buflisted(l:alternateBufNum) + buffer # + else + bnext + endif + + if bufnr("%") == l:currentBufNum + new + endif + + if buflisted(l:currentBufNum) + execute("bdelete! ".l:currentBufNum) + endif +endfunction + diff --git a/README.md b/README.md index 7796a36..f48c261 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ -# dotfiles -Collection of various config files +# Dotfiles + +## Overview + +This repo is a skeleton/template repo for tracking my dotfiles. It contains a utility ([dfm](https://github.com/justone/dfm)) to help with managing and +updating your dotfiles. + +## Using this repo + +First, fork this repo. + +Then, add your dotfiles: + + $ git clone https://github.com/Eragos/dotfiles.git .dotfiles + $ cd .dotfiles + $ # add and edit files you want + $ git push origin master + +Finally, to install your dotfiles onto a new system: + + $ cd $HOME + $ git clone git@github.com:username/dotfiles.git .dotfiles + $ ./.dotfiles/bin/dfm install # creates symlinks to install files + +## Full documentation + +For more information, check out the [wiki](http://github.com/justone/dotfiles/wiki). + +You can also run dfm --help. \ No newline at end of file diff --git a/aliases b/aliases new file mode 100755 index 0000000..e90b15c --- /dev/null +++ b/aliases @@ -0,0 +1,28 @@ +# Dir navigation +alias ..='cd ..' +alias ...='cd ../..' +alias ....='cd ../../..' +alias ~='cd ~' + +alias la='ls -la' +alias ls='ls -GFh' + + +# Utilities +alias a="ack -ia" +alias b="bundle exec" +alias c="pygmentize -O style=monokai -f console256 -g" +alias d="du -h -d=1" +alias df="df -h" +alias g="git" +alias grep='GREP_COLOR="1;37;45" LANG=C grep --color=auto' +alias h="history" +alias httpdump="sudo tcpdump -i en1 -n -s 0 -w - | grep -a -o -E \"Host\: .*|GET \/.*\"" +alias ip="curl -s http://checkip.dyndns.com/ | sed 's/[^0-9\.]//g'" +alias localip="ipconfig getifaddr en1" +#alias mp="mvim -p" +#alias rkt="racket -il xrepl" +alias tmux="tmux -2" +alias view="vim -p -R" +alias vp="vim -p" + diff --git a/bin/dfm b/bin/dfm new file mode 100755 index 0000000..9cb6205 --- /dev/null +++ b/bin/dfm @@ -0,0 +1,1140 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use English qw( -no_match_vars ); # Avoids regex performance penalty +use Data::Dumper; +use FindBin qw($RealBin $RealScript); +use Getopt::Long; +use Cwd qw(realpath getcwd); +use File::Spec; +use File::Copy; +use File::Basename; +use Pod::Usage; + +our $VERSION = 'v0.7.4'; + +my %opts; +my $shellrc_filename; +my $shellrc_load_filename; +my $repo_dir; +my $home; + +my $command_aliases = { + 'mi' => 'mergeandinstall', + 'umi' => 'updatemergeandinstall', + 'un' => 'uninstall', + 'im' => 'import', + 'in' => 'install' +}; + +my $commands = { + 'install' => sub { + DEBUG("Running in [$RealBin] and installing in [$home]"); + + # install files + install( $home, $repo_dir ); + }, + 'updates' => sub { + my $argv = shift; + + GetOptionsFromArray( $argv, \%opts, 'no-fetch' ); + + fetch_updates( \%opts ); + }, + 'mergeandinstall' => sub { + my $argv = shift; + + GetOptionsFromArray( $argv, \%opts, 'merge', 'rebase' ); + + merge_and_install( \%opts ); + }, + 'updatemergeandinstall' => sub { + my $argv = shift; + + GetOptionsFromArray( $argv, \%opts, 'merge', 'no-fetch' ); + + fetch_updates( \%opts ); + merge_and_install( \%opts ); + }, + 'uninstall' => sub { + my $argv = shift; + + # uninstall files + uninstall($home, $repo_dir); + }, + 'import' => sub { + my $argv = shift; + + GetOptionsFromArray( $argv, \%opts, 'message=s', 'no-commit|n' ); + + # import files + import_files( _abs_repo_path( $home, $repo_dir ), $home, $argv ); + }, + 'help' => sub { + my $argv = shift; + + my $command = shift @$argv; + + if ($command) { + $command = $command_aliases->{$command} || $command; + + my %options = ( + -verbose => 99, + -exitstatus => 0, + -sections => uc($command), + ); + + # if run as part of test, add option to point + # to real script source + if ( $RealScript eq '04.misc.t' ) { + $options{'-input'} = '../dfm'; + } + + pod2usage(%options); + } + else { + pod2usage(2); + } + }, +}; + +run_dfm( $RealBin, @ARGV ) unless defined caller; + +sub run_dfm { + my ( $realbin, @argv ) = @_; + + # set options to nothing so that running multiple times in tests + # does not reuse options + %opts = (); + $shellrc_filename = undef; + $shellrc_load_filename = undef; + $repo_dir = undef; + $home = undef; + + my $command; + + if ( scalar(@argv) == 0 || $argv[0] =~ /^-/ ) { + + # check to make sure there's not a dfm subcommand later in the arg list + if ( grep { exists $commands->{$_} } @argv ) { + ERROR("The command should be first."); + exit(-2); + } + $command = 'help'; + } + else { + $command = $argv[0]; + } + + $command = $command_aliases->{$command} || $command; + + if ( exists $commands->{$command} ) { + + # parse global options first + Getopt::Long::Configure('pass_through'); + GetOptionsFromArray( \@argv, \%opts, 'verbose', 'quiet', 'dry-run', 'help', 'version' ); + Getopt::Long::Configure('no_pass_through'); + } + + $home = realpath( $ENV{HOME} ); + if ( !$home ) { + ERROR("unable to determine 'realpath' for $ENV{HOME}"); + exit(-2); + } + + if ( $ENV{'DFM_REPO'} ) { + $repo_dir = $ENV{'DFM_REPO'}; + $repo_dir =~ s/$home\///; + } + elsif ( -e "$realbin/t/02.updates_mergeandinstall.t" ) { + + # dfm is being invoked from its own repo, not a dotfiles repo; try and + # figure out what repo in the users's homedir is the dotfiles repo + # + # TODO: alternate strategy: see if there are files in $home that are + # already symlinked and use those as a guide + foreach my $potential_dotfiles_repo (qw(.dotfiles dotfiles)) { + if ( -d "$home/$potential_dotfiles_repo" + && -d "$home/$potential_dotfiles_repo/.git" ) + { + $repo_dir = "$home/$potential_dotfiles_repo"; + $repo_dir =~ s/$home\///; + } + } + + if ( !$repo_dir ) { + ERROR("unable to discover dotfiles repo and dfm is running from its own repo"); + exit(-2); + } + } + else { + $repo_dir = $realbin; + $repo_dir =~ s/$home\///; + $repo_dir =~ s/\/bin//; + } + + DEBUG("Repo dir: $repo_dir"); + + # extract the shell name from env + my $shell = basename( $ENV{SHELL} ); + $shellrc_filename = '.' . $shell . 'rc'; + + DEBUG("Shell: $shell, Shell RC filename: $shellrc_filename"); + + # shellrc in MacOS is ~/.profile + if ( lc($OSNAME) eq 'darwin' and $shell eq 'bash' ) { + $shellrc_filename = '.profile'; + } + + if ( exists $commands->{$command} ) { + if ( $opts{'help'} ) { + $commands->{'help'}->( [$command] ); + } + elsif ( $opts{'version'} ) { + show_version(); + } + else { + shift(@argv); # remove the command from the array + $commands->{$command}->( \@argv ); + } + } + else { + + # assume it's a git command and call accordingly + _run_git(@argv); + } +} + +sub my_symlink { + my $target = shift; + my $link = shift; + + if ($^O eq "cygwin") + { + my $flags = ""; + if (-d $target) { $flags = "/D" }; + + $target = `cygpath -w $target`; + $link = `cygpath -w $link`; + + chomp $target; + chomp $link; + + my $command = "cmd /c mklink $flags \"$link\" \"$target\""; + system($command); + } + else + { + symlink($target,$link); + } +} + +sub get_changes { + my $what = shift; + + return `git log --pretty='format:%h: %s' $what`; +} + +sub get_current_branch { + my $current_branch = `git symbolic-ref HEAD`; + chomp $current_branch; + + # convert 'refs/heads/personal' to 'personal' + $current_branch =~ s/^.+\///g; + + DEBUG("current branch: $current_branch"); + + return $current_branch; +} + +sub check_remote_branch { + my $branch = shift; + my $branch_remote = `git config branch.$branch.remote`; + chomp $branch_remote; + + DEBUG("remote for branch $branch: $branch_remote"); + + if ( $branch_remote eq "" ) { + WARN("no remote found for branch $branch"); + exit(-1); + } +} + +# a few log4perl-alikes +sub ERROR { + print "ERROR: @_\n"; +} + +sub WARN { + print "WARN: @_\n"; +} + +sub INFO { + print "INFO: @_\n" if !$opts{quiet}; +} + +sub DEBUG { + print "DEBUG: @_\n" if $opts{verbose}; +} + +sub fetch_updates { + my $opts = shift; + + chdir( _abs_repo_path( $home, $repo_dir ) ); + + if ( !$opts->{'no-fetch'} ) { + DEBUG('fetching changes'); + system("git fetch") if !$opts->{'dry-run'}; + } + + my $current_branch = get_current_branch(); + check_remote_branch($current_branch); + + print get_changes("$current_branch..$current_branch\@{u}"), "\n"; +} + +sub merge_and_install { + my $opts = shift; + + chdir( _abs_repo_path( $home, $repo_dir ) ); + + my $current_branch = get_current_branch(); + check_remote_branch($current_branch); + + my $sync_command = $opts->{'rebase'} ? 'rebase' : 'merge'; + + if ( get_changes("$current_branch..$current_branch\@{u}") ) { + + # check for local commits + if ( my $local_changes = get_changes("$current_branch\@{u}..$current_branch") ) { + + # if a decision wasn't made about how to deal with local commits + if ( !$opts->{'merge'} && !$opts->{'rebase'} ) { + WARN("local changes detected, run with either --merge or --rebase"); + print $local_changes, "\n"; + exit; + } + } + + INFO("using $sync_command to bring in changes"); + system("git $sync_command $current_branch\@{u}") + if !$opts->{'dry-run'}; + + INFO("re-installing dotfiles"); + install( $home, $repo_dir ) if !$opts->{'dry-run'}; + } + else { + INFO("no changes to merge"); + } +} + +sub install { + my ( $home, $repo_dir ) = @_; + + INFO( "Installing dotfiles..." . ( $opts{'dry-run'} ? ' (dry run)' : '' ) ); + + DEBUG("Running in [$RealBin] and installing in [$home]"); + + install_files( _abs_repo_path( $home, $repo_dir ), $home ); + + $shellrc_load_filename = ''; + + # link in the shell loader + if ( -e _abs_repo_path( $home, $repo_dir ) . "/.shellrc.load" ) { + $shellrc_load_filename = '.shellrc.load'; + } + elsif ( -e _abs_repo_path( $home, $repo_dir ) . "/.bashrc.load" ) { + $shellrc_load_filename = '.bashrc.load'; + } + + if ($shellrc_load_filename) { + configure_shell_loader(); + } +} + +sub uninstall { + my ( $home, $repo_dir ) = @_; + + INFO( "Uninstalling dotfiles..." . ( $opts{'dry-run'} ? ' (dry run)' : '' ) ); + + DEBUG("Running in [$RealBin] and installing in [$home]"); + + # uninstall files + uninstall_files( _abs_repo_path( $home, $repo_dir ), $home ); + + # link in the shell loader + if ( -e _abs_repo_path( $home, $repo_dir ) . "/.shellrc.load" ) { + $shellrc_load_filename = '.shellrc.load'; + } + elsif ( -e _abs_repo_path( $home, $repo_dir ) . "/.bashrc.load" ) { + $shellrc_load_filename = '.bashrc.load'; + } + + if ($shellrc_load_filename) { + unconfigure_shell_loader(); + } +} + +# function to install files +# possible options: +# install_only: list of files to install, as opposed to all of them +sub install_files { + my ( $source_dir, $target_dir, $options ) = @_; + + my $install_only; + + if ( $options->{install_only} + && scalar @{ $options->{install_only} } > 0 ) + { + $install_only = $options->{install_only}; + } + + DEBUG("Installing from $source_dir into $target_dir"); + + my $symlink_base = _calculate_symlink_base( $source_dir, $target_dir ); + + my $backup_dir = $target_dir . '/.backup'; + DEBUG("Backup dir: $backup_dir"); + + my $cwd_before_install = getcwd(); + chdir($target_dir); + + my $dfm_install = _load_dfminstall("$source_dir/.dfminstall"); + + if ( !-e $backup_dir ) { + DEBUG("Creating $backup_dir"); + mkdir($backup_dir) if !$opts{'dry-run'}; + } + + my $dirh; + opendir $dirh, $source_dir; + foreach my $direntry ( readdir($dirh) ) { + + if ($install_only) { + next unless grep { $_ eq $direntry } @$install_only; + } + + # skip vim swap files + next if $direntry =~ /^\..*\.sw.$/; + + # skip emacs temporary and backup files + next if $direntry =~ /^\.#.*$/; + next if $direntry =~ /^.*~$/; + + # skip any other files + next if $dfm_install->{skip_files}->{$direntry}; + + DEBUG(" Working on $direntry"); + + if ( !-l $direntry ) { + if ( -e $direntry ) { + INFO(" Backing up $direntry."); + system("mv '$direntry' '$backup_dir/$direntry'") + if !$opts{'dry-run'}; + } + INFO(" Symlinking $direntry ($symlink_base/$direntry)."); + my_symlink( "$symlink_base/$direntry", "$direntry" ) + if !$opts{'dry-run'}; + } + } + + cleanup_dangling_symlinks( $source_dir, $target_dir, $dfm_install->{skip_files} ); + + foreach my $recurse ( @{ $dfm_install->{recurse_files} } ) { + if ( -d "$source_dir/$recurse" ) { + DEBUG("recursing into $source_dir/$recurse"); + if ( -l "$target_dir/$recurse" ) { + DEBUG("removing symlink $target_dir/$recurse"); + unlink("$target_dir/$recurse"); + } + if ( !-d "$target_dir/$recurse" ) { + DEBUG("making directory $target_dir/$recurse"); + mkdir("$target_dir/$recurse"); + } + + my $recurse_options; + if ($install_only) { + $recurse_options = { + install_only => [ + map { s/^$recurse\///; $_ } + grep {/^$recurse/} @$install_only + ] + }; + } + install_files( "$source_dir/$recurse", "$target_dir/$recurse", $recurse_options ); + } + else { + WARN("couldn't recurse into $source_dir/$recurse, not a directory"); + } + } + + foreach my $execute ( @{ $dfm_install->{execute_files} } ) { + my $cwd = getcwd(); + + if ( -x "$source_dir/$execute" ) { + DEBUG("Executing $source_dir/$execute in $cwd"); + system("'$source_dir/$execute'"); + } + elsif ( -o "$source_dir/$execute" ) { + system("chmod +x '$source_dir/$execute'"); + + DEBUG("Executing $source_dir/$execute in $cwd"); + system("'$source_dir/$execute'"); + } + } + + foreach my $chmod_file ( keys %{ $dfm_install->{chmod_files} } ) { + my $new_perms = $dfm_install->{chmod_files}->{$chmod_file}; + + # TODO maybe skip if perms are already ok + DEBUG("Setting permissions on $chmod_file to $new_perms"); + chmod oct($new_perms), $chmod_file; + } + + # restore previous working directory + chdir($cwd_before_install); +} + +sub configure_shell_loader { + chdir($home); + + my $shellrc_contents = _read_shellrc_contents(); + + # check if the loader is in + if ( $shellrc_contents !~ /$shellrc_load_filename/ ) { + INFO("Appending loader to $shellrc_filename"); + $shellrc_contents .= "\n. \$HOME/$shellrc_load_filename\n"; + } + + # if the new loader filename (.shellrc.load) is used, but the old loader + # filename (.bashrc.load) is in the shell rc, remove it + if ( $shellrc_load_filename =~ m/shellrc/ && $shellrc_contents =~ /\.bashrc\.load/ ) { + $shellrc_contents =~ s{\n. \$HOME/\.bashrc\.load\n}{}gs; + } + + _write_shellrc_contents($shellrc_contents); +} + +sub uninstall_files { + my ( $source_dir, $target_dir ) = @_; + + DEBUG("Uninstalling from $target_dir"); + + my $backup_dir = $target_dir . '/.backup'; + DEBUG("Backup dir: $backup_dir"); + + chdir($target_dir); + + my $dfm_install = _load_dfminstall("$source_dir/.dfminstall"); + + my $dirh; + opendir $dirh, $target_dir; + foreach my $direntry ( readdir($dirh) ) { + + DEBUG(" Working on $direntry"); + + if ( -l $direntry ) { + my $link_target = readlink($direntry); + DEBUG("$direntry points a $link_target"); + my ( $volume, @elements ) = File::Spec->splitpath($link_target); + my $element = pop @elements; + + my $target_base + = realpath( File::Spec->rel2abs( File::Spec->catpath( '', @elements ) ) ); + + DEBUG( "target_base '", defined $target_base ? $target_base : '', "' $source_dir" ); + if ( defined $target_base and $target_base eq $source_dir ) { + INFO(" Removing $direntry ($link_target)."); + unlink($direntry) if !$opts{'dry-run'}; + } + + my $backup_path = File::Spec->catpath( '', '.backup', $element ); + if ( -e $backup_path ) { + INFO(" Restoring $direntry from backup."); + rename( $backup_path, $element ) if !$opts{'dry-run'}; + } + } + } + + foreach my $execute ( @{ $dfm_install->{execute_uninstall_files} } ) { + my $cwd = getcwd(); + + if ( -x "$source_dir/$execute" ) { + DEBUG("Executing $source_dir/$execute in $cwd"); + system("'$source_dir/$execute'"); + } + elsif ( -o "$source_dir/$execute" ) { + system("chmod +x '$source_dir/$execute'"); + + DEBUG("Executing $source_dir/$execute in $cwd"); + system("'$source_dir/$execute'"); + } + } + + foreach my $recurse ( @{ $dfm_install->{recurse_files} } ) { + if ( -d "$target_dir/$recurse" ) { + DEBUG("recursing into $target_dir/$recurse"); + uninstall_files( "$source_dir/$recurse", "$target_dir/$recurse" ); + } + else { + WARN("couldn't recurse into $target_dir/$recurse, not a directory"); + } + } +} + +sub relative_to_target { + my ( $tryfile, $target_dir ) = @_; + + if ( -l $tryfile ) { + my ( $volume, $dirs, $lfile ) = File::Spec->splitpath($tryfile); + return File::Spec->abs2rel( File::Spec->catfile( realpath($dirs), $lfile ), $target_dir ); + } + else { + return File::Spec->abs2rel( realpath($tryfile), $target_dir ); + } +} + +sub import_files { + my ( $source_dir, $target_dir, $files ) = @_; + + my $symlink_base = _calculate_symlink_base( $source_dir, $target_dir ); + + foreach my $file (@$files) { + + if ( $file =~ m{^/} ) { + $file = relative_to_target( $file, $target_dir ); + } + else { + my $tryfile = File::Spec->rel2abs($file); + + if ( -e $tryfile ) { + + #print "FOUND in cwd\n"; + $file = relative_to_target( $tryfile, $target_dir ); + } + else { + my $tryfile = File::Spec->rel2abs( $file, $target_dir ); + + if ( -e $tryfile ) { + + #print "FOUND in home\n"; + $file = relative_to_target( $tryfile, $target_dir ); + } + } + } + + if ( $file =~ /^\.\./ ) { + ERROR("file $file is not in your home directory"); + return; + } + + # if dfm import $HOME is called + if ( $file eq '.' ) { + ERROR("unable to import your home directory itself"); + return; + } + + if ( !-e "$target_dir/$file" ) { + ERROR("file $file not found, unable to import"); + return; + } + + DEBUG("file path, relative to homedir: $file"); + + my ( $in_a_subdir, $subdir ) + = _file_in_tracked_or_untracked( $source_dir, $source_dir, $file ); + if ( $in_a_subdir eq 'untracked' ) { + ERROR( + "file $file is in a subdirectory that is not tracked, consider using 'dfm import $subdir'." + ); + return; + } + elsif ( $in_a_subdir eq 'tracked' ) { + ERROR( + "file $file is in a subdirectory that is already tracked, consider using 'dfm add $subdir'." + ); + return; + } + elsif ( $in_a_subdir eq 'skip' ) { + ERROR("file $file is skipped."); + return; + } + + # detect file that's already tracked, either by being a symlink that + # points into the repo or in the repo itself + if (( -l "$target_dir/$file" + && ( readlink("$target_dir/$file") =~ /(\.\.\/)*$symlink_base/ ) + ) + || $file =~ /^$symlink_base/ + ) + { + ERROR("file $file is already tracked."); + return; + } + + } + + my $message = $opts{message} || "importing " . join( ', ', @$files ); + + foreach my $file (@$files) { + INFO( "Importing $file from $target_dir into $source_dir" + . ( $opts{'dry-run'} ? ' (dry run)' : '' ) ); + + DEBUG("moving $file into $source_dir"); + if ( !$opts{'dry-run'} ) { + move( "$target_dir/$file", "$source_dir/$file" ); + } + + if ( !$opts{'dry-run'} ) { + _run_git( 'add', $file ); + } + } + + install_files( _abs_repo_path( $home, $repo_dir ), $home, { install_only => [@$files] } ); + + INFO( "Committing with message '$message'" . ( $opts{'dry-run'} ? ' (dry run)' : '' ) ); + if ( !$opts{'dry-run'} ) { + if ( !$opts{'no-commit'} ) { + _run_git( 'commit', @$files, '-m', $message ); + } + } +} + +sub cleanup_dangling_symlinks { + my ( $source_dir, $target_dir, $skip_files ) = @_; + $skip_files ||= {}; + + DEBUG(" Cleaning up dangling symlinks in $target_dir"); + + my $dirh; + opendir $dirh, $target_dir; + foreach my $direntry ( readdir($dirh) ) { + + DEBUG(" Working on $direntry"); + + # if symlink is dangling or is now skipped + if ( -l $direntry && ( !-e $direntry || $skip_files->{$direntry} ) ) { + my $link_target = readlink($direntry); + DEBUG("$direntry points at $link_target"); + my ( $volume, @elements ) = File::Spec->splitpath($link_target); + my $element = pop @elements; + + my $target_base + = realpath( File::Spec->rel2abs( File::Spec->catpath( '', @elements ) ) ); + + DEBUG( "target_base '", defined $target_base ? $target_base : '', "' $source_dir" ); + if ( defined $target_base and $target_base eq $source_dir ) { + INFO(" Cleaning up dangling symlink $direntry ($link_target)."); + unlink($direntry) if !$opts{'dry-run'}; + } + } + } +} + +sub unconfigure_shell_loader { + chdir($home); + + my $shellrc_contents = _read_shellrc_contents(); + + # remove shell loader if found + $shellrc_contents =~ s{\n. \$HOME/$shellrc_load_filename\n}{}gs; + + _write_shellrc_contents($shellrc_contents); +} + +sub _write_shellrc_contents { + my $shellrc_contents = shift; + + if ( !$opts{'dry-run'} ) { + open( my $shellrc_out, '>', $shellrc_filename ); + print $shellrc_out $shellrc_contents; + close $shellrc_out; + } +} + +sub _read_shellrc_contents { + my $shellrc_contents; + { + local $INPUT_RECORD_SEPARATOR = undef; + if ( open( my $shellrc_in, '<', $shellrc_filename ) ) { + $shellrc_contents = <$shellrc_in>; + close $shellrc_in; + } + else { + $shellrc_contents = ''; + } + } + return $shellrc_contents; +} + +sub _run_git { + my @args = @_; + + my $cwd_before_git = getcwd(); + + DEBUG( 'running git ' . join( ' ', @args ) . " in $home/$repo_dir" ); + chdir( _abs_repo_path( $home, $repo_dir ) ); + system( 'git', @args ); + + chdir($cwd_before_git); +} + +sub _abs_repo_path { + my ( $home, $repo ) = @_; + + if ( File::Spec->file_name_is_absolute($repo) ) { + return $repo; + } + else { + return $home . '/' . $repo; + } +} + +# when symlinking from source_dir into target_dir, figure out if there's a +# relative path between the two +sub _calculate_symlink_base { + my ( $source_dir, $target_dir ) = @_; + + my $symlink_base; + + # if the paths have no first element in common + if ( ( File::Spec->splitdir($source_dir) )[1] ne ( File::Spec->splitdir($target_dir) )[1] ) { + $symlink_base = $source_dir; # use absolute path + } + else { + + # otherwise, calculate the relative path between the two directories + $symlink_base = File::Spec->abs2rel( $source_dir, $target_dir ); + } + + return $symlink_base; +} + +sub _file_in_tracked_or_untracked { + my ( $orig_source_dir, $source_dir, $file ) = @_; + + # strip the repo dir off the front, in case the file is already tracked + $file =~ s/$repo_dir\///; + + my $cwd_before_inspection = getcwd(); + chdir($source_dir); + + my $dfm_install = _load_dfminstall("$source_dir/.dfminstall"); + + # skip vim swap files + return ('skip') if $file =~ /.*\.sw.$/; + + # skip any other files + return ('skip') if $dfm_install->{skip_files}->{$file}; + + my @dirs = File::Spec->splitdir($file); + if ( scalar(@dirs) > 1 ) { + my $recurse_dir = shift(@dirs); + if ( grep { $recurse_dir eq $_ } @{ $dfm_install->{recurse_files} } ) { + chdir($cwd_before_inspection); + return _file_in_tracked_or_untracked( + $orig_source_dir, + File::Spec->catfile( $source_dir, $recurse_dir ), + File::Spec->catfile(@dirs) + ); + } + else { + my $relative_path = File::Spec->abs2rel( $source_dir, $orig_source_dir ); + + my $dir_type = -e $recurse_dir ? 'tracked' : 'untracked'; + + chdir($cwd_before_inspection); + return ( $dir_type, + ( $relative_path eq '.' ) + ? $recurse_dir + : File::Spec->catfile( $relative_path, $recurse_dir ) ); + } + } + + chdir($cwd_before_inspection); + return ('install'); +} + +sub _load_dfminstall { + my ($dfminstall_path) = @_; + + my $dfminstall_info = { + skip_files => { + '.' => 1, + '..' => 1, + '.dfminstall' => 1, + '.gitignore' => 1, + '.git' => 1, + }, + recurse_files => [], + execute_files => [], + execute_uninstall_files => [], + chmod_files => {}, + }; + + if ( -e $dfminstall_path ) { + open( my $skip_fh, '<', $dfminstall_path ); + foreach my $line (<$skip_fh>) { + chomp($line); + if ( length($line) ) { + my ( $filename, @options ) = split( q{ }, $line ); + DEBUG(".dfminstall file $filename has @options"); + if ( !defined $options[0] ) { + WARN( + "using implied recursion in .dfminstall is deprecated, change '$filename' to '$filename recurse' in $dfminstall_path." + ); + push( @{ $dfminstall_info->{recurse_files} }, $filename ); + $dfminstall_info->{skip_files}->{$filename} = 1; + } + elsif ( $options[0] eq 'skip' ) { + $dfminstall_info->{skip_files}->{$filename} = 1; + } + elsif ( $options[0] eq 'recurse' ) { + push( @{ $dfminstall_info->{recurse_files} }, $filename ); + $dfminstall_info->{skip_files}->{$filename} = 1; + } + elsif ( $options[0] eq 'exec' ) { + push( @{ $dfminstall_info->{execute_files} }, $filename ); + } + elsif ( $options[0] eq 'exec-uninstall' ) { + push( @{ $dfminstall_info->{execute_uninstall_files} }, $filename ); + } + elsif ( $options[0] eq 'chmod' ) { + if ( !$options[1] ) { + ERROR("chmod option requires a mode (e.g. 0600) in $dfminstall_path"); + exit 1; + } + if ( $options[1] !~ /^[0-7]{4}$/ ) { + ERROR( + "bad mode '$options[1]' (should be 4 digit octal, like 0600) in $dfminstall_path" + ); + exit 1; + } + $dfminstall_info->{chmod_files}->{$filename} + = $options[1]; + } + } + } + close($skip_fh); + $dfminstall_info->{skip_files}->{skip} = 1; + + DEBUG("Skipped file: $_") for keys %{ $dfminstall_info->{skip_files} }; + } + + return $dfminstall_info; +} + +sub show_version { + print "dfm version $VERSION\n"; +} + +# work-alike for function from perl 5.8.9 and later +# added for compatibility with CentOS 5, which is stuck on 5.8.8 +sub GetOptionsFromArray { + my ( $argv, $opts, @options ) = @_; + + local @ARGV = @$argv; + GetOptions( $opts, @options ); + + # update the passed argv array + @$argv = @ARGV; +} + +1; + +__END__ + +=head1 NAME + + dfm - A script to manage a dotfiles repository + +=head1 SYNOPSIS + +usage: dfm [--version] [--dry-run] [--verbose] [--quiet] [] + +The commands are: + + install Install dotfiles + import Add a new dotfile to the repo + uninstall Uninstall dotfiles + updates Fetch updates but don't merge them in + mi Merge in updates and install dotfiles again + umi Fetch updates, merge in and install + +See 'dfm help ' for more information on a specific command. + +Any git command can be run on the dotfiles repository by using the following +syntax: + + dfm [git subcommand] [git options] + +=head1 DESCRIPTION + + Manages installing files from and operating on a repository that contains + dotfiles. + +=head1 COMMON OPTIONS + +All the subcommands implemented by dfm have the following options: + + --verbose Show extra information about what dfm is doing + --quiet Show as little info as possible. + --dry-run Don't do anything. + --version Print version information. + +=head1 HELP + +All Options: + + dfm help + dfm --help + +Examples: + + dfm install --help + dfm help install + +Description: + +This shows the help for a particular subcommand. + +=head1 INSTALL + +All Options: + + dfm install [--verbose|--quiet] [--dry-run] + +Examples: + + dfm install + dfm install --dry-run + +Description: + +This installs everything in the repository into the current user's home +directory by making symlinks. To skip any files, add their names to a file +named '.dfminstall'. For instance, to skip 'README.md', put this in +.dfminstall: + + README.md skip + +To recurse into a directory and install files inside rather than symlinking the +directory itself, just add its name to .dfminstall. For instance, to make 'dfm +install' symlink files inside of ~/.ssh instead of making ~/.ssh a symlink, put +this in .dfminstall: + + .ssh + +=head1 UNINSTALL + +All Options: + + dfm uninstall [--verbose|--quiet] [--dry-run] + - or - + dfm un [--verbose|--quiet] [--dry-run] + +Examples: + + dfm uninstall + dfm uninstall --dry-run + +Description: + +This removes all traces of dfm and the dotfiles. It basically is the reverse +of 'dfm install'. + +=head1 IMPORT + +All Options: + + dfm import [--verbose|--quiet] [--dry-run] [--no-commit] [--message ] file1 [file2 ..] + - or - + dfm im [--verbose|--quiet] [--dry-run] [--no-commit] [--message ] file1 [file2 ..] + +Examples + + dfm import ~/.vimrc + dfm import .tmux.conf --message 'adding my tmux config' + +Description: + +This command moves each file specified into the dotfiles repository and +symlinks it into $HOME. Then a commit is made. + +Use '--message' to specify a different commit message. + +Use '--no-commit' to add the files, but not commit. + +=head1 UPDATES + +All Options: + + dfm updates [--verbose|--quiet] [--dry-run] [--no-fetch] + +Examples: + + dfm updates + dfm updates --no-fetch + +Description: + +This fetches any changes from the upstream remote and then shows a shortlog of +what updates would come in if merged into the current branch. Use '--no-fetch' +to skip the fetch and just show what's new. + +=head1 MERGEANDINSTALL + +All Options: + + dfm mergeandinstall [--verbose|--quiet] [--dry-run] [--merge|--rebase] + - or - + dfm mi [--verbose|--quiet] [--dry-run] [--merge|--rebase] + +Examples: + + dfm mergeandinstall + dfm mi + dfm mergeandinstall --rebase + +Description: + +This merges or rebases the upstream changes in and re-installs dotfiiles. + +=head1 UPDATEMERGEANDINSTALL + +All Options: + + dfm updatemergeandinstall [--verbose|--quiet] [--dry-run] [--merge|--rebase] [--no-fetch] + - or - + dfm umi [--verbose|--quiet] [--dry-run] [--merge|--rebase] [--no-fetch] + +Examples: + + dfm updatemergeandinstall + dfm umi + dfm updatemergeandinstall --no-fetch + +Description: + +This combines 'updates' and 'mergeandinstall'. + +=head1 dfm [git subcommand] [git options] + +This runs any git command as if it was inside the dotfiles repository. For +instance, this makes it easy to commit changes that are made by running 'dfm +commit'. + +=head1 AUTHOR + +Nate Jones + +=head1 COPYRIGHT + +Copyright (c) 2010 L as listed above. + +=head1 LICENSE + +This program is free software distributed under the Artistic License 2.0. + +=cut \ No newline at end of file