Skip to content

Latest commit

ย 

History

History
3224 lines (2830 loc) ยท 96.7 KB

dotfiles.org

File metadata and controls

3224 lines (2830 loc) ยท 96.7 KB

Dotfile

README

็”Ÿๆˆ README.md

# Dotfiles
[![Build Status](https://www.travis-ci.com/teddy-ma/dotfiles.svg?branch=master)](https://www.travis-ci.com/teddy-ma/dotfiles)

่ฟ™ๆ˜ฏๆˆ‘็š„ `dotfiles`,  ไฝฟ็”จ Emacs ่ฟ›่กŒ็ฎก็†, ๆ”ฏๆŒ macOS ไธŽ Linux

# Install

ๅฎŒๆˆไธ‹้ขๆ‰€ๅ†™็š„ๅ‡†ๅค‡ๅทฅไฝœๅŽ๏ผŒๅช่ฆๆ‰“ๅผ€ Emacs, ็ญ‰ๅพ…้…็ฝฎๅฎŒๆˆ๏ผŒ่พ“ๅ…ฅ `C-i` ๆ‰“ๅผ€้…็ฝฎ `dotfiles.org` ๆ–‡ไปถ๏ผŒ
ไฝฟ็”จ `C-c C-v t` ๅฐฑ่ƒฝ็”Ÿๆˆๅ„็ง dotfiles ไบ†ใ€‚ `C-c C-v C-b` ๅฏไปฅๆ‰ง่กŒ shell ๅ‘ฝไปคใ€‚

## macOS prepare

macOS ไธป่ฆไพ่ต– [homebrew](https://brew.sh) ๅŒ…็ฎก็†ๅทฅๅ…ท๏ผŒ็„ถๅŽ้…ๅˆ Dropbox ไธŠๅ‚จๅญ˜็š„็งๆœ‰้…็ฝฎๆ–‡ไปถๅฎŒๆˆ้…็ฝฎใ€‚

  ```shell
  brew install fish dropbox curl

  chsh -s /usr/local/bin/fish

  git clone [email protected]:teddy-ma/dotfiles.git ~/.emacs.d
  ```

## Linux prepare

Linux ไธ‹ๅช้œ€่ฆๅฎ‰่ฃ…ๅ‡ ไธชๆœ€ๅŸบ็ก€็š„ๅŒ…

  ```shell
  sudo pacman -Syu git fish ttf-inconsolata ttf-arphic-uming fzf

  git clone [email protected]:teddy-ma/dotfiles.git ~/.emacs.d/
  ```

shell

fish

Setup scripts

echo /usr/local/bin/fish | sudo tee -a /etc/shells # macOS
chsh -s /usr/bin/fish # Linux

curl -sL https://git.io/fisher | source
fisher install jethrokuan/fzf
fisher install jethrokuan/z
fisher install franciscolourenco/done

Color setting

set TERM "xterm-256color"

set fish_color_normal normal
set fish_color_command 005fd7
set fish_color_quote 999900
set fish_color_redirection 00afff
set fish_color_end 009900
set fish_color_error ff0000
set fish_color_param 00afff
set fish_color_comment 990000
set fish_color_match --background=brblue
set fish_color_selection white --bold --background=brblack
set fish_color_search_match bryellow --background=brblack
set fish_color_history_current --bold
set fish_color_operator 00a6b2
set fish_color_escape 00a6b2
set fish_color_cwd green
set fish_color_cwd_root red
set fish_color_valid_path --underline
set fish_color_autosuggestion 555 brblack
set fish_color_user brgreen
set fish_color_host normal
set fish_color_cancel -r
set fish_pager_color_completion normal
set fish_pager_color_description B3A06D yellow
set fish_pager_color_prefix white --bold --underline
set fish_pager_color_progress brwhite --background=cyan

Path and source (macOS)

source /usr/local/opt/asdf/asdf.fish
mcfly init fish | source
fish_add_path ~/.cargo/bin
fish_add_path ~/.local/share/solana/install/active_release/bin

Path and source (Linux)

source /opt/asdf-vm/asdf.fish

Env setting

export EDITOR=nvim
set FZF_LEGACY_KEYBINDINGS 0

Starship setup

starship init fish | source

starship

scan_timeout = 1000
command_timeout = 1000

# Disable the newline at the start of the prompt
add_newline = true

# Replace the "โฏ" symbol in the prompt with "โžœ"
[character] # The name of the module we are configuring is "character"
success_symbol = "[โžœ](bold green)" # The "success_symbol" segment is being set to "โžœ" with the color "bold green"

[battery]
full_symbol = "๐Ÿ”‹"
charging_symbol = "โšก๏ธ"
discharging_symbol = "๐Ÿ’€"

[ruby]
symbol = "๐Ÿ”บ "

[nodejs]
symbol = "๎œ˜ "

[git_status]
conflicted = "๐Ÿณ"
ahead = "๐ŸŽ๐Ÿ’จ"
behind = "๐Ÿ˜ฐ"
diverged = "๐Ÿ˜ต"
untracked = "๐Ÿคทโ€"
stashed = "๐Ÿ“ฆ"
modified = "๐Ÿ“"
staged = '[++\($count\)](green)'
renamed = "๐Ÿ‘…"
deleted = "๐Ÿ—‘"

[git_branch]
symbol = "๐ŸŒฑ "

welcome memssage

remove last login message by touch this dot file


function fish_greeting

end

alias

fish shell ไฝฟ็”จๅ‡ฝๆ•ฐๆฅๅฎž็Žฐ alias

function cat
  bat $argv
end
function vim
  nvim $argv
end
function ls
  exa $argv
end
function gita
  python3 -m gita $argv
end

Git

basic

ๅŸบ็ก€้…็ฝฎ

ln -s ~/Dropbox/Config/id_rsa ~/.ssh/id_rsa
ln -s ~/Dropbox/Config/id_rsa.pub ~/.ssh/id_rsa.pub
[include]
        path = ~/.config/git/gitconfig
[push]
        default = simple
[pull]
        rebase = false
[core]
        excludesfile = ~/.gitignore_global
[commit]
        template = ~/.gitmessage
[protocol]
        version = 2
[pager]
        branch = false
[user]
        name = teddy
        email = [email protected]

global ignore

ๅ…จๅฑ€็š„ ignore ้…็ฝฎ

#############################################################################
# https://github.com/github/gitignore/blob/master/Global/Archives.gitignore #
#############################################################################
# It's better to unpack these files and commit the raw source because
# git has its own built in compression methods.
*.7z
*.jar
*.rar
*.zip
*.gz
*.bzip
*.bz2
*.xz
*.lzma
*.cab

#packing-only formats
*.iso
*.tar

#package management formats
*.dmg
*.xpi
*.gem
*.egg
*.deb
*.rpm
*.msi
*.msm
*.msp
###########################################################################
# https://github.com/github/gitignore/blob/master/Global/Cloud9.gitignore #
###########################################################################
# Cloud9 IDE - http://c9.io
.c9revisions
.c9
############################################################################
# https://github.com/github/gitignore/blob/master/Global/CodeKit.gitignore #
############################################################################
# General CodeKit files to ignore
config.codekit
/min
##########################################################################
# https://github.com/github/gitignore/blob/master/Global/Emacs.gitignore #
##########################################################################
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*

# Org-mode
.org-id-locations
*_archive

# flymake-mode
*_flymake.*

# eshell files
/eshell/history
/eshell/lastdir

# elpa packages
/elpa/

# reftex files
*.rel

# AUCTeX auto folder
/auto/

# cask packages
.cask/
####################################################################################
# https://github.com/github/gitignore/blob/master/Global/IPythonNotebook.gitignore #
####################################################################################
# Temporary data
.ipynb_checkpoints/
##############################################################################
# https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore #
##############################################################################
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
################################################################################
# https://github.com/github/gitignore/blob/master/Global/LibreOffice.gitignore #
################################################################################
# LibreOffice locks
.~lock.*#
##########################################################################
# https://github.com/github/gitignore/blob/master/Global/Linux.gitignore #
##########################################################################
*~

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*
####################################################################################
# https://github.com/github/gitignore/blob/master/Global/MicrosoftOffice.gitignore #
####################################################################################
*.tmp

# Word temporary
~$*.doc*

# Excel temporary
~$*.xls*

# Excel Backup File
*.xlk
##############################################################################
# https://github.com/github/gitignore/blob/master/Global/NotepadPP.gitignore #
##############################################################################
# Notepad++ backups #
*.bak
########################################################################
# https://github.com/github/gitignore/blob/master/Global/OSX.gitignore #
########################################################################
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear on external disk
.Spotlight-V100
.Trashes

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
##########################################################################
# https://github.com/github/gitignore/blob/master/Global/Redis.gitignore #
##########################################################################
# Ignore redis binary dump (dump.rdb) files

*.rdb
################################################################################
# https://github.com/github/gitignore/blob/master/Global/SublimeText.gitignore #
################################################################################
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache

# workspace files are user-specific
*.sublime-workspace

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project

# sftp configuration file
sftp-config.json
#############################################################################
# https://github.com/github/gitignore/blob/master/Global/TextMate.gitignore #
#############################################################################
*.tmproj
*.tmproject
tmtags
########################################################################
# https://github.com/github/gitignore/blob/master/Global/Vim.gitignore #
########################################################################
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
############################################################################
# https://github.com/github/gitignore/blob/master/Global/Windows.gitignore #
############################################################################
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk
##########################################################################
# https://github.com/github/gitignore/blob/master/Global/Xcode.gitignore #
##########################################################################
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.xcuserstate
###################################################
# EXCERPT https://gist.github.com/octocat/9257657 #
###################################################

# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so

# Logs and databases #
######################
*.sql
*.sqlite
*.log
############
# PERSONAL #
############
tmp/
temp/

# Floobits
.floo
.flooignore

git message

git ๆไบคไฟกๆฏ็š„ๆ ผๅผๆจกๆฟ

Why:

*

This change addresses the need by:

*

# 50-character subject line
#
# 72-character wrapped longer description.

git diff

https://github.com/dandavison/delta

[core]
    pager = delta

[interactive]
    diffFilter = delta --color-only

[delta]
    features = line-numbers decorations
    whitespace-error-style = 22 reverse

[delta "decorations"]
    commit-decoration-style = bold yellow box ul
    file-style = bold yellow ul
    file-decoration-style = none

Auto correct

where 20 is a 2 second delay before executing the suggested command. You can set a delay of your choice.

[help]
    autocorrect = 20

homebrew

ๅธธ็”จ็š„่ฝฏไปถ้ƒฝๅˆ—ๅœจ่ฟ™้‡Œไบ†

echo '
  tap "d12frosted/emacs-plus"
  tap "heroku/brew"
  tap "homebrew/bundle"
  tap "homebrew/cask"
  tap "homebrew/cask-drivers"
  tap "homebrew/cask-fonts"
  tap "homebrew/cask-versions"
  tap "homebrew/core"
  tap "homebrew/services"
  tap "thoughtbot/formulae"
  tap "universal-ctags/universal-ctags"
  brew "antigen"
  brew "brotli"
  brew "[email protected]"
  brew "aria2"
  brew "asciinema"
  brew "automake"
  brew "coreutils"
  brew "libyaml"
  brew "asdf"
  brew "aspell"
  brew "asuka"
  brew "autojump"
  brew "bandwhich"
  brew "bat"
  brew "bit-git"
  brew "pkg-config"
  brew "clisp"
  brew "cloc"
  brew "cmake"
  brew "cmake-docs"
  brew "ctags", link: false
  brew "diskonaut"
  brew "erlang"
  brew "exa"
  brew "harfbuzz"
  brew "ffmpeg"
  brew "gcc"
  brew "fish"
  brew "flow-cli"
  brew "fswatch"
  brew "fx"
  brew "fzf"
  brew "fzy"
  brew "geckodriver"
  brew "gh"
  brew "git"
  brew "git-delta"
  brew "git-quick-stats"
  brew "gping"
  brew "gradle"
  brew "graphviz"
  brew "gsl"
  brew "htop"
  brew "httpie"
  brew "hub"
  brew "hugo"
  brew "iftop"
  brew "shared-mime-info"
  brew "imagemagick"
  brew "jpegoptim"
  brew "jq"
  brew "luarocks"
  brew "memcached", restart_service: true
  brew "mpg123"
  brew "mplayer"
  brew "mysql", restart_service: true
  brew "ncdu"
  brew "neofetch"
  brew "neovim"
  brew "nushell"
  brew "onefetch"
  brew "pandoc"
  brew "percol"
  brew "pfetch"
  brew "plantuml"
  brew "poppler"
  brew "postgresql", restart_service: true
  brew "postgresql@13", restart_service: true
  brew "prettyping"
  brew "procs"
  brew "pstree"
  brew "rcm"
  brew "reattach-to-user-namespace"
  brew "redis", restart_service: true
  brew "rename"
  brew "ripgrep"
  brew "rust-analyzer"
  brew "rustup-init"
  brew "sbcl"
  brew "speedtest-cli"
  brew "splint"
  brew "starship"
  brew "stow"
  brew "subversion"
  brew "terminal-notifier"
  brew "the_silver_searcher"
  brew "thefuck"
  brew "tig"
  brew "tldr"
  brew "tmux"
  brew "tokei"
  brew "tree"
  brew "typespeed"
  brew "vcs"
  brew "vim"
  brew "vips"
  brew "w3m"
  brew "watchman"
  brew "wget"
  brew "yarn"
  brew "you-get"
  brew "youtube-dl"
  brew "zsh"
  brew "d12frosted/emacs-plus/emacs-plus@27", link: false
  brew "d12frosted/emacs-plus/emacs-plus@28"
  brew "heroku/brew/heroku"
  brew "thoughtbot/formulae/parity"
  brew "universal-ctags/universal-ctags/universal-ctags", args: ["HEAD"]
  cask "balenaetcher"
  cask "chromedriver"
  cask "chromium"
  cask "citra"
  cask "clashx"
  cask "dropbox"
  cask "edex-ui"
  cask "emacs"
  cask "epic-games"
  cask "feishu"
  cask "firefox"
  cask "font-cascadia-code"
  cask "font-fira-mono-for-powerline"
  cask "font-hack-nerd-font"
  cask "font-noto-sans-mono"
  cask "font-source-code-pro"
  cask "font-source-code-pro-for-powerline"
  cask "gitup"
  cask "google-chrome"
  cask "gpg-suite"
  cask "hammerspoon"
  cask "handshaker"
  cask "iina"
  cask "intellij-idea-ce"
  cask "java6"
  cask "next"
  cask "qq"
  cask "slack"
  cask "steam"
  cask "tableplus"
  cask "tandem"
  cask "telegram"
  cask "the-unarchiver"
  cask "visual-studio-code"
  cask "vivaldi"
  cask "wechat"
' |  brew bundle --file=-

Neovim

ไธๅคช็”จ vim, ๅชๆœ‰ๆœ€ๅŸบๆœฌ็š„้…็ฝฎ

" Douglas Black
" Colors {{{
syntax enable           " enable syntax processing
" }}}
" Misc {{{
set ttyfast                     " faster redraw
set backspace=indent,eol,start
" }}}
" Spaces & Tabs {{{
set tabstop=4           " 4 space tab
set expandtab           " use spaces for tabs
set softtabstop=4       " 4 space tab
set shiftwidth=4
set modelines=1
filetype indent on
filetype plugin on
set autoindent
" }}}
" UI Layout {{{
set number              " show line numbers
set showcmd             " show command in bottom bar
set nocursorline          " highlight current line
set wildmenu
"set lazyredraw
set showmatch           " higlight matching parenthesis
" }}}
" Searching {{{
set ignorecase          " ignore case when searching
set incsearch           " search as characters are entered
set hlsearch            " highlight all matches
" }}}
" Folding {{{
"=== folding ===
set foldmethod=indent   " fold based on indent level
set foldnestmax=10      " max 10 depth
set foldenable          " don't fold files by default on open
nnoremap <space> za
set foldlevelstart=10    " start with fold level of 1
" }}}
" Line Shortcuts {{{
nnoremap j gj
nnoremap k gk
nnoremap B ^
nnoremap E $
nnoremap $ <nop>
nnoremap ^ <nop>
nnoremap gV `[v`]
onoremap an :<c-u>call <SID>NextTextObject('a', 'f')<cr>
xnoremap an :<c-u>call <SID>NextTextObject('a', 'f')<cr>
onoremap in :<c-u>call <SID>NextTextObject('i', 'f')<cr>
xnoremap in :<c-u>call <SID>NextTextObject('i', 'f')<cr>

onoremap al :<c-u>call <SID>NextTextObject('a', 'F')<cr>
xnoremap al :<c-u>call <SID>NextTextObject('a', 'F')<cr>
onoremap il :<c-u>call <SID>NextTextObject('i', 'F')<cr>
xnoremap il :<c-u>call <SID>NextTextObject('i', 'F')<cr>
" }}}
" Leader Shortcuts {{{
let mapleader=","
nnoremap <leader>m :silent make\|redraw!\|cw<CR>
nnoremap <leader>w :NERDTree<CR>
nnoremap <leader>u :GundoToggle<CR>
nnoremap <leader>h :A<CR>
nnoremap <leader>ev :vsp $MYVIMRC<CR>
nnoremap <leader>ez :vsp ~/.zshrc<CR>
nnoremap <leader>sv :source $MYVIMRC<CR>
nnoremap <leader>l :call ToggleNumber()<CR>
nnoremap <leader><space> :noh<CR>
nnoremap <leader>s :mksession<CR>
nnoremap <leader>a :Ag
nnoremap <leader>c :SyntasticCheck<CR>:Errors<CR>
nnoremap <leader>1 :set number!<CR>
nnoremap <leader>d :Make!
nnoremap <leader>r :call RunTestFile()<CR>
nnoremap <leader>g :call RunGoFile()<CR>
vnoremap <leader>y "+y
vmap v <Plug>(expand_region_expand)
vmap <C-v> <Plug>(expand_region_shrink)
inoremap jk <esc>
" }}}
" Powerline {{{
"set encoding=utf-8
"python from powerline.vim import setup as powerline_setup
"python powerline_setup()
"python del powerline_setup
let g:airline#extensions#tabline#left_sep = ' '
let g:airline#extensions#tabline#left_alt_sep = '|'
let g:airline_left_sep = ''
let g:airline_left_alt_sep = ''
let g:airline_right_sep = ''
let g:airline_right_alt_sep = ''
set laststatus=2
" }}}
" CtrlP {{{
let g:ctrlp_match_window = 'bottom,order:ttb'
let g:ctrlp_switch_buffer = 0
let g:ctrlp_working_path_mode = 0
let g:ctrlp_custom_ignore = '\vbuild/|dist/|venv/|target/|\.(o|swp|pyc|egg)$'
" }}}
" NERDTree {{{
let NERDTreeIgnore = ['\.pyc$', 'build', 'venv', 'egg', 'egg-info/', 'dist', 'docs']
" }}}
" Syntastic {{{
let g:syntastic_python_flake8_args='--ignore=E501'
let g:syntastic_ignore_files = ['.java$']
" }}}
" Launch Config {{{
runtime! debian.vim
set nocompatible
" }}}
"" Tmux {{{
"if exists('$TMUX') " allows cursor change in tmux mode
"    let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
"    let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
"else
"    let &t_SI = "\<Esc>]50;CursorShape=1\x7"
"    let &t_EI = "\<Esc>]50;CursorShape=0\x7"
"endif
"" }}}
" MacVim {{{
set guioptions-=r
set guioptions-=L
" }}}
" AutoGroups {{{
augroup configgroup
    autocmd!
    autocmd VimEnter * highlight clear SignColumn
    autocmd BufWritePre *.php,*.py,*.js,*.txt,*.hs,*.java,*.md,*.rb :call <SID>StripTrailingWhitespaces()
    autocmd BufEnter *.cls setlocal filetype=java
    autocmd BufEnter *.zsh-theme setlocal filetype=zsh
    autocmd BufEnter Makefile setlocal noexpandtab
    autocmd BufEnter *.sh setlocal tabstop=2
    autocmd BufEnter *.sh setlocal shiftwidth=2
    autocmd BufEnter *.sh setlocal softtabstop=2
