linux

Linux Development Environment Deployment

Posted on 2020-07-28,27 min read

Usage

➜  linux_environment git:(master) ✗ ./setup.bash --help
=================================================================================================
        ███████╗███╗   ██╗██╗   ██╗    ██████╗ ███████╗██████╗ ██╗      ██████╗ ██╗   ██╗
        ██╔════╝████╗  ██║██║   ██║    ██╔══██╗██╔════╝██╔══██╗██║     ██╔═══██╗╚██╗ ██╔╝
        █████╗  ██╔██╗ ██║██║   ██║    ██║  ██║█████╗  ██████╔╝██║     ██║   ██║ ╚████╔╝
        ██╔══╝  ██║╚██╗██║╚██╗ ██╔╝    ██║  ██║██╔══╝  ██╔═══╝ ██║     ██║   ██║  ╚██╔╝
        ███████╗██║ ╚████║ ╚████╔╝     ██████╔╝███████╗██║     ███████╗╚██████╔╝   ██║
        ╚══════╝╚═╝  ╚═══╝  ╚═══╝      ╚═════╝ ╚══════╝╚═╝     ╚══════╝ ╚═════╝    ╚═╝
=================================================================================================
Usage: ./setup.bash [options]
Configure development environment for linux system
Options:
    -d, --distribution       linux distribution ([debian|redhat] series)
    -u, --username           set user name for git
    -e, --email              set email for git
    -p, --password           password for root
    -h, --help               Script help information

example

./setup.sh -d ubuntu -u username -e xxx@email.com -p password

Script

#!/bin/bash
#
# Configure development environment for linux system

# set -euxo pipefail

distro="fedora"
# for git configuration
username=""
email=""
# for automation
password=""

function info() {
  echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $@" >&2
}

function auto()
{
	expect_file=$(mktemp /tmp/expect-script.XXXXXX)
	cat > ${expect_file} << EOF
set timeout -1
match_max 100000
spawn $@
expect -exact "password"
send -- "${password}\r"
expect eof
EOF
	expect -f ${expect_file}
	rm -rf ${expect_file}
}

function install_automation_tool()
{
	which expect
	if [[ $? -eq 0 ]]; then
		return
	fi

	if [[ ${distro} == "ubuntu" ]] || [[ ${distro} == "debian" ]]; then
		sudo apt update  -y
		sudo apt install -y expect
	elif [[ ${distro} == "fedora" ]] || [[ ${distro} == "centos" ]]; then
		sudo dnf upgrade -y
		sudo dnf install -y expect
	else
		echo "Unsupport other linux distro other than debian and redhat series"
	fi
}

function install_common_tools_for_debian_series()
{
	auto sudo apt update  -y
	auto sudo apt upgrade -y

	auto sudo apt install -y silversearcher-ag fd-find bat ccze git tig cmatrix screenfetch universal-ctags
	auto sudo apt install -y fzf glances tmux shellcheck ranger aria2 axel cloc taskwarrior jq zsh npm
	auto sudo apt install -y neovim cscope global python3-pip ca-certificates gdebi

	auto sudo apt install -y build-essential nodejs golang clangd ruby-dev clang llvm
	auto sudo apt install -y manpages-dev man-db manpages-posix-dev
	auto sudo apt install -y libtool automake autoconf cmake pkgconf cmake
	auto sudo apt install -y valgrind gdb gdbserver tcpdump systemtap ltrace strace
}

function install_common_tools_for_redhat_series()
{
	auto sudo dnf upgrade -y

	auto sudo dnf install -y the_silver_searcher fd-find bat exa ccze git tig cmatrix screenfetch ctags 
	auto sudo dnf install -y fzf glances tmux ShellCheck ranger aria2 axel cloc task jq zsh npm
	auto sudo dnf install -y neovim cscope global python3-pip ca-certificates

	auto dnf install -y nodejs golang clang llvm ruby-devel
	auto dnf install -y valgrind gdb gdb-gdbserver tcpdump systemtap ltrace strace
	auto dnf group install -y 'Development Tools' 
	auto dnf install -y gcc gcc-c++ rpm-build rpm-devel rpmlint make python bash coreutils diffutils patch rpmdevtools
}

function install_common_tools()
{
	if [[ ${distro} == "ubuntu" ]] || [[ ${distro} == "debian" ]]; then
		install_common_tools_for_debian_series
	elif [[ ${distro} == "fedora" ]] || [[ ${distro} == "centos" ]]; then
		install_common_tools_for_redhat_series
	else
		echo "Unsupport other linux distro other than debian and redhat series"
	fi
}

function write_git_commit_template()
{
	cat << EOF > ${1}
# [<tag>] (If applied, this commit will...) <subject> (Max 72 char)
# |<----   Preferably using up to 50 chars   --->|<------------------->|
# Example:
# [feat] Implement automated commit messages

# (Optional) Explain why this change is being made
# |<----   Try To Limit Each Line to a Maximum Of 72 Characters   ---->|

# (Optional) Provide links or keys to any relevant tickets, articles or other resources
# Example: Github issue #23

# --- COMMIT END ---
# Tag can be 
#    feat     (new feature)
#    fix      (bug fix)
#    refactor (refactoring code)
#    style    (formatting, missing semi colons, etc; no code change)
#    doc      (changes to documentation)
#    test     (adding or refactoring tests; no production code change)
#    version  (version bump/new release; no production code change)
#    jsrXXX   (Patches related to the implementation of jsrXXX, where XXX the JSR number)
#    jdkX     (Patches related to supporting jdkX as the host VM, where X the JDK version)
#    dbg      (Changes in debugging code/frameworks; no production code change)
#    license  (Edits regarding licensing; no production code change)
#    hack     (Temporary fix to make things move forward; please avoid it)
#    WIP      (Work In Progress; for intermediate commits to keep patches reasonably sized)
#    defaults (changes default options)
#
# Note: Multiple tags can be combined, e.g. [fix][jsr292] Fix issue X with methodhandles
# --------------------
# Remember to:
#   * Capitalize the subject line
#   * Use the imperative mood in the subject line
#   * Do not end the subject line with a period
#   * Separate subject from body with a blank line
#   * Use the body to explain what and why vs. how
#   * Can use multiple lines with "-" or "*" for bullet points in body
# --------------------
EOF
}

function configure_git_diff()
{
	# npm config get registry

	auto sudo npm config set registry https://registry.npm.taobao.org
	auto sudo npm install -g diff-so-fancy

	git config --global core.pager "diff-so-fancy | less --tabs=4 -RFX"
	git config --global color.ui true
	git config --global color.diff-highlight.oldNormal    "red bold"
	git config --global color.diff-highlight.oldHighlight "red bold 52"
	git config --global color.diff-highlight.newNormal    "green bold"
	git config --global color.diff-highlight.newHighlight "green bold 22"

	git config --global color.diff.meta       "11"
	git config --global color.diff.frag       "magenta bold"
	git config --global color.diff.commit     "yellow bold"
	git config --global color.diff.old        "red bold"
	git config --global color.diff.new        "green bold"
	git config --global color.diff.whitespace "red reverse"
	git config --bool --global diff-so-fancy.markEmptyLines false
	git config --bool --global diff-so-fancy.changeHunkIndicators false
	git config --bool --global diff-so-fancy.stripLeadingSymbols false
	git config --bool --global diff-so-fancy.useUnicodeRuler false
	# git log's commit header width
	git config --global diff-so-fancy.rulerWidth 47
}

function configure_git()
{
	git config --global user.name ${username}
	git config --global user.email ${email}
	git config --global http.sslVerify false
	git config --global core.editor nvim
	# for mac or linux
	git config --global core.autocrlf input
	# for windows
	# git config --global core.autocrlf false

	write_git_commit_template ~/.git-commit-template.txt
	git config --global commit.template ~/.git-commit-template.txt

	configure_git_diff
}