augroup END
" }}}
" Backups {{{
set backup
set backupdir=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
set backupskip=/tmp/*,/private/tmp/*
set directory=~/.vim-tmp,~/.tmp,~/tmp,/var/tmp,/tmp
set writebackup
" }}}
" Custom Functions {{{
function! ToggleNumber()
    if(&relativenumber == 1)
        set norelativenumber
        set number
    else
        set relativenumber
    endif
endfunc

function! RunTestFile()
    if(&ft=='python')
        exec ":!" . ". venv/bin/activate; nosetests " .bufname('%') . " --stop"
    endif
endfunction

function! RunGoFile()
    if(&ft=='go')
        exec ":new|0read ! go run " . bufname('%')
    endif
endfunction

function! RunTestsInFile()
    if(&ft=='php')
        :execute "!" . "/Users/dblack/pear/bin/phpunit -d memory_limit=512M -c /usr/local/twilio/src/php/tests/config.xml --bootstrap /usr/local/twilio/src/php/tests/bootstrap.php " . bufname('%') . ' \| grep -v Configuration \| egrep -v "^$" '
    elseif(&ft=='go')
        exec ":!gp test"
    elseif(&ft=='python')
        exec ":read !" . ". venv/bin/activate; nosetests " . bufname('%') . " --nocapture"
    endif
endfunction

" strips trailing whitespace at the end of files. this
" is called on buffer write in the autogroup above.
function! <SID>StripTrailingWhitespaces()
    " save last search & cursor position
    let _s=@/
    let l = line(".")
    let c = col(".")
    %s/\s\+$//e
    let @/=_s
    call cursor(l, c)
endfunction

function! <SID>CleanFile()
    " Preparation: save last search, and cursor position.
    let _s=@/
    let l = line(".")
    let c = col(".")
    " Do the business:
    %!git stripspace
    " Clean up: restore previous search history, and cursor position
    let @/=_s
    call cursor(l, c)
endfunction

function! s:NextTextObject(motion, dir)
  let c = nr2char(getchar())

  if c ==# "b"
      let c = "("
  elseif c ==# "B"
      let c = "{"
  elseif c ==# "r"
      let c = "["
  endif

  exe "normal! ".a:dir.c."v".a:motion.c
endfunction
" }}}

" vim:foldmethod=marker:foldlevel=0

psql

postgresql ๆ•ฐๆฎๅบ“ๅฎขๆˆท็ซฏ็š„้…็ฝฎ

cli

# vi: ft=dosini
[main]

# Enables context sensitive auto-completion. If this is disabled the all
# possible completions will be listed.
smart_completion = True

# Display the completions in several columns. (More completions will be
# visible.)
wider_completion_menu = False

# Multi-line mode allows breaking up the sql statements into multiple lines. If
# this is set to True, then the end of the statements must have a semi-colon.
# If this is set to False then sql statements can't be split into multiple
# lines. End of line (return) is considered as the end of the statement.
multi_line = False

# If multi_line_mode is set to "psql", in multi-line mode, [Enter] will execute
# the current input if the input ends in a semicolon.
# If multi_line_mode is set to "safe", in multi-line mode, [Enter] will always
# insert a newline, and [Esc] [Enter] or [Alt]-[Enter] must be used to execute
# a command.
multi_line_mode = psql

# Enables expand mode, which is similar to `\x` in psql.
expand = False

# Enables auto expand mode, which is similar to `\x auto` in psql.
auto_expand = False

# If set to True, table suggestions will include a table alias
generate_aliases = False

# log_file location.
# In Unix/Linux: ~/.config/pgcli/log
# In Windows: %USERPROFILE%\AppData\Local\dbcli\pgcli\log
# %USERPROFILE% is typically C:\Users\{username}
log_file = default

# keyword casing preference. Possible values "lower", "upper", "auto"
keyword_casing = auto

# casing_file location.
# In Unix/Linux: ~/.config/pgcli/casing
# In Windows: %USERPROFILE%\AppData\Local\dbcli\pgcli\casing
# %USERPROFILE% is typically C:\Users\{username}
casing_file = default

# If generate_casing_file is set to True and there is no file in the above
# location, one will be generated based on usage in SQL/PLPGSQL functions.
generate_casing_file = False

# Casing of column headers based on the casing_file described above
case_column_headers = True

# history_file location.
# In Unix/Linux: ~/.config/pgcli/history
# In Windows: %USERPROFILE%\AppData\Local\dbcli\pgcli\history
# %USERPROFILE% is typically C:\Users\{username}
history_file = default

# Default log level. Possible values: "CRITICAL", "ERROR", "WARNING", "INFO"
# and "DEBUG". "NONE" disables logging.
log_level = INFO

# Order of columns when expanding * to column list
# Possible values: "table_order" and "alphabetic"
asterisk_column_order = table_order

# Whether to qualify with table alias/name when suggesting columns
# Possible values: "always", never" and "if_more_than_one_table"
qualify_columns = if_more_than_one_table

# When no schema is entered, only suggest objects in search_path
search_path_filter = False

# Default pager.
# By default 'PAGER' environment variable is used
# pager = less -SRXF

# Timing of sql statments and table rendering.
timing = True

# Table format. Possible values: psql, plain, simple, grid, fancy_grid, pipe,
# ascii, double, github, orgtbl, rst, mediawiki, html, latex, latex_booktabs,
# textile, moinmoin, jira, vertical, tsv, csv.
# Recommended: psql, fancy_grid and grid.
table_format = psql

# Syntax Style. Possible values: manni, igor, xcode, vim, autumn, vs, rrt,
# native, perldoc, borland, tango, emacs, friendly, monokai, paraiso-dark,
# colorful, murphy, bw, pastie, paraiso-light, trac, default, fruity
syntax_style = default

# Keybindings:
# When Vi mode is enabled you can use modal editing features offered by Vi in the REPL.
# When Vi mode is disabled emacs keybindings such as Ctrl-A for home and Ctrl-E
# for end are available in the REPL.
vi = False

# Error handling
# When one of multiple SQL statements causes an error, choose to either
# continue executing the remaining statements, or stopping
# Possible values "STOP" or "RESUME"
on_error = STOP

# Set threshold for row limit prompt. Use 0 to disable prompt.
row_limit = 1000

# Skip intro on startup and goodbye on exit
less_chatty = False

# Postgres prompt
# \u - Username
# \h - Hostname of the server
# \d - Database name
# \n - Newline
prompt = '\u@\h:\d> '

# Number of lines to reserve for the suggestion menu
min_num_menu_lines = 4

# Character used to left pad multi-line queries to match the prompt size.
multiline_continuation_char = ''

# The string used in place of a null value.
null_string = '<null>'

# Custom colors for the completion menu, toolbar, etc.
[colors]
Token.Menu.Completions.Completion.Current = 'bg:#ffffff #000000'
Token.Menu.Completions.Completion = 'bg:#008888 #ffffff'
Token.Menu.Completions.Meta.Current = 'bg:#44aaaa #000000'
Token.Menu.Completions.Meta = 'bg:#448888 #ffffff'
Token.Menu.Completions.MultiColumnMeta = 'bg:#aaffff #000000'
Token.Menu.Completions.ProgressButton = 'bg:#003333'
Token.Menu.Completions.ProgressBar = 'bg:#00aaaa'
Token.SelectedText = '#ffffff bg:#6666aa'
Token.SearchMatch = '#ffffff bg:#4444aa'
Token.SearchMatch.Current = '#ffffff bg:#44aa44'
Token.Toolbar = 'bg:#222222 #aaaaaa'
Token.Toolbar.Off = 'bg:#222222 #888888'
Token.Toolbar.On = 'bg:#222222 #ffffff'
Token.Toolbar.Search = 'noinherit bold'
Token.Toolbar.Search.Text = 'nobold'
Token.Toolbar.System = 'noinherit bold'
Token.Toolbar.Arg = 'noinherit bold'
Token.Toolbar.Arg.Text = 'nobold'
Token.Toolbar.Transaction.Valid = 'bg:#222222 #00ff5f bold'
Token.Toolbar.Transaction.Failed = 'bg:#222222 #ff005f bold'

# Named queries are queries you can execute by name.
[named queries]

# DNS to call by -D option
[alias_dsn]
# example_dsn = postgresql://[user[:password]@][netloc][:port][/dbname]

# Format for number representation
# for decimal "d" - 12345678, ",d" - 12,345,678
# for float "g" - 123456.78, ",g" - 123,456.78
[data_formats]
decimal = ""
float = ""

rc

\set QUIET 1
\timing
\set ON_ERROR_ROLLBACK interactive
\set VERBOSITY verbose
\x auto
\set PROMPT1 '%[%033[1m%]%M/%/%R%[%033[0m%]%# '
\set PROMPT2 ''
\set HISTFILE ~/.psql_history- :DBNAME
\set HISTCONTROL ignoredups
\pset null [null]
\unset QUIET

Xresources

ๅฑๅน•่ฎพ็ฝฎ

Xft.dpi:       96
Xft.antialias: true
Xft.hinting:   true
Xft.rgba:      rgb
Xft.autohint:  false
Xft.hintstyle: hintslight
Xft.lcdfilter: lcddefault

XTerm ่ฎพ็ฝฎ

XTerm*background:        #222D31
XTerm*foreground:        #d8d8d8
XTerm*pointerColor:      #1ABB9B
XTerm*faceName:          Fixed
XTerm*faceSize:          11
XTerm*reverseVideo:      on
XTerm*selectToClipboard: true

้ขœ่‰ฒ่ฎพ็ฝฎ

*background:                      #222D31
*foreground:                      #d8d8d8
*fading:                          8
*fadeColor:                       black
*cursorColor:                     #1ABB9B
*pointerColorBackground:          #2B2C2B
*pointerColorForeground:          #16A085

!! black dark/light
*color0:                          #222D31
*color8:                          #585858

!! red dark/light
*color1:                          #ab4642
*color9:                          #ab4642

!! green dark/light
*color2:                          #7E807E
*color10:                         #8D8F8D

!! yellow dark/light
*color3:                          #f7ca88
*color11:                         #f7ca88

!! blue dark/light
*color4:                          #7cafc2
*color12:                         #7cafc2

!! magenta dark/light
*color5:                          #ba8baf
*color13:                         #ba8baf

!! cyan dark/light
*color6:                          #1ABB9B
*color14:                         #1ABB9B

!! white dark/light
*color7:                          #d8d8d8
*color15:                         #f8f8f8

Xcursor.theme:                    xcursor-breeze
Xcursor.size:                     0

URxvt ่ฎพ็ฝฎ

URxvt*font:                       xft:SauceCodePro Nerd Font Mono:pixelsize=21:minspace=False, xft:DejaVu Sans:pixelsize=14, xft:Monaco:style=regular:pixelsize=13:antialias=true,hinting=true, xft:dejavu sans mono:pixelsize=13:antialias=true,hinting=true, xft:Twitter Color Emoji:pixelsize=14, xft:NotoEmoji Nerd Font Mono:pixelsize=14, xft:Symbola
URxvt*boldFont:                   xft:SauceCodePro Nerd Font Mono:pixelsize=21:minspace=False, xft:DejaVu Sans:pixelsize=14, xft:Monaco:style=regular:pixelsize=13:antialias=true,hinting=true, xft:dejavu sans mono:pixelsize=13:antialias=true,hinting=true
URxvt*letterSpace:                0
! alternative font settings with 'terminus':
! URxvt.font:      -xos4-terminus-medium-r-normal--16-160-72-72-c-80-iso10646-1
! URxvt.bold.font: -xos4-terminus-bold-r-normal--16-160-72-72-c-80-iso10646-1
!! terminus names see end of file!

URxvt.depth:                      32
URxvt.background:                 [100]#222D31
URxvt*scrollBar:                  false
URxvt*mouseWheelScrollPage:       false
URxvt*cursorBlink:                true
URxvt*background:                 black
URxvt*foreground:                 grey
URxvt*saveLines:                  5000

! for 'fake' transparency (without Compton) uncomment the following three lines
! URxvt*inheritPixmap:            true
! URxvt*transparent:              true
! URxvt*shading:                  138

! Normal copy-paste keybindings without perls
URxvt.iso14755:                   false
URxvt.keysym.Mod4-v:                 eval:paste_clipboard
URxvt.keysym.Mod4-c:                 eval:selection_to_clipboard
URxvt.keysym.Mod4-l:              command:\033c
URxvt.keysym.Mod4-k:                    echo -ne '\\033c'\n

!Xterm escape codes, word by word movement
URxvt.keysym.Control-Left:        \033[1;5D
URxvt.keysym.Shift-Control-Left:  \033[1;6D
URxvt.keysym.Control-Right:       \033[1;5C
URxvt.keysym.Shift-Control-Right: \033[1;6C
URxvt.keysym.Control-Up:          \033[1;5A
URxvt.keysym.Shift-Control-Up:    \033[1;6A
URxvt.keysym.Control-Down:        \033[1;5B
URxvt.keysym.Shift-Control-Down:  \033[1;6B

Alacritty

  window:
  decorations: 'buttonless'
  padding:
    x: 4
    y: 8

font:
  use_thin_strokes: false
  normal:
    # family: 'ShureTechMono Nerd Font Mono'
    family: 'Iosevka Nerd Font Mono'
  bold:
    family: 'Iosevka Nerd Font Mono'
  italic:
    family: 'Iosevka Nerd Font Mono'
  bold_italic:
    family: 'Iosevka Nerd Font Mono'
  size: 13.0

# Colors (One Dark)
colors:
  # Default colors
  primary:
    # background: '#282c34'
    background: '#1F2329'
    foreground: '#abb2bf'

  # Normal colors
  normal:
    # NOTE: Use '#131613' for the `black` color if you'd like to see
    # black text on the background.
    # black:   '#282c34'
    black: '#1F2329'
    red:     '#e06c75'
    green:   '#98c379'
    yellow:  '#d19a66'
    blue:    '#61afef'
    magenta: '#c678dd'
    cyan:    '#56b6c2'
    white:   '#abb2bf'

  # Bright colors
  bright:
    black:   '#5c6370'
    red:     '#e06c75'
    green:   '#98c379'
    yellow:  '#d19a66'
    blue:    '#61afef'
    magenta: '#c678dd'
    cyan:    '#56b6c2'
    white:   '#ffffff'

key_bindings:
  - { key: A,         mods: Alt,       chars: "\x1ba"                       }
  - { key: B,         mods: Alt,       chars: "\x1bb"                       }
  - { key: C,         mods: Alt,       chars: "\x1bc"                       }
  - { key: D,         mods: Alt,       chars: "\x1bd"                       }
  - { key: E,         mods: Alt,       chars: "\x1be"                       }
  - { key: F,         mods: Alt,       chars: "\x1bf"                       }
  - { key: G,         mods: Alt,       chars: "\x1bg"                       }
  - { key: H,         mods: Alt,       chars: "\x1bh"                       }
  - { key: I,         mods: Alt,       chars: "\x1bi"                       }
  - { key: J,         mods: Alt,       chars: "\x1bj"                       }
  - { key: K,         mods: Alt,       chars: "\x1bk"                       }
  - { key: L,         mods: Alt,       chars: "\x1bl"                       }
  - { key: M,         mods: Alt,       chars: "\x1bm"                       }
  - { key: N,         mods: Alt,       chars: "\x1bn"                       }
  - { key: O,         mods: Alt,       chars: "\x1bo"                       }
  - { key: P,         mods: Alt,       chars: "\x1bp"                       }
  - { key: Q,         mods: Alt,       chars: "\x1bq"                       }
  - { key: R,         mods: Alt,       chars: "\x1br"                       }
  - { key: S,         mods: Alt,       chars: "\x1bs"                       }
  - { key: T,         mods: Alt,       chars: "\x1bt"                       }
  - { key: U,         mods: Alt,       chars: "\x1bu"                       }
  - { key: V,         mods: Alt,       chars: "\x1bv"                       }
  - { key: W,         mods: Alt,       chars: "\x1bw"                       }
  - { key: X,         mods: Alt,       chars: "\x1bx"                       }
  - { key: Y,         mods: Alt,       chars: "\x1by"                       }
  - { key: Z,         mods: Alt,       chars: "\x1bz"                       }
  - { key: A,         mods: Alt|Shift, chars: "\x1bA"                       }
  - { key: B,         mods: Alt|Shift, chars: "\x1bB"                       }
  - { key: C,         mods: Alt|Shift, chars: "\x1bC"                       }
  - { key: D,         mods: Alt|Shift, chars: "\x1bD"                       }
  - { key: E,         mods: Alt|Shift, chars: "\x1bE"                       }
  - { key: F,         mods: Alt|Shift, chars: "\x1bF"                       }
  - { key: G,         mods: Alt|Shift, chars: "\x1bG"                       }
  - { key: H,         mods: Alt|Shift, chars: "\x1bH"                       }
  - { key: I,         mods: Alt|Shift, chars: "\x1bI"                       }
  - { key: J,         mods: Alt|Shift, chars: "\x1bJ"                       }
  - { key: K,         mods: Alt|Shift, chars: "\x1bK"                       }
  - { key: L,         mods: Alt|Shift, chars: "\x1bL"                       }
  - { key: M,         mods: Alt|Shift, chars: "\x1bM"                       }
  - { key: N,         mods: Alt|Shift, chars: "\x1bN"                       }
  - { key: O,         mods: Alt|Shift, chars: "\x1bO"                       }
  - { key: P,         mods: Alt|Shift, chars: "\x1bP"                       }
  - { key: Q,         mods: Alt|Shift, chars: "\x1bQ"                       }
  - { key: R,         mods: Alt|Shift, chars: "\x1bR"                       }
  - { key: S,         mods: Alt|Shift, chars: "\x1bS"                       }
  - { key: T,         mods: Alt|Shift, chars: "\x1bT"                       }
  - { key: U,         mods: Alt|Shift, chars: "\x1bU"                       }
  - { key: V,         mods: Alt|Shift, chars: "\x1bV"                       }
  - { key: W,         mods: Alt|Shift, chars: "\x1bW"                       }
  - { key: X,         mods: Alt|Shift, chars: "\x1bX"                       }
  - { key: Y,         mods: Alt|Shift, chars: "\x1bY"                       }
  - { key: Z,         mods: Alt|Shift, chars: "\x1bZ"                       }
  - { key: Key1,      mods: Alt,       chars: "\x1b1"                       }
  - { key: Key2,      mods: Alt,       chars: "\x1b2"                       }
  - { key: Key3,      mods: Alt,       chars: "\x1b3"                       }
  - { key: Key4,      mods: Alt,       chars: "\x1b4"                       }
  - { key: Key5,      mods: Alt,       chars: "\x1b5"                       }
  - { key: Key6,      mods: Alt,       chars: "\x1b6"                       }
  - { key: Key7,      mods: Alt,       chars: "\x1b7"                       }
  - { key: Key8,      mods: Alt,       chars: "\x1b8"                       }
  - { key: Key9,      mods: Alt,       chars: "\x1b9"                       }
  - { key: Key0,      mods: Alt,       chars: "\x1b0"                       }
  - { key: Space,     mods: Control,   chars: "\x00"                        } # Ctrl + Space
  - { key: Grave,     mods: Alt,       chars: "\x1b`"                       } # Alt + `
  - { key: Grave,     mods: Alt|Shift, chars: "\x1b~"                       } # Alt + ~
  - { key: Period,    mods: Alt,       chars: "\x1b."                       } # Alt + .
  - { key: Key8,      mods: Alt|Shift, chars: "\x1b*"                       } # Alt + *
  - { key: Key3,      mods: Alt|Shift, chars: "\x1b#"                       } # Alt + #
  - { key: Period,    mods: Alt|Shift, chars: "\x1b>"                       } # Alt + >
  - { key: Comma,     mods: Alt|Shift, chars: "\x1b<"                       } # Alt + <
  - { key: Minus,     mods: Alt|Shift, chars: "\x1b_"                       } # Alt + _
  - { key: Key5,      mods: Alt|Shift, chars: "\x1b%"                       } # Alt + %
  - { key: Key6,      mods: Alt|Shift, chars: "\x1b^"                       } # Alt + ^
  - { key: Backslash, mods: Alt,       chars: "\x1b\\"                      } # Alt + \
  - { key: Backslash, mods: Alt|Shift, chars: "\x1b|"                       } # Alt + |

tmux

basic

# cat << โ–บ_โ—„ > /dev/null
# ไธŠ้ข่ฟ™่กŒๅฏไปฅ็”จๆฅๆฃ€ๆต‹็‰นๆฎŠๅญ—็ฌฆ่ƒฝๅฆๅœจๅฝ“ๅ‰็Žฏๅขƒ่ขซๆ˜พ็คบ

# -- general -------------------------------------------------------------------

setw -g xterm-keys on

set -sg repeat-time 600                   # increase repeat timeout

set -g prefix2 C-a                        # GNU-Screen compatible prefix
bind C-a send-prefix -2                   # ้ป˜่ฎคๅ‰็ผ€ๆ˜ฏ c-a

# edit configuration
bind e new-window -n '~/.tmux.conf' '${EDITOR:-vim} ~/.tmux.conf && tmux source ~/.tmux.conf && tmux display "~/.tmux.conf sourced"'

# see https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
if 'which -s reattach-to-user-namespace' 'set -g default-command "tmux rename-window initializing; tmux set -w automatic-rename; reattach-to-user-namespace $SHELL -l"'

# -- display -------------------------------------------------------------------

set -g base-index 1         # start windows numbering at 1
setw -g pane-base-index 1   # make pane numbering consistent with windows

setw -g automatic-rename on # rename window to reflect current program
# renumber windows when a window is closed
set -g renumber-windows on

set -g set-titles on                        # set terminal title
set -g set-titles-string '#h โ #S โ— #I #W'  # ๆ˜พ็คบ็š„title

set -g display-panes-time 800 # slightly longer pane indicators display time

# 24 hour clock
setw -g clock-mode-style 24

# clear both screen and history
bind -n C-l send-keys C-l \; run 'tmux clear-history'

# activity
set -g monitor-activity on
set -g visual-activity off

# -- navigation ----------------------------------------------------------------

# create new session
bind C-c new-session # ๅˆ›ๅปบๆ–ฐ็š„ session

# find session
bind C-f command-prompt -p find-session 'switch-client -t %%' # ๆŸฅๆ‰พ session

bind - splitw -v # ๅˆ†ๅ‰ฒๆˆไธŠไธ‹ไธคไธช็ช—ๅฃ
bind | splitw -h # ๅˆ†ๅ‰ฒๆˆๅทฆๅณไธคไธช็ช—ๅฃ

# pane navigation vim ้”ฎไฝ็š„ๅฏผ่ˆชๅœจ pane ไน‹้—ด
bind -r h select-pane -L  # move left
bind -r j select-pane -D  # move down
bind -r k select-pane -U  # move up
bind -r l select-pane -R  # move right
bind > swap-pane -D       # swap current pane with the next one
bind < swap-pane -U       # swap current pane with the previous one

# maximize current pane ๆœ€ๅคงๅŒ–ๅฝ“ๅ‰ pane
bind + run 'cut -c3- ~/.tmux.conf | sh -s maximize_pane'

# pane resizing ๅคงๅ†™็š„ vim ้”ฎไฝ๏ผŒ ่ฐƒๆ•ด pane ๅฐบๅฏธ
bind -r H resize-pane -L 2
bind -r J resize-pane -D 2
bind -r K resize-pane -U 2
bind -r L resize-pane -R 2

# window navigation
bind -r C-h previous-window # select previous window
bind -r C-l next-window     # select next window
bind Space last-window      # move to last active window

# toggle mouse
bind m run "cut -c3- ~/.tmux.conf | sh -s toggle_mouse"


# copy to Mac OSX pasteboard
if 'which -s reattach-to-user-namespace' 'bind y run "tmux save-buffer - | reattach-to-user-namespace pbcopy"'

# ็”จๆˆท่‡ชๅฎšไน‰็š„ๆจกๅ—
if '[ -f ~/.tmux.conf.local ]' 'source ~/.tmux.conf.local'
# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
# Other examples:
# set -g @plugin 'github_username/plugin_name'
# set -g @plugin '[email protected]/user/plugin'
# set -g @plugin '[email protected]/user/plugin'
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'

local

# tmux theme, colors and status line
# available themes:
#   - powerline (a powerline inspired theme)
#   - powerline_patched_font (a powerline inspired theme using a patched font)
#tmux_conf_theme=powerline # powerline ็š„ไธป้ข˜
set-option -g status-position top
# set -g status-right ""
set -g status-right '#{prefix_highlight} | %a %Y-%m-%d %H:%M'

#### COLOUR (Solarized light)

# default statusbar colors
set-option -g status-bg white #base2
set-option -g status-fg yellow #yellow
set-option -g status-attr default

# default window title colors
set-window-option -g window-status-fg brightyellow #base00
set-window-option -g window-status-bg default
#set-window-option -g window-status-attr dim

# active window title colors
set-window-option -g window-status-current-fg brightred #orange
set-window-option -g window-status-current-bg default
#set-window-option -g window-status-current-attr bright

# pane border
set-option -g pane-border-fg white #base2
set-option -g pane-active-border-fg brightcyan #base1

# message text
set-option -g message-bg white #base2
set-option -g message-fg brightred #orange

# pane number display
set-option -g display-panes-active-colour blue #blue
set-option -g display-panes-colour brightred #orange

# clock
set-window-option -g clock-mode-colour green #green

# bell
set-window-option -g window-status-bell-style fg=white,bg=red #base2, red

wayland

# Configuration for Alacritty, the GPU enhanced terminal emulator

env:
  TERM: xterm-256color

window:
  dimensions:
    columns: 100
    lines: 85

  padding:
    x: 0
    y: 0

  dynamic_padding: false

  decorations: full

  startup_mode: Windowed

scrolling:
  history: 5000
  multiplier: 3

# Font configuration (changes require restart)
font:
  # The normal (roman) font face to use.
  # Style can be specified to pick a specific face.
  normal:
    family: Iosevka
    style: Light
    # family: "Fira Code"
    # family: "Source Code Pro"
    # style: Retina

  # The bold font face
  bold:
    family: Iosevka
    style: Medium
    # family: "Fira Code"
    # family: "Source Code Pro"

  # The italic font face
  italic:
    family: Iosevka
    style: "Light Italic"
    # style: "Light Oblique"
    # family: "Fira Code"
    # family: "Source Code Pro"
    # style: "Medium Italic"

  # Point size of the font
  size: 14.0

  # Offset is the extra space around each character. offset.y can be thought of
  # as modifying the linespacing, and offset.x as modifying the letter spacing.
  offset:
    x: 0
    y: 0

  # Glyph offset determines the locations of the glyphs within their cells with
  # the default being at the bottom. Increase the x offset to move the glyph to
  # the right, increase the y offset to move the glyph upward.
  glyph_offset:
    x: 0
    y: 0

  use_thin_strokes: true

# When true, bold text is drawn using the bright variant of colors.
draw_bold_text_with_bright_colors: false

# Use custom cursor colors. If true, display the cursor in the cursor.foreground
# and cursor.background colors, otherwise invert the colors of the cursor.
# custom_cursor_colors: false

# Colors
colors:
  # Default colours
  primary:
    background: '0xffffff'
    foreground: '0x2e2e2d'

  # Colors that should be used to draw the terminal cursor. If these are unset,
  # the cursor colour will be the inverse of the cell colour.
  # cursor:
  #   text: '0x2e2e2d'
  #   # text: '0x000000'
  #   cursor: '0xffffff'

  # Normal colors
  normal:
    black:   '0x000000'
    red:     '0xc62828'
    green:   '0x558b2f'
    yellow:  '0xf9a825'
    blue:    '0x1565c0'
    magenta: '0x6a1e9a'
    cyan:    '0x00838f'
    white:   '0xf2f2f2'

  # Bright colors
  bright:
    black:   '0x545454'
    red:     '0xef5350'
    green:   '0x8bc34a'
    yellow:  '0xffeb3b'
    blue:    '0x64b5f6'
    magenta: '0xba68c8'
    cyan:    '0x26c6da'
    white:   '0xe0e0e0'

  # Dim colors (Optional)
  dim:
    black:   '0x333333'
    red:     '0xf2777a'
    green:   '0x99cc99'
    yellow:  '0xffcc66'
    blue:    '0x6699cc'
    magenta: '0xcc99cc'
    cyan:    '0x66cccc'
    white:   '0xdddddd'

  # Tomorrow Night Bright
  # primary:
  #   background: '0x000000'
  #   foreground: '0xeaeaea'
  #
  # cursor:
  #   text: '0x000000'
  #   cursor: '0xffffff'
  #
  # normal:
  #   black:   '0x000000'
  #   red:     '0xd54e53'
  #   green:   '0xb9ca4a'
  #   yellow:  '0xe6c547'
  #   blue:    '0x7aa6da'
  #   magenta: '0xc397d8'
  #   cyan:    '0x70c0ba'
  #   white:   '0xffffff'
  #
  # bright:
  #   black:   '0x666666'
  #   red:     '0xff3334'
  #   green:   '0x9ec400'
  #   yellow:  '0xe7c547'
  #   blue:    '0x7aa6da'
  #   magenta: '0xb77ee0'
  #   cyan:    '0x54ced6'
  #   white:   '0xffffff'

  # Indexed Colors
  #
  # The indexed colors include all colors from 16 to 256.
  # When these are not set, they're filled with sensible defaults.
  #
  # Example:
  #   `- { index: 16, color: '0xff00ff' }`
  #
  indexed_colors: []

bell:
  animation: EaseOutExpo
  color: '0xffffff'
  duration: 0

# Background opacity
background_opacity: 1.0

#
# Example:
#   `- { key: V, mods: Control|Shift, action: Paste }`
#
# Available fields:
#   - key
#   - mods (optional)
#   - chars | action | command (exactly one required)
#   - mode (optional)
#
# Values for `key`:
#   - `A` -> `Z`
#   - `F1` -> `F12`
#   - `Key1` -> `Key0`
#
#   A full list with available key codes can be found here:
#   https://docs.rs/glutin/*/glutin/enum.VirtualKeyCode.html#variants
#
#   Instead of using the name of the keys, the `key` field also supports using
#   the scancode of the desired key. Scancodes have to be specified as a
#   decimal number.
#   This command will allow you to display the hex scancodes for certain keys:
#     `showkey --scancodes`
#
# Values for `mods`:
#   - Command
#   - Control
#   - Option
#   - Super
#   - Shift
#   - Alt
#
#   Multiple `mods` can be combined using `|` like this: `mods: Control|Shift`.
#   Whitespace and capitalization is relevant and must match the example.
#
# Values for `chars`:
#   The `chars` field writes the specified string to the terminal. This makes
#   it possible to pass escape sequences.
#   To find escape codes for bindings like `PageUp` ("\x1b[5~"), you can run
#   the command `showkey -a` outside of tmux.
#   Note that applications use terminfo to map escape sequences back to
#   keys. It is therefore required to update the terminfo when
#   changing an escape sequence.
#
# Values for `action`:
#   - Paste
#   - PasteSelection
#   - Copy
#   - IncreaseFontSize
#   - DecreaseFontSize
#   - ResetFontSize
#   - ScrollPageUp
#   - ScrollPageDown
#   - ScrollLineUp
#   - ScrollLineDown
#   - ScrollToTop
#   - ScrollToBottom
#   - ClearHistory
#   - Hide
#   - Quit
#   - ClearLogNotice
#   - SpawnNewInstance
#   - ToggleFullscreen
#   - None
#
# Values for `action` (macOS only):
#   - ToggleSimpleFullscreen: Enters fullscreen without occupying another space
#
# Values for `command`:
#   The `command` field must be a map containing a `program` string and
#   an `args` array of command line parameter strings.
#
#   Example:
#       `command: { program: "alacritty", args: ["-e", "vttest"] }`
#
# Values for `mode`:
#   - ~AppCursor
#   - AppCursor
#   - ~AppKeypad
#   - AppKeypad
#
key_bindings:
  - { key: V,        mods: Command,       action: Paste                        }
  - { key: C,        mods: Command,       action: Copy                         }
  - { key: Q,        mods: Command,       action: Quit                         }
  - { key: N,        mods: Command,       action: SpawnNewInstance             }
  - { key: Return,   mods: Command,       action: ToggleFullscreen             }

  - { key: Home,                          chars: "\x1bOH",   mode: AppCursor   }
  - { key: Home,                          chars: "\x1b[H",   mode: ~AppCursor  }
  - { key: End,                           chars: "\x1bOF",   mode: AppCursor   }
  - { key: End,                           chars: "\x1b[F",   mode: ~AppCursor  }
  - { key: Equals,   mods: Command,       action: IncreaseFontSize             }
  - { key: Minus,    mods: Command,       action: DecreaseFontSize             }
  - { key: Minus,    mods: Command|Shift, action: ResetFontSize                }
  - { key: PageUp,   mods: Shift,         chars: "\x1b[5;2~"                   }
  - { key: PageUp,   mods: Control,       chars: "\x1b[5;5~"                   }
  - { key: PageUp,                        chars: "\x1b[5~"                     }
  - { key: PageDown, mods: Shift,         chars: "\x1b[6;2~"                   }
  - { key: PageDown, mods: Control,       chars: "\x1b[6;5~"                   }
  - { key: PageDown,                      chars: "\x1b[6~"                     }
  - { key: Left,     mods: Shift,         chars: "\x1b[1;2D"                   }
  - { key: Left,     mods: Control,       chars: "\x1b[1;5D"                   }
  - { key: Left,     mods: Alt,           chars: "\x1b[1;3D"                   }
  - { key: Left,                          chars: "\x1b[D",   mode: ~AppCursor  }
  - { key: Left,                          chars: "\x1bOD",   mode: AppCursor   }
  - { key: Right,    mods: Shift,         chars: "\x1b[1;2C"                   }
  - { key: Right,    mods: Control,       chars: "\x1b[1;5C"                   }
  - { key: Right,    mods: Alt,           chars: "\x1b[1;3C"                   }
  - { key: Right,                         chars: "\x1b[C",   mode: ~AppCursor  }
  - { key: Right,                         chars: "\x1bOC",   mode: AppCursor   }
  - { key: Up,       mods: Shift,         chars: "\x1b[1;2A"                   }
  - { key: Up,       mods: Control,       chars: "\x1b[1;5A"                   }
  - { key: Up,       mods: Alt,           chars: "\x1b[1;3A"                   }
  - { key: Up,                            chars: "\x1b[A",   mode: ~AppCursor  }
  - { key: Up,                            chars: "\x1bOA",   mode: AppCursor   }
  - { key: Down,     mods: Shift,         chars: "\x1b[1;2B"                   }
  - { key: Down,     mods: Control,       chars: "\x1b[1;5B"                   }
  - { key: Down,     mods: Alt,           chars: "\x1b[1;3B"                   }
  - { key: Down,                          chars: "\x1b[B",   mode: ~AppCursor  }
  - { key: Down,                          chars: "\x1bOB",   mode: AppCursor   }
  - { key: Tab,      mods: Shift,         chars: "\x1b[Z"                      }
  - { key: F1,                            chars: "\x1bOP"                      }
  - { key: F2,                            chars: "\x1bOQ"                      }
  - { key: F3,                            chars: "\x1bOR"                      }
  - { key: F4,                            chars: "\x1bOS"                      }
  - { key: F5,                            chars: "\x1b[15~"                    }
  - { key: F6,                            chars: "\x1b[17~"                    }
  - { key: F7,                            chars: "\x1b[18~"                    }
  - { key: F8,                            chars: "\x1b[19~"                    }
  - { key: F9,                            chars: "\x1b[20~"                    }
  - { key: F10,                           chars: "\x1b[21~"                    }
  - { key: F11,                           chars: "\x1b[23~"                    }
  - { key: F12,                           chars: "\x1b[24~"                    }
  - { key: Back,                          chars: "\x7f"                        }
  - { key: Back,     mods: Alt,           chars: "\x1b\x7f"                    }
  - { key: Insert,                        chars: "\x1b[2~"                     }
  - { key: Delete,                        chars: "\x1b[3~"                     }

    # shortcuts for tmux. the leader key is control-b (0x02)
  - { key: W,        mods: Command,       chars: "\x02&"                       }  # close tab (kill)
  - { key: T,        mods: Command,       chars: "\x02c"                       }  # new tab
  - { key: RBracket, mods: Command|Shift, chars: "\x02n"                       }  # select next tab
  - { key: LBracket, mods: Command|Shift, chars: "\x02p"                       }  # select previous tab
  - { key: RBracket, mods: Command,       chars: "\x02o"                       }  # select next pane
  - { key: LBracket, mods: Command,       chars: "\x02;"                       }  # select last (previously used) pane
  - { key: F,        mods: Command,       chars: "\x02/"                       }  # search (upwards) (see tmux.conf)

mouse:
  # Click settings
  #
  # The `double_click` and `triple_click` settings control the time
  # alacritty should wait for accepting multiple clicks as one double
  # or triple click.
  double_click: { threshold: 300 }
  triple_click: { threshold: 300 }

  # If this is `true`, the cursor is temporarily hidden when typing.
  hide_when_typing: true

  # URL launcher
  # url:
    # This program is executed when clicking on a text which is recognized as a URL.
    # The URL is always added to the command as the last parameter.
    #
    # When set to `None`, URL launching will be disabled completely.
    #
    # Default:
    #   - (macOS) open
    #   - (Linux) xdg-open
    #   - (Windows) explorer
    # launcher:
    #   program: xdg-open
    #   args: []

    # These are the modifiers that need to be held down for opening URLs when clicking
    # on them. The available modifiers are documented in the key binding section.
    # modifiers: Control|Shift

selection:
  semantic_escape_chars: ",โ”‚`|:\"' ()[]{}<>"

  # When set to `true`, selected text will be copied to the primary clipboard.
  save_to_clipboard: false

# Mouse bindings
#
# Available fields:
# - mouse
# - action
# - mods (optional)
#
# Values for `mouse`:
# - Middle
# - Left
# - Right
# - Numeric identifier such as `5`
#
# All available `mods` and `action` values are documented in the key binding
# section.
mouse_bindings:
  - { mouse: Middle, action: PasteSelection }