function auto_install_zsh()
{
	expect_file=$(mktemp /tmp/expect-script.XXXXXX)
	cat > ${expect_file} << EOF
set timeout -1
match_max 100000
spawn $@
expect -exact "Y/n"
send "Y\r"
expect -exact "Password"
send -- "${password}\r"
expect eof
EOF
	expect -f ${expect_file}
	rm -rf ${expect_file}
}

function configure_terminal()
{
	# terminal configuration
	if [[ -d ~/.oh-my-zsh ]]; then
		rm -rf ~/.oh-my-zsh
	fi

	wget --no-check-certificate https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O on-my-zsh-install.sh
	if [[ $? -ne 0 ]]; then
		curl -fksSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -o on-my-zsh-install.sh
	fi

	auto_install_zsh sh on-my-zsh-install.sh 
	rm -rf on-my-zsh-install.sh
	git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
	git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
	git clone https://github.com/zsh-users/zsh-history-substring-search ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search
	git clone https://github.com/chrissicool/zsh-256color ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-256color
	sed -i 's/fg=8/fg=3/g' ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
	sed -i 's/plugins=(git)/plugins=(git zsh-autosuggestions extract zsh-syntax-highlighting history-substring-search history zsh-256color vi-mode z wd taskwarrior)/g' ~/.zshrc
	cat << EOF >> ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh
bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down
EOF
}

function alias_vim()
{
	cat << EOF >> ~/.zshrc
alias vi='nvim'
alias vim='nvim'
EOF
}

function configure_npm_source()
{
	mkdir -p ~/.pip
	cat << EOF > ~/.pip/pip.conf
[global]
index-url = https://mirrors.aliyun.com/pypi/simple
EOF
}

function language_support_vim()
{
  	configure_npm_source
	npm config set registry https://registry.npm.taobao.org
	yarn config set registry https://registry.npm.taobao.org
	gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
	auto sudo npm install --global yarn

	# curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
	axel -n 5 https://bootstrap.pypa.io/get-pip.py
	auto sudo python2 get-pip.py
	rm get-pip.py
	auto sudo pip2 install --no-cache-dir --upgrade --force-reinstall neovim # -i https://pypi.tuna.tsinghua.edu.cn/simple
	auto sudo pip3 install --no-cache-dir --upgrade --force-reinstall neovim # -i https://pypi.tuna.tsinghua.edu.cn/simple
	auto sudo npm install -g neovim
	auto sudo gem install neovim
}

function customize_spacevim_configuration()
{
	if [[ -f ~/.SpaceVim.d/init.toml ]]; then
		mv ~/.SpaceVim.d/init.toml ~/.SpaceVim.d/init.toml.bak
	fi
	mkdir -p ~/.SpaceVim.d
	cat << EOF > ~/.SpaceVim.d/init.toml
[options]
    # set spacevim theme. by default colorscheme layer is not loaded,
    # if you want to use more colorscheme, please load the colorscheme
    # layer
    # colorscheme = "gruvbox"
    colorscheme = "NeoSolarized"
    colorscheme_bg = "dark"
    # Disable guicolors in basic mode, many terminal do not support 24bit
    # true colors
    enable_guicolors = true
    # Disable statusline separator, if you want to use other value, please
    # install nerd fonts
    statusline_separator = "arrow"
    statusline_inactive_separator = "bar"
    buffer_index_type = 4
    windows_index_type = 3
    enable_statusline_mode = true
     # left sections of statusline
    statusline_left_sections = [
       'winnr',
       'major mode',
       'filename',
       'fileformat',
       'minor mode lighters',
       'version control info',
       'search status'
    ]
    # right sections of statusline
    statusline_right_sections = [
       'cursorpos',
       'percentage',
       'input method',
       'date',
       'time'
    ]

    enable_tabline_filetype_icon = true
    enable_statusline_display_mode = true
    statusline_unicode_symbols = true
    realtime_leader_guide = 1
    enable_statusline_tag = true
    # Enable vim compatible mode, avoid changing origin vim key bindings
    vimcompatible = true
    automatic_update = true
    enable_neomake = false
    filemanager = "defx"

[[custom_plugins]]
	name = 'neoclide/coc.nvim'
	merge = 0
	build =  'yarn install --frozen-lockfile'
	# branch = 'release'

[[layers]]
	name = 'shell'
	default_position = 'right'

[[layers]]
	name = "VersionControl"
	enable-gtm-status = true

[[layers]]
	name = "checkers"
	show_cursor_error = false

[[layers]]
	name = "colorscheme"

[[layers]]
	name = "git"
	git-plugin = "fugitive"

[[layers]]
	name = "tmux"

[[layers]]
	name = "leaderf"

[[layers]]
	name = "sudo"

[[layers]]
	name = "tags"

[[layers]]
	name = "tools"

[[layers]]
	name = 'core'
EOF
}