cursor:
  # Cursor style
  #
  # Values for 'style':
  #   - โ–‡ Block
  #   - _ Underline
  #   - | Beam
  style: Block

  # If this is `true`, the cursor will be rendered as a hollow box when the
  # window is not focused.
  unfocused_hollow: true

# dynamic_title: false

# Live config reload (changes require restart)
live_config_reload: true

# Shell
#
# You can set shell.program to the path of your favorite shell, e.g. /bin/fish.
# Entries in shell.args are passed unmodified as arguments to the shell.
shell:
  program: /usr/bin/fish
  #args:
  #  - --command=tmux

debug:
  # Should display the render timer
  render_timer: false

  # Keep the log file after quitting Alacritty.
  persistent_logging: false

  # Log level
  #
  # Values for `log_level`:
  #   - OFF
  #   - ERROR
  #   - WARN
  #   - INFO
  #   - DEBUG
  #   - TRACE
  log_level: OFF

  # Print all received window events.
  print_events: false

  # Record all characters and escape sequences as test data.
  ref_test: false

# vim: nospell
set -x MOZ_ENABLE_WAYLAND 1
--enable-features=UseOzonePlatform
--ozone-platform=wayland
# Logo key. Use Mod1(super) for Alt.
set $mod Mod4
# Home row direction keys, like vim
set $left h
set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term alacritty
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
#set $menu dmenu_path | dmenu | xargs swaymsg exec --
set $menu wofi --show=drun --lines=5 --prompt=""
# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/)
output * bg /usr/share/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill

### Key bindings
#
# Basics:
#
# Start a terminal
bindsym $mod+Return exec $term

# Kill focused window
bindsym $mod+Shift+q kill

# Start your launcher
bindsym $mod+d exec $menu

# Drag floating windows by holding down $mod and left mouse button.
# Resize them with right mouse button + $mod.
# Despite the name, also works for non-floating windows.
# Change normal to inverse to use left mouse button for resizing and right
# mouse button for dragging.
floating_modifier $mod normal

# Reload the configuration file
bindsym $mod+Shift+c reload

# Exit sway (logs you out of your Wayland session)
bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit'
#
# Moving around:
#
# Move your focus around
bindsym $mod+$left focus left
bindsym $mod+$down focus down
bindsym $mod+$up focus up
bindsym $mod+$right focus right
# Or use $mod+[up|down|left|right]
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right

# Move the focused window with the same, but add Shift
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
# Ditto, with arrow keys
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
#
# Workspaces:
#
# Switch to workspace
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
bindsym $mod+4 workspace number 4
bindsym $mod+5 workspace number 5
bindsym $mod+6 workspace number 6
bindsym $mod+7 workspace number 7
bindsym $mod+8 workspace number 8
bindsym $mod+9 workspace number 9
bindsym $mod+0 workspace number 10
# Move focused container to workspace
bindsym $mod+Shift+1 move container to workspace number 1
bindsym $mod+Shift+2 move container to workspace number 2
bindsym $mod+Shift+3 move container to workspace number 3
bindsym $mod+Shift+4 move container to workspace number 4
bindsym $mod+Shift+5 move container to workspace number 5
bindsym $mod+Shift+6 move container to workspace number 6
bindsym $mod+Shift+7 move container to workspace number 7
bindsym $mod+Shift+8 move container to workspace number 8
bindsym $mod+Shift+9 move container to workspace number 9
bindsym $mod+Shift+0 move container to workspace number 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
#
# Layout stuff:
#
# You can "split" the current object of your focus with
# $mod+b or $mod+v, for horizontal and vertical splits
# respectively.
bindsym $mod+b splith
bindsym $mod+v splitv