function configure_init_vim()
{
	cat << EOF >> ~/.SpaceVim/init.vim
set tabstop=4
set expandtab
set shiftwidth=4
nnoremap <F9> :set invpaste paste?<CR>
set pastetoggle=<F9>
set showmode
set cmdheight=1

let g:coc_global_extensions = ['coc-json','coc-clangd','coc-cmake','coc-explorer','coc-fzf-preview','coc-python','coc-spell-checker','coc-template','coc-go']
" let g:EasyMotion_do_mapping = 1

" filetype plugin indent on
" syntax enable
"
" Default value is "normal", Setting this option to "high" or "low" does use the
" same Solarized palette but simply shifts some values up or down in order to
" expand or compress the tonal range displayed.
let g:neosolarized_contrast = "normal"

" Special characters such as trailing whitespace, tabs, newlines, when displayed
" using ":set list" can be set to one of three levels depending on your needs.
" Default value is "normal". Provide "high" and "low" options.
let g:neosolarized_visibility = "normal"

" I make vertSplitBar a transparent background color. If you like the origin
" solarized vertSplitBar style more, set this value to 0.
let g:neosolarized_vertSplitBgTrans = 1

" If you wish to enable/disable NeoSolarized from displaying bold, underlined
" or italicized" typefaces, simply assign 1 or 0 to the appropriate variable.
" Default values:
let g:neosolarized_bold = 1
let g:neosolarized_underline = 1
let g:neosolarized_italic = 0

" Used to enable/disable "bold as bright" in Neovim terminal. If colors of bold
" text output by commands like `ls` aren't what you expect, you might want to
" try disabling this option. Default value:
let g:neosolarized_termBoldAsBright = 1

" TextEdit might fail if hidden is not set.
set hidden

" Some servers have issues with backup files, see #649.
set nobackup
set nowritebackup

" Give more space for displaying messages.
set cmdheight=2

" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
" delays and poor user experience.
set updatetime=300

" Don't pass messages to |ins-completion-menu|.
set shortmess+=c

" Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved.
if has("patch-8.1.1564")
  " Recently vim can merge signcolumn and number column into one
  set signcolumn=number
else
  set signcolumn=yes
endif

" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
      \ pumvisible() ? "\<C-n>" :
      \ <SID>check_back_space() ? "\<TAB>" :
      \ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"

function! s:check_back_space() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction

" Use <c-space> to trigger completion.
if has('nvim')
  inoremap <silent><expr> <c-space> coc#refresh()
else
  inoremap <silent><expr> <c-@> coc#refresh()
endif

" Use <cr> to confirm completion, `<C-g>u` means break undo chain at current
" position. Coc only does snippet and additional edit on confirm.
" <cr> could be remapped by other vim plugin, try `:verbose imap <CR>`.
if exists('*complete_info')
  inoremap <expr> <cr> complete_info()["selected"] != "-1" ? "\<C-y>" : "\<C-g>u\<CR>"
else
  inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
endif

" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)

" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)

" Use K to show documentation in preview window.
nnoremap <silent> K :call <SID>show_documentation()<CR>

function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  else
    call CocAction('doHover')
  endif
endfunction

" Highlight the symbol and its references when holding the cursor.
autocmd CursorHold * silent call CocActionAsync('highlight')

" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)

" Formatting selected code.
xmap <leader>f  <Plug>(coc-format-selected)
nmap <leader>f  <Plug>(coc-format-selected)

augroup mygroup
  autocmd!
  " Setup formatexpr specified filetype(s).
  autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
  " Update signature help on jump placeholder.
  autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end

" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a  <Plug>(coc-codeaction-selected)
nmap <leader>a  <Plug>(coc-codeaction-selected)

" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac  <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf  <Plug>(coc-fix-current)

" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)

" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of LS, ex: coc-tsserver
nmap <silent> <C-s> <Plug>(coc-range-select)
xmap <silent> <C-s> <Plug>(coc-range-select)

" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocAction('format')

" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call     CocAction('fold', <f-args>)

" Add `:OR` command for organize imports of the current buffer.
command! -nargs=0 OR   :call     CocAction('runCommand', 'editor.action.organizeImport')

" Add (Neo)Vim's native statusline support.
" NOTE: Please see `:h coc-status` for integrations with external plugins that
" provide custom statusline: lightline.vim, vim-airline.
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}

" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a  :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e  :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c  :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o  :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s  :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j  :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k  :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p  :<C-u>CocListResume<CR>
EOF
}

function set_background_translucent()
{
	cat << EOF >> ${HOME}/.SpaceVim/config/init.vim
func! s:transparent_background()
    highlight Normal guibg=None ctermbg=None
    highlight NonText guibg=None ctermbg=None
endf
autocmd ColorScheme * call s:transparent_background()
EOF
}

function install_spacevim()
{
	curl -sLf https://spacevim.org/install.sh | bash -s -- --install neovim
	customize_spacevim_configuration
	configure_init_vim
	set_background_translucent
}

function configure_coc_plugins()
{
	echo "TODO: coc"
	# Reference:
	# https://github.com/neoclide/coc.nvim
	# https://github.com/neoclide/coc.nvim/wiki
	# https://clangd.llvm.org/
	#
	# cd ~/.cache/vimfiles/repos/github.com/neoclide/coc.nvim
	# git clean -xfd
	# yarn install --frozen-lockfile
	# coc-clangd coc-cmake coc-sh coc-go coc-python coc-explorer coc-highlight 
	rm -rf $(find ~ -name 'deoplete*')
	sed -i "s/let g:spacevim_autocomplete_method = 'deoplete'/let g:spacevim_autocomplete_method = 'coc'/g" ${HOME}/.SpaceVim/autoload/SpaceVim.vim
}

function configure_vim()
{
	# vim configuration
	alias_vim
	language_support_vim
	install_spacevim
	configure_coc_plugins
}

function customize_fzf_configuration()
{
	cat << EOF >> ~/.zshrc
alias fd=fdfind
export FZF_DEFAULT_COMMAND='fd --hidden --follow -E ".git" -E "node_modules" . /etc /home'
export FZF_DEFAULT_OPTS='--height 90% --layout=reverse --bind=alt-j:down,alt-k:up,alt-i:toggle+down --border --preview "(bat --style=numbers --color=always {}) 2> /dev/null | head -500" --preview-window=down'

# Use ~~ as the trigger sequence instead of the default **
export FZF_COMPLETION_TRIGGER='~~'

# Options to fzf command
export FZF_COMPLETION_OPTS='+c -x'

# Use fd (https://github.com/sharkdp/fd) instead of the default find
# command for listing path candidates.
# - The first argument to the function ($1) is the base path to start traversal
# - See the source code (completion.{bash,zsh}) for the details.
_fzf_compgen_path() {
	fd --hidden --follow --exclude ".git" . "$1"
}

# Use fd to generate the list for directory completion
_fzf_compgen_dir() {
	fd --type d --hidden --follow --exclude ".git" . "$1"
}

# (EXPERIMENTAL) Advanced customization of fzf options via _fzf_comprun function
# - The first argument to the function is the name of the command.
# - You should make sure to pass the rest of the arguments to fzf.
_fzf_comprun() {
  local command=$1
  shift

  case "$command" in
    cd)           fzf "$@" --preview 'tree -C {} | head -200' ;;
    export|unset) fzf "$@" --preview "eval 'echo \$'{}" ;;
    ssh)          fzf "$@" --preview 'dig {}' ;;
    *)            fzf "$@" ;;
  esac
}
EOF
}