# Switch the current container between different layout styles
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split

# Make the current focus fullscreen
bindsym $mod+f fullscreen

# Toggle the current focus between tiling and floating mode
bindsym $mod+Shift+space floating toggle

# Swap focus between the tiling area and the floating area
bindsym $mod+space focus mode_toggle

# Move focus to the parent container
bindsym $mod+a focus parent
#
# Scratchpad:
#
# Sway has a "scratchpad", which is a bag of holding for windows.
# You can send windows there and get them back later.

# Move the currently focused window to the scratchpad
bindsym $mod+Shift+minus move scratchpad

# Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show
#
# Resizing containers:
#
mode "resize" {
# left will shrink the containers width
# right will grow the containers width
# up will shrink the containers height
# down will grow the containers height
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px

# Ditto, with arrow keys
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px

# Return to default mode
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"

#
# Status Bar:
#
# Read `man 5 sway-bar` for more information about this section.
bar {
position top

# When the status_command prints a new line to stdout, swaybar updates.
# The default just shows the current date and time.
# status_command while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done
swaybar_command waybar
colors {
statusline #ffffff
background #323232
inactive_workspace #32323200 #32323200 #5c5c5c
}
}

input "type:keyboard" {
# or input <identifier>
xkb_options ctrl:nocaps
}

include /etc/sway/config.d/*

hammerspoon

Link Spoons

ln -s ~/Dropbox/Config/Spoons ~/.hammerspoon

Install fennel

luarocks install fennel

Setup

hs.loadSpoon("AClock")
hs.loadSpoon("WinWin")
hs.loadSpoon("WindowScreenLeftAndRight")
hs.loadSpoon("WindowHalfsAndThirds")
hs.loadSpoon("Cherry")
hs.loadSpoon("PopupTranslateSelection")

require "modules/config"
require "modules/reload"
require "modules/app"
require "modules/window"
require "modules/screen"
require "modules/key"
require "modules/dashboard"
require "modules/select"
require "modules/layout"
require "modules/react"
require "modules/caffeine"
require "modules/pomo"
require "modules/translate"
require "modules/cherry"

-- Support upcoming 5.4 release and also use luarocks' local path
package.path = package.path .. ";" .. os.getenv("HOME") .. "/.luarocks/share/lua/5.4/?.lua;" .. os.getenv("HOME") .. "/.luarocks/share/lua/5.4/?/init.lua"
package.cpath = package.cpath .. ";" .. os.getenv("HOME") .. "/.luarocks/lib/lua/5.4/?.so"
package.path = package.path .. ";" .. os.getenv("HOME") .. "/.luarocks/share/lua/5.3/?.lua;" .. os.getenv("HOME") .. "/.luarocks/share/lua/5.3/?/init.lua"
package.cpath = package.cpath .. ";" .. os.getenv("HOME") .. "/.luarocks/lib/lua/5.3/?.so"

fennel = require("fennel")
table.insert(package.loaders or package.searchers, fennel.searcher)

hs.hotkey.bind(hyper, 'h', function() hs.alert.show("Hello World!") end)

require "core"

Core

(hs.ipc.cliInstall) ; ensure CLI installed
(local fennel (require :fennel))

(hs.hotkey.bind
 [:ctrl :cmd] "`" nil
 (fn []
   (hs.openConsole)))

Config

hyper = {'cmd', 'alt', 'ctrl'}
hyperShift = {'alt', 'cmd', 'shift'}
macbook_monitor = "Color LCD"
dostyle_monitor = "DM320QC"
lg_4k_monitor = "LV273HUPR"
portable_monitor = "CLUO FHD"
lg_ultrawide_monitor = "LG ULTRAWIDE"

Reload

function reloadConfig(files)
    doReload = false
    for _,file in pairs(files) do
        if file:sub(-4) == ".lua" then
            doReload = true
        end
    end
    if doReload then
       hs.reload()
    end
end
hammerspoonConfigFilesWatcher = hs.pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", reloadConfig):start()

hs.hotkey.bind(hyper, 'r', function() hs.reload() end)
hs.alert.show("๐Ÿค“.๐Ÿ› .๐Ÿค“, config succesfully")

App Launcher

hs.hotkey.bind(hyper, 'i', function()
                  hs.application.launchOrFocus('Terminal')
                  -- hs.application.launchOrFocus('Warp')
end)

hs.hotkey.bind(hyper, 'f', function()
                  hs.application.launchOrFocus('Finder')
end)

hs.hotkey.bind(hyper, 's', function()
                  hs.application.launchOrFocus('Slack')
end)

hs.hotkey.bind(hyper, 'e', function()
                  hs.application.launchOrFocus('Emacs')
end)

hs.hotkey.bind(hyper, 't', function()
                  spoon.AClock:toggleShow()
end)

Key

function showKeyPress(tap_event)
   local duration = 1.5  -- popup duration
   local modifiers = ""  -- key modifiers string representation
   local flags = tap_event:getFlags()
   local character = hs.keycodes.map[tap_event:getKeyCode()]
   -- we only want to read special characters via getKeyCode, so we use this subset of hs.keycodes.map
   local special_chars = {
      ["f1"] = true, ["f2"] = true, ["f3"] = true, ["f4"] = true,
      ["f5"] = true, ["f6"] = true, ["f7"] = true, ["f8"] = true,
      ["f9"] = true, ["f10"] = true, ["f11"] = true, ["f12"] = true,
      ["f13"] = true, ["f14"] = true, ["f15"] = true, ["f16"] = true,
      ["f17"] = true, ["f18"] = true, ["f19"] = true, ["f20"] = true,
      ["pad"] = true, ["pad*"] = true, ["pad+"] = true, ["pad/"] = true,
      ["pad-"] = true, ["pad="] = true, ["pad0"] = true, ["pad1"] = true,
      ["pad2"] = true, ["pad3"] = true, ["pad4"] = true, ["pad5"] = true,
      ["pad6"] = true, ["pad7"] = true, ["pad8"] = true, ["pad9"] = true,
      ["padclear"] = true, ["padenter"] = true, ["return"] = true,
      ["tab"] = true, ["space"] = true, ["delete"] = true, ["escape"] = true,
      ["help"] = true, ["home"] = true, ["pageup"] = true,
      ["forwarddelete"] = true, ["end"] = true, ["pagedown"] = true,
      ["left"] = true, ["right"] = true, ["down"] = true, ["up"] = true
   }

   -- if we have a simple character (no modifiers), we want a shorter popup duration.
   if (not flags.shift and not flags.cmd and not flags.alt and not flags.ctrl) then
      duration = 0.3
   end

   -- we want to get regular characters via getCharacters as it "cleans" the key for us
   -- (e.g. for a "โ‡ง-5" keypress we want to show "โ‡ง-%").
   if special_chars[character] == nil then
      character = tap_event:getCharacters(true)
      if flags.shift then
         character = string.lower(character)
      end
   end

   local pretty_characters = {
      ["return"]  = "โŽ",
      ["delete"]  = "โŒซ",
      ["escape"]  = "โŽ‹",
      ["space"]   = "SPC",
      ["up"]      = "โ†‘",
      ["down"]    = "โ†“",
      ["left"]    = "โ†",
      ["right"]   = "โ†’",
      ["tab"]     = "โ‡ฅ"
   }

   character = pretty_characters[character] or character

   -- get modifiers' string representation
   if flags.ctrl then
      modifiers = modifiers .. "โŒƒ-"
   end
   if flags.cmd then
      modifiers = modifiers .. "โŒ˜-"
   end
   if flags.shift then
      modifiers = modifiers .. "โ‡ง-"
   end
   if flags.alt then
      modifiers = modifiers .. "โŒฅ-"
   end

   key_char = modifiers .. character
   display_key_char(key_char)
end

function display_key_char(key_char)
   build_exist_key_string(key_char)

   if not key_draw then
      create_draw(exist_key_string)
   else
      destroy_draw(key_draw)
      create_draw(exist_key_string)
   end
   key_draw:show()
   reset_key_display_timer()
end

function build_exist_key_string(string)
   local max_display_key_command_length = 8
   key_array = key_array or {}

   if #key_array > max_display_key_command_length then
      table.remove(key_array, 1)
   end

   key_array[#key_array + 1] = string
   exist_key_string = table.concat(key_array, ' ')
end

function reset_key_display_timer()
   if key_display_timer then
      key_display_timer:stop()
   end
   key_display_timer = hs.timer.doAfter(2, function() destroy_draw(key_draw) key_array = {} end)
end

function create_draw(content)
   local mainRes = hs.mouse.getCurrentScreen():fullFrame() -- e.g w:1920 h:1080
   local font_size = 40
   local styledString = hs.styledtext.new(
      content,
      {
         font = { name = "Fira Mono", size = font_size },
         color = hs.drawing.color.hammerspoon.osx_green, --hs.drawing.color.x11.silver,
         paragraphStyle = { alignment = "center" }
      }
   )
   local w = mainRes.w * 2 / 3
   local h = font_size * 1.5
   local x = mainRes.w / 2 - w / 3
   local y = mainRes.y + h + w / 2
   local keyFrame = hs.geometry.rect(x, y, w, h)
   key_draw = hs.drawing.text(keyFrame, styledString)
   key_draw:setLevel(hs.drawing.windowLevels.overlay)
end

function destroy_draw(draw)
   if draw then
      key_draw:delete()
      key_draw = nil
   end
end

local key_tap = hs.eventtap.new(
   {hs.eventtap.event.types.keyDown},
   showKeyPress
)

-- Enable/Disable Keypress Show Mode with "hyper-p"
k = hs.hotkey.modal.new(hyper, 'P')
function k:entered()
   hs.alert.show("Enabling Keypress Show Mode", 1.5)
   key_tap:start()
end
function k:exited()
   hs.alert.show("Disabling Keypress Show Mode", 1.5)
end
k:bind(hyper, 'P', function()
          key_tap:stop()
          k:exit()
end)

Layout

top_half    = hs.geometry.unitrect(0,0,1,0.5)
buttom_half = hs.geometry.unitrect(0,0.5,1,0.5)
left_half   = hs.layout.left50
right_half  = hs.layout.right50
maximized   = hs.layout.maximized


local reading_layout= {
  {"Emacs",         nil, macbook_monitor, maximized, nil, nil},
  {"Google Chrome", nil, main_monitor,    right_half,   nil, nil},
  {"iBooks",        nil, main_monitor,    left_half,    nil, nil},
  {"Telegram",      nil, second_monitor,  top_half,    nil, nil},
  {"Mail",          nil, second_monitor,  buttom_half,   nil, nil},
}

local coding_layout= {
  {"Terminal",      nil, macbook_monitor, maximized, nil, nil},
  {"Google Chrome", nil, main_monitor,    left_half,    nil, nil},
  {"Emacs",         nil, main_monitor,    right_half,   nil, nil},
  {"Station",       nil, second_monitor,  top_half,    nil, nil},
  {"TablePlus",     nil, second_monitor,  buttom_half,   nil, nil},
}

local writing_layout= {
  {"Emacs",         nil, main_monitor,    maximized, nil, nil},
  {"Google Chrome", nil, second_monitor,  maximized, nil, nil},
  {"IINA",          nil, macbook_monitor, maximized, nil, nil},
}

hs.hotkey.bind(hyper, '1', function()
  hs.application.launchOrFocus('Emacs')
  hs.application.launchOrFocus('Google Chrome')
  hs.application.launchOrFocus('iBooks')
  hs.application.launchOrFocus('Telegram')
  hs.application.launchOrFocus('Mail')

  hs.layout.apply(reading_layout)
end)

hs.hotkey.bind(hyper, '2', function()
  hs.application.launchOrFocus('Terminal')
  hs.application.launchOrFocus('Google Chrome')
  hs.application.launchOrFocus('Emacs')
  hs.application.launchOrFocus('Station')
  hs.application.launchOrFocus('TablePlus')

  hs.layout.apply(coding_layout)
end)

hs.hotkey.bind(hyper, '3', function()
  hs.application.launchOrFocus('Google Chrome')
  hs.application.launchOrFocus('Emacs')
  hs.application.launchOrFocus('IINA')

  hs.layout.apply(writing_layout)
end)

React

function applicationWatcher(appName, eventType, appObject)
   if (eventType == hs.application.watcher.activated) then
      if (appName == "Terminal") then
         appObject:selectMenuItem({"Window", "Bring All to Front"})
      elseif (appName == "Finder") then
         appObject:selectMenuItem({"Window", "Bring All to Front"})
      elseif (appName == "Google Chrome") then
         appObject:selectMenuItem({"Window", "Bring All to Front"})
      end
   end
end

appWatcher = hs.application.watcher.new(applicationWatcher)
appWatcher:start()

Caffeine

  ampIconOn = [[ASCII:
.....1a..........AC..........E
..............................
......4.......................
1..........aA..........CE.....
e.2......4.3...........h......
..............................
..............................
.......................h......
e.2......6.3.........t...q....
5..........c.........s........
......6.......................
.........................q....
.....5c..............s...t....
]]

ampIconOff = [[ASCII:
.....1a.....x....AC.y.......zE
..............................
......4.......................
1..........aA..........CE.....
e.2......4.3...........h......
..............................
..............................
.......................h......
e.2......6.3.........t...q....
5..........c.........s........
......6.......................
.........................q....
...x.5c....y.......z.s...t....
]]

-- caffeine replacement
local caffeine = hs.menubar.new()

function setCaffeineDisplay(state)
   if state then
      caffeine:setIcon(ampIconOn)
   else
      caffeine:setIcon(ampIconOff)
   end
end

function caffeineClicked()
   setCaffeineDisplay(hs.caffeinate.toggle("displayIdle"))
end

if caffeine then
   caffeine:setClickCallback(caffeineClicked)
   setCaffeineDisplay(hs.caffeinate.get("displayIdle"))
end

Screen

function focus_other_screen() -- focuses the other screen
   local current_screen = hs.mouse.getCurrentScreen()
   local nextScreen = current_screen:next()
   local rect = nextScreen:fullFrame()
   local center = hs.geometry.rectMidPoint(rect)
   hs.mouse.setAbsolutePosition(center)
   return nextScreen
end

function get_window_under_mouse() -- from https://gist.github.com/kizzx2/e542fa74b80b7563045a
   local my_pos = hs.geometry.new(hs.mouse.getAbsolutePosition())
   local my_screen = hs.mouse.getCurrentScreen()
   return hs.fnutils.find(hs.window.orderedWindows(), function(w)
                             return my_screen == w:screen() and my_pos:inside(w:frame())
   end)
end

function activate_other_screen()
   local next_screen = focus_other_screen()
   local win = get_window_under_mouse()
   win:focus()
   redrawBorder()
end

hs.hotkey.bind(hyper, 'o', function()
                  activate_other_screen()
end)

function redrawBorder()
   win = hs.window.focusedWindow()
   if not win then
      return
   end
   top_left = win:topLeft()
   size = win:size()
   if global_border ~= nil then global_border:delete() end
   global_border = hs.drawing.rectangle(hs.geometry.rect(top_left['x'], top_left['y'], size['w'], size['h']))
   global_border:setStrokeColor({ ["red"] = 1, ["blue"] = 0, ["green"] = 0, ["alpha"] = 0.8 })
   global_border:setFill(false)
   global_border:setStrokeWidth(8)
   global_border:show()
   hs.timer.doAfter(1, function() global_border:hide() end)
end

function mouseHighlight()
   -- Delete an existing highlight if it exists
   if mouseCircle then
      mouseCircle:delete()
      if mouseCircleTimer then
         mouseCircleTimer:stop()
      end
   end
   -- Get the current co-ordinates of the mouse pointer
   mousepoint = hs.mouse.getAbsolutePosition()
   hs.alert.show(mousepoint)
   -- Prepare a big red circle around the mouse pointer
   mouseCircle = hs.drawing.circle(hs.geometry.rect(mousepoint.x-40, mousepoint.y-40, 80, 80))
   mouseCircle:setStrokeColor({ ["red"] = 1, ["blue"] = 0, ["green"] = 0, ["alpha"] = 1 })
   mouseCircle:setFill(false)
   mouseCircle:setStrokeWidth(5)
   mouseCircle:show()

   -- Set a timer to delete the circle after 3 seconds
   mouseCircleTimer = hs.timer.doAfter(3, function() mouseCircle:delete() end)
end

Window

-- hs.window.animationDuration = 0
spoon.WindowScreenLeftAndRight:bindHotkeys({
      screen_left = { hyperShift, "Left" },
      screen_right= { hyperShift, "Right" },
})

spoon.WindowHalfsAndThirds:bindHotkeys({
      left_half   = { hyper, "Left" },
      right_half  = { hyper, "Right" },
      top_half    = { hyper, "Up" },
      bottom_half = { hyper, "Down" },
})

-- hs.hotkey.bind(hyper, "m", function()
--   local win = hs.window.focusedWindow()
--   win:maximize()
-- end)

Dashboard

hs.hotkey.bind(hyper, 'y', function()
                  if not dashboardView then
                     generate_view()
                     local webcontent = html_dashboard(generate_result())
                     dashboardView:html(webcontent)
                     dashboardView:show()
                  else
                     dashboardView:delete()
                     dashboardView:hide()
                     dashboardView = nil
                  end
end)

function generate_result()
   local items = {
      todolist = {'cat ~/Documents/org/todo.org  | grep "* TODO" | sed "s/TODO/""/g"', "col-todo-list"},
      roamlist = {'ls ~/Documents/org/roam', "col-roam-list"}
   }

   result = generate_html_row_div(items)
   return result
end

function generate_html_row_div(tb)
   result = '<div class="row" style="min-height:100px">'
   for k, v in pairs(tb) do
      result = result .. '<div class="col-sm ' .. v[2] .. '">'
      result = result .. '<h4>' .. k .. '</h4>'
      result = result .. get_command_result(v[1]) .. '</div>'
   end
   result = result .. '</div>'
   return result
end

function get_command_result(c)
   local handle = io.popen(c)
   local result = handle:read("*a")
   handle:close()
   return result.gsub(result, "\n", "<br/>")
end

function generate_view()
   local cscreen = hs.screen.mainScreen()
   local cres = cscreen:fullFrame()

   dashboardView = hs.webview.new({x=0, y=0, w=0, h=0})
   dashboardView:windowTitle("Dashboard")
   dashboardView:windowStyle("utility")
   dashboardView:allowGestures(true)
   dashboardView:allowNewWindows(false)
   dashboardView:level(hs.drawing.windowLevels.modalPanel)
   dashboardView:frame({
         x = cres.x + cres.w * 0.15 / 2,
         y = cres.y + cres.h * 0.25 / 2,
         w = cres.w * 0.85,
         h = cres.h * 0.75
   })
end

function html_dashboard(content)
   local html = [[
      <!doctype html>
      <html lang="en">
        <head>
          <!-- Required meta tags -->
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1">

          <!-- Bootstrap CSS -->
          <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">

        </head>
        <body>
          <h1 style="text-align: center">Dashboard</h1>

      <div class="container">
                  ]] .. content .. [[

    </div>
        </body>
      </html>
                  ]]

   return html
end

Pomo

--- Pomodoro module

--------------------------------------------------------------------------------
-- Configuration variables
--------------------------------------------------------------------------------
local pom={}
pom.bar = {
  indicator_height = 0.1, -- ratio from the height of the menubar (0..1)
  indicator_alpha  = 0.3,
  indicator_in_all_spaces = true,
  color_time_remaining = hs.drawing.color.green,
  color_time_used      = hs.drawing.color.red,

  c_left = hs.drawing.rectangle(hs.geometry.rect(0,0,0,0)),
  c_used = hs.drawing.rectangle(hs.geometry.rect(0,0,0,0))
}

pom.config = {
  enable_color_bar = true,
  work_period_sec  = 25 * 60,
  rest_period_sec  = 5 * 60,

}

pom.var = {
  is_active        = false,
  disable_count    = 0,
  work_count       = 0,
  curr_active_type = "๐Ÿ„", -- {"work", "rest"}
  time_left        = pom.config.work_period_sec,
  max_time_sec     = pom.config.work_period_sec
}

--------------------------------------------------------------------------------
-- Color bar for pomodoor
--------------------------------------------------------------------------------

function pom_del_indicators()
  pom.bar.c_left:delete()
  pom.bar.c_used:delete()
end

function pom_draw_on_menu(target_draw, screen, offset, width, fill_color)
  local screeng                  = screen:fullFrame()
  local screen_frame_height      = screen:frame().y
  local screen_full_frame_height = screeng.y
  local height_delta             = screen_frame_height - screen_full_frame_height
  local height                   = pom.bar.indicator_height * (height_delta)

  target_draw:setSize(hs.geometry.rect(screeng.x + offset, screen_full_frame_height, width, height))
  target_draw:setTopLeft(hs.geometry.point(screeng.x + offset, screen_full_frame_height))
  target_draw:setFillColor(fill_color)
  target_draw:setFill(true)
  target_draw:setAlpha(pom.bar.indicator_alpha)
  target_draw:setLevel(hs.drawing.windowLevels.overlay)
  target_draw:setStroke(false)
  if pom.bar.indicator_in_all_spaces then
    target_draw:setBehavior(hs.drawing.windowBehaviors.canJoinAllSpaces)
  end
  target_draw:show()
end

function pom_draw_indicator(time_left, max_time)
  local main_screen = hs.screen.mainScreen()
  local screeng     = main_screen:fullFrame()
  local time_ratio  = time_left / max_time
  local width       = math.ceil(screeng.w * time_ratio)
  local left_width  = screeng.w - width

  pom_draw_on_menu(pom.bar.c_left, main_screen, left_width, width,      pom.bar.color_time_remaining)
  pom_draw_on_menu(pom.bar.c_used, main_screen, 0,          left_width, pom.bar.color_time_used)

end
--------------------------------------------------------------------------------

-- update display
local function pom_update_display()
  local time_min = math.floor( (pom.var.time_left / 60))
  local time_sec = pom.var.time_left - (time_min * 60)
  local str = string.format ("[ %s | %02d:%02d | #%02d ]", pom.var.curr_active_type, time_min, time_sec, pom.var.work_count)
  pom_menu:setTitle(str)
end

-- stop the clock
-- Stateful:
-- * Disabling once will pause the countdown
-- * Disabling twice will reset the countdown
-- * Disabling trice will shut down and hide the pomodoro timer
function pom_disable()

  local pom_was_active = pom.var.is_active
  pom.var.is_active = false

  if (pom.var.disable_count == 0) then
     if (pom_was_active) then
      pom_timer:stop()
    end
  elseif (pom.var.disable_count == 1) then
    pom.var.time_left         = pom.config.work_period_sec
    pom.var.curr_active_type  = "๐Ÿ„"
    pom_update_display()
  elseif (pom.var.disable_count >= 2) then
    if pom_menu == nil then
      pom.var.disable_count = 2
      return
    end

    pom_menu:delete()
    pom_menu = nil
    pom_timer:stop()
    pom_timer = nil
    pom_del_indicators()
  end

  pom.var.disable_count = pom.var.disable_count + 1

end

-- update pomodoro timer
local function pom_update_time()
  if pom.var.is_active == false then
    return
  else
    pom.var.time_left = pom.var.time_left - 1

    if (pom.var.time_left <= 0 ) then
      pom_disable()
      if pom.var.curr_active_type == "๐Ÿ„" then
        hs.alert.show("Work Complete!", 2)
        pom.var.work_count        =  pom.var.work_count + 1
        pom.var.curr_active_type  = "โ˜•๏ธ"
        pom.var.time_left         = pom.config.rest_period_sec
        pom.var.max_time_sec      = pom.config.rest_period_sec
      else
          hs.alert.show("Done resting.", 2)
          pom.var.curr_active_type  = "๐Ÿ„"
          pom.var.time_left         = pom.config.work_period_sec
          pom.var.max_time_sec      = pom.config.work_period_sec
      end
    end

    -- draw color bar indicator, if enabled.
    if (pom.config.enable_color_bar == true) then
      pom_draw_indicator(pom.var.time_left, pom.var.max_time_sec)
    end

  end
end

-- update menu display
local function pom_update_menu()
  pom_update_time()
  pom_update_display()
end

local function pom_create_menu(pom_origin)
  if pom_menu == nil then
    pom_menu = hs.menubar.new()
    pom.bar.c_left = hs.drawing.rectangle(hs.geometry.rect(0,0,0,0))
    pom.bar.c_used = hs.drawing.rectangle(hs.geometry.rect(0,0,0,0))
  end
end

-- start the pomodoro timer
function pom_enable()
  pom.var.disable_count = 0;
  if (pom.var.is_active) then
    return
  end

  pom_create_menu()
  pom_timer = hs.timer.new(1, pom_update_menu)

  pom.var.is_active = true
  pom_timer:start()
end

-- reset work count
-- TODO - reset automatically every day
function pom_reset_work()
  pom.var.work_count = 0;
end
-- Use examples:

-- init pomodoro -- show menu immediately
-- pom_create_menu()
-- pom_update_menu()

-- show menu only on first pom_enable
-- hs.hotkey.bind(hyper, '9', function() pom_enable() end)
-- hs.hotkey.bind(hyper, '0', function() pom_disable() end)

Translate

hs.hotkey.bind(hyper, '8', function() spoon.PopupTranslateSelection:translateSelectionPopup() end)

Cherry

-- hs.hotkey.bind(hyper, '9', '๐Ÿค“ > POMO ON', function() spoon.Cherry:start() end)
-- hs.hotkey.bind(hyper, '0', '๐Ÿ˜Œ > POMO OFF', function() spoon.Cherry:popup() end)
hs.hotkey.bind(hyper, '9', '๐Ÿค“ > POMO ON', function() pom_enable() end)
hs.hotkey.bind(hyper, '0', '๐Ÿ˜Œ > POMO OFF', function() pom_disable() end)

DOING Select Demo

https://xenodium.com/emacs-utilities-for-your-os/

local chooser = hs.chooser.new(function(choice)
      hs.alert.show(choice['text'])
end)

chooser:choices({
      {
         ["text"] = "Alfred\n",
         ["subText"] = "macOS only\n",
      },
      {
         ["text"] = "Quicksilver\n",
         ["subText"] = "macOS only\n",
      },
      {
         ["text"] = "Hammerspoon\n",
         ["subText"] = "macOS only\n",
      },
      {
         ["text"] = "Emacs\n",
         ["subText"] = "is everywhere :)\n",
      },
})

function toggle_chooser()
   chooser:show()
end

hs.hotkey.bind(hyper, 'c', toggle_chooser)

Misc

pyim

ln -s ~/Dropbox/Config/pyim ~/.emacs.d

Snippets

ln -s ~/Dropbox/Config/snippets ~/.emacs.d

bat

--theme="Nord"

wtfutil

ๅ‘ฝไปค่กŒ็š„ dashboard ๅทฅๅ…ท

wtf:
  colors:
    background: black
    border:
      focusable: darkslateblue
      focused: orange
      normal: gray
    checked: yellow
    highlight:
      fore: black
      back: gray
    rows:
      even: yellow
      odd: white
  grid:
    columns: [50, 50, 50]
    rows: [10, 10, 10]
  navigation:
    shortcuts: false

  refreshInterval: 1
  mods:
    clocks_a:
      colors:
        rows:
          even: "lightblue"
          odd: "white"
      enabled: true
      locations:
        Vancouver: "America/Vancouver"
        Toronto: "America/Toronto"
      position:
        top: 0
        left: 1
        height: 1
        width: 1
      refreshInterval: 15
      sort: "alphabetical"
      title: "Clocks A"
      type: "clocks"
    clocks_b:
      colors:
        rows:
          even: "lightblue"
          odd: "white"
      enabled: true
      locations:
        Avignon: "Europe/Paris"
        Barcelona: "Europe/Madrid"
        Dubai: "Asia/Dubai"
      position:
        top: 0
        left: 2
        height: 1
        width: 1
      refreshInterval: 15
      sort: "alphabetical"
      title: "Clocks B"
      type: "clocks"
    feedreader:
      enabled: true
      feeds:
      - https://news.ycombinator.com/rss
      feedLimit: 10
      position:
        top: 1
        left: 1
        width: 2
        height: 1
      updateInterval: 14400
    power:
      enabled: true
      position:
        top: 2
        left: 1
        height: 1
        width: 1
      refreshInterval: 15
      title: "โšก๏ธ"
    textfile:
      enabled: true
      filePath: "~/.config/wtf/config.yml"
      format: true
      position:
        top: 0
        left: 0
        height: 4
        width: 1
      refreshInterval: 30
      wrapText: false
    uptime:
      args: [""]
      cmd: "uptime"
      enabled: true
      position:
        top: 2
        left: 3
        height: 1
        width: 1
      refreshInterval: 30
      type: cmdrunner

    work_git:
      commitCount: 5
      commitFormat: "[forestgreen]%h [grey]%cd [white]%s [grey]%an[white]"
      dateFormat: "%H:%M %d %b %y"
      enabled: true
      position:
        top: 0
        left: 3
        height: 2
        width: 1
      refreshInterval: 8
      repositories:
      - "/Users/teddy/code/gfresh/fishclub"
      type: git

    personal_git:
      commitCount: 5
      commitFormat: "[forestgreen]%h [grey]%cd [white]%s [grey]%an[white]"
      dateFormat: "%H:%M %d %b %y"
      enabled: true
      position:
        top: 0
        left: 4
        height: 2
        width: 1
      refreshInterval: 8
      repositories:
      - "/Users/teddy/code/todo"
      type: git

    resourceusage:
      cpuCombined: false
      enabled: true
      position:
        top: 2
        left: 2
        height: 1
        width: 1
        refreshInterval: 1
      showCPU: true
      showMem: true
      showSwp: true

Xmodmap

swap control and capslock

clear lock
clear control
keycode 66 = Control_L
add control = Control_L
add Lock = Control_R

Server

ownCloud

ไฝฟ็”จ docker ่ตทไธ€ไธช็ฝ‘็›˜

ๅช่ฆ sudo docker-compose up

version: '2.1'

volumes:
  files:
    driver: local
  mysql:
    driver: local
  backup:
    driver: local
  redis:
    driver: local

services:
  owncloud:
    image: owncloud/server:${OWNCLOUD_VERSION}
    restart: always
    ports:
      - ${HTTP_PORT}:8080
    depends_on:
      - db
      - redis
    environment:
      - OWNCLOUD_DOMAIN=${OWNCLOUD_DOMAIN}
      - OWNCLOUD_DB_TYPE=mysql
      - OWNCLOUD_DB_NAME=owncloud
      - OWNCLOUD_DB_USERNAME=owncloud
      - OWNCLOUD_DB_PASSWORD=owncloud
      - OWNCLOUD_DB_HOST=db
      - OWNCLOUD_ADMIN_USERNAME=${ADMIN_USERNAME}
      - OWNCLOUD_ADMIN_PASSWORD=${ADMIN_PASSWORD}
      - OWNCLOUD_MYSQL_UTF8MB4=true
      - OWNCLOUD_REDIS_ENABLED=true
      - OWNCLOUD_REDIS_HOST=redis
    healthcheck:
      test: ["CMD", "/usr/bin/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - /home/teddy/Public:/mnt/data

  db:
    image: webhippie/mariadb:latest
    restart: always
    environment:
      - MARIADB_ROOT_PASSWORD=owncloud
      - MARIADB_USERNAME=owncloud
      - MARIADB_PASSWORD=owncloud
      - MARIADB_DATABASE=owncloud
      - MARIADB_MAX_ALLOWED_PACKET=128M
      - MARIADB_INNODB_LOG_FILE_SIZE=64M
    healthcheck:
      test: ["CMD", "/usr/bin/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - mysql:/var/lib/mysql
      - backup:/var/lib/backup

  redis:
    image: webhippie/redis:latest
    restart: always
    environment:
      - REDIS_DATABASES=1
    healthcheck:
      test: ["CMD", "/usr/bin/healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - redis:/var/lib/redis

openwrt

็›ดๆŽฅไฝฟ็”จ้•œๅƒ๏ผŒ ้•œๅƒ่ฝฌๆข้œ€่ฆไปฅ็ฎก็†ๅ‘˜่บซไปฝๆ‰ง่กŒ

simple static file server

/*
Serve is a very simple static file server in go
Usage:
	-p="8100": port to serve on
	-d=".":    the directory of static files to host
Navigating to http://localhost:8100 will display the index.html or directory
listing file.
*/
package main

import (
	"flag"
	"log"
	"net/http"
)

func main() {
	port := flag.String("p", "8100", "port to serve on")
	directory := flag.String("d", ".", "the directory of static file to host")
	flag.Parse()

	http.Handle("/", http.FileServer(http.Dir(*directory)))

	log.Printf("Serving %s on HTTP port: %s\n", *directory, *port)
	log.Fatal(http.ListenAndServe(":"+*port, nil))
}