function configure_fzf()
{
	# set command-line fuzzer finder
	rm -rf ~/.fzf
	git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
	alias curl='curl -k'
	expect_file=$(mktemp /tmp/expect-script.XXXXXX)
	cat > ${expect_file} << EOF
set timeout -1
match_max 100000
spawn bash ${HOME}/.fzf/install
expect -exact "\[y\]/n"
send -- "y\r"
expect -exact "\[y\]/n"
send -- "y\r"
expect -exact "\[y\]/n"
send -- "y\r"
expect eof
EOF
	expect -f ${expect_file}
	rm -rf ${expect_file}
	customize_fzf_configuration
}

function support_true_color_for_terminal()
{
	# terminal true-color support
	if [[ $(tput colors) -ne 256 ]]; then
		cat << EOF >> /etc/profile
case "$TERM" in
	xterm)
		export TERM=xterm-256color
		;;
	screen)
		export TERM=screen-256color
		;;
esac
EOF
	fi

	awk 'BEGIN{
	    s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
	    for(colnum=0; colnum<77; colnum++) {
		r = 255-(colnum*255/76);
		g = (colnum*510/76);
		b = (colnum*255/76);
		if (g>255) g = 510-g;
		printf "\033[48;2;%d;%d;%dm", r,g,b;
		printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
		printf "%s\033[0m", substr(s,colnum+1,1);
	    }
	    printf "\n";
	}'

	for T in $(find /usr/share/terminfo -type f -printf '%f '); do echo "$T $(tput -T $T colors)"; done | sort -nk2 | tail -n20
}

function configure_tmux()
{
	# tmux configuration
	cd ${HOME}
	rm -rf ${HOME}/.tmux
	git clone https://github.com/gpakosz/.tmux.git ${HOME}/.tmux
	rm -rf ${HOME}/.tmux.conf
	ln -s -f ${HOME}/.tmux/.tmux.conf
	rm -rf ${HOME}/.tmux.conf.local
	cp ${HOME}/.tmux/.tmux.conf.local .
	echo "export EDITOR='vim'" >> ~/.zshrc

	auto sudo gem install tmuxinator
	
	cd ${HOME}/.tmux
	mkdir plugins
	git clone https://github.com/tmux-plugins/tmux-resurrect.git
	cd ${HOME}/.tmux/plugins
	git clone https://github.com/tmux-plugins/tmux-continuum.git

	rm -rf ~/.bin/.tmuxinator.zsh
	echo "source ~/.bin/.tmuxinator.zsh" >> ${HOME}/.zshrc
	mkdir -p ${HOME}/.bin
	# should escaping \$
	cat << EOF > ${HOME}/.bin/.tmuxinator.zsh
#compdef _tmuxinator tmuxinator

_tmuxinator() {
  local commands projects
  commands=(\${(f)"\$(tmuxinator commands zsh)"})
  projects=(\${(f)"\$(tmuxinator completions start)"})

  if (( CURRENT == 2 )); then
    _alternative \
      'commands:: _describe -t commands "tmuxinator subcommands" commands' \
      'projects:: _describe -t projects "tmuxinator projects" projects'
  elif (( CURRENT == 3)); then
    case \$words[2] in
      copy|cp|c|debug|delete|rm|open|o|start|s|edit|e)
        _arguments '*:projects:(\$projects)'
      ;;
    esac
  fi

  return
}

complete -F _tmuxinator tmuxinator mux
alias mux="tmuxinator"
# Local Variables:
# mode: Shell-Script
# sh-indentation: 2
# indent-tabs-mode: nil
# sh-basic-offset: 2
# End:
# vim: ft=zsh sw=2 ts=2 et
EOF

	cat << EOF >> ${HOME}/.tmux.conf.local
set -g mouse on
set -g status-keys vi
set -g mode-keys vi

# replace C-b by C-a instead of using both prefixes
set-option -g prefix2 \` 

unbind '"'
bind - splitw -v
unbind %
bind | splitw -h
# move status line to top
set -g status-position bottom

run-shell ~/.tmux/plugins/tmux-resurrect/resurrect.tmux
run-shell ~/.tmux/plugins/tmux-continuum/continuum.tmux
set -g @continuum-save-interval '1440'
set -g @continuum-restore 'on'
bind C-c run " tmux save-buffer - | xclip -i -sel clipboard"
bind C-v run " tmux set-buffer "\$(xclip -o -sel clipboard)"; tmux paste-buffer"
EOF
}

function set_development_environment()
{
	# set c/c++ development environment
	cat << EOF >> ${HOME}/.zshrc
export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig
mkdir -p /corefile
ulimit -c unlimited
echo "1" > /proc/sys/kernel/core_uses_pid
echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
EOF

	# TODO
	auto sudo sh -c 'echo /usr/local/lib >> /etc/ld.so.conf'
	auto sudo sh -c 'echo /usr/local/lib64 >> /etc/ld.so.conf'
}

function usage() {
    echo -e "\
=================================================================================================\033[1;37m
	███████╗███╗   ██╗██╗   ██╗    ██████╗ ███████╗██████╗ ██╗      ██████╗ ██╗   ██╗
	██╔════╝████╗  ██║██║   ██║    ██╔══██╗██╔════╝██╔══██╗██║     ██╔═══██╗╚██╗ ██╔╝
	█████╗  ██╔██╗ ██║██║   ██║    ██║  ██║█████╗  ██████╔╝██║     ██║   ██║ ╚████╔╝ 
	██╔══╝  ██║╚██╗██║╚██╗ ██╔╝    ██║  ██║██╔══╝  ██╔═══╝ ██║     ██║   ██║  ╚██╔╝  
	███████╗██║ ╚████║ ╚████╔╝     ██████╔╝███████╗██║     ███████╗╚██████╔╝   ██║   
	╚══════╝╚═╝  ╚═══╝  ╚═══╝      ╚═════╝ ╚══════╝╚═╝     ╚══════╝ ╚═════╝    ╚═╝   \033[0m 
================================================================================================="
  echo "Usage: $0 [options]"
  echo "Configure development environment for linux system"
  echo "Options:"
  echo "    -d, --distribution       linux distribution ([debian|redhat] series)" 
  echo "    -u, --username           set user name for git" 
  echo "    -e, --email              set email for git" 
  echo "    -p, --password           password for root" 
  echo "    -h, --help               Script help information"
}

function main()
{
	args=`getopt -o d:u:e:p:h --long distribution:,username:,email:,password:,help -- "$@"`
	if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
	eval set -- "$args"
	
	while true; do
		case "$1" in
    			-d|--distribution)      distro="$2"; shift 2;;
    			-u|--username)          username="$2"; shift 2;;
    			-e|--email)             email="$2"; shift 2;;
    			-p|--password)          password="$2"; shift 2;;
    			-h|--help)              usage ; exit 0 ;;
    			--)                     shift ; break ;;
    			*)                      err "invalid parameter" ; exit -1 ;;
  		esac
	done
	
	if [[ -z ${distro} ]] || [[ -z ${password} ]]; then
		echo "distribution and password requried"
	fi
	info "Starting set deployment environment for linux..."
	whoami
	install_automation_tool
	install_common_tools
	configure_git
	configure_terminal
	configure_vim
	configure_fzf
	support_true_color_for_terminal
	configure_tmux
	set_development_environment
}

main $@

下一篇: Issue Template→