나의 git globacl configuration. commit, checkout, cherry-pick 대신 ci, co, cp등을 사용하도록 하는 간단한 configuration. ~/.gitconfig의 내용이다.
[user]
email = {EMAIL}
name = {NAME}
[color]
ui = true
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "status"]
added = yellow
changed = green
untracked = cyan
[color "diff"]
whitespace = red reverse
meta = blue black bold
[core]
pager = less -F -XR -x2
excludesfile = /{User Home}/.gitignore_global
[push]
default = tracking
[receive]
denyCurrentBranch = warn
[branch]
autosetupmerge = true
[alias]
dag = log --graph --format='format:%C(yellow)%h%C(reset) %C(blue)\"%an\" <%ae>%C(reset) %C(magenta)%cr%C(reset)%C(auto)%d%C(reset)%n%s' --date-order
[commit]
template = /{User Home}/.stCommitMsg
[amazon]
append-cr-url = true
pull-request-by-default = true
pull-request-using-local-branch-name = true
[alias]
st = status
ts = status
ci = commit
br = branch
co = checkout
cp = cherry-pick
rb = rebase
irb = rebase -i HEAD~3
unstage = reset HEAD --
diffstat = diff -w --ignore-space-at-eol --stat -r
h = log --graph --all --decorate --since='2 week' --format=format:'%C(auto)%d%C(reset) %C(dim cyan)%h%C(reset) %C(dim green)(%ar)%C(reset) %C(dim yellow)%an%C(reset) %C(white)%s%C(reset)'
hl = log --graph --all --decorate --format=format:'%C(auto)%d%C(reset) %C(dim cyan)%h%C(reset) %C(dim green)(%ar)%C(reset) %C(dim yellow)%an%C(reset) %C(white)%s%C(reset)'
history = !"git lg1-specific"
DFS는 간단힌 recursion과 stack을 이용한 iteration으로 구현할 수 있다.
function(g, s) //g는 graph, s는 시작 vertex
visited를 false(미방문상태)로 초기화
시작점 s를 방문한 것으로 표시 //visited에서 s를 true로 설정
process(g, visited, s)
process(g, visited, s) //g는 graph, s는 시작 vertex
skip 조건 확인 // outOfBound, 이미 방문 했는지, 기타 skip 조건에 해당하는지
종료 조건 확인
인접 vertex loop
v <- next v
visited[v] = true
process(g, visited, v)
visited[v] = false // 이것은 모든 경우의 수를 테스트 하는 경우 사용
function(g, s) //g는 graph, s는 시작 vertex
stack 초기화
visited[]를 false(미방문상태)로 초기화
시작점 s를 방문한 것으로 표시 //visited[]에서 s를 true로 설정
stack에 s를 삽입//push
while(stack이 비어있지 않으면)
v <- stack에서 pop
for(u <- v와 인접한 vertex들)
if(skip 조건 확인) { // outOfBound, 이미 방문 했는지, 기타 skip 조건에 해당하는지
continue;
}
종료 조건 확인
방문으로 표시 //visited[]에서 u를 true로 설정
u를 stack에 push
BFS는 queue를 이용해 구현할 수 있다.
function(g, s) //g는 graph, s는 시작 vertex
queue 초기화
visited[]를 false(미방문상태)로 초기화
시작점 s를 방문한 것으로 표시 //visited[]에서 s를 true로 설정
stack에 s를 삽입//offer
while(queue가 비어있지 않으면)
size <- q.size()
while size-- > 0 // 현재 queue에 있는 아이템에 대해서 모두 (한 레벨씩)
v <- queue에서 poll
for(u <- v와 인접한 vertex들)
if(skip 조건 확인) { // outOfBound, 이미 방문 했는지, 기타 skip 조건에 해당하는지
continue;
}
종료 조건 확인
방문으로 표시 //visited[]에서 u를 true로 설정
u를 queue에 offer
Math.min(), Min.max()
Interger.Min_Value, Interger.Max_Value
Stack<int[]> stack = new Stack<>();
stack.push(new int[]{i, j});
int[] s = stack.pop();
int y = s[0];
int x = s[1];
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{i, j});
int[] s = queue.poll();
int y = s[0];
int x = s[1];
int[][] dirs = new int[][]{ {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
for (int[] dir : dirs) {
int nextY = dir[0];
int nextX = dir[1];
}
https://leetcode.com/problems/shortest-bridge/
두개의 island를 잊는 가장 짧은 다리를 구하는 것이다. 1이 육지이고 0이 바다이다. 1을 찾은 후 그것의 DFS를 그려서 모두 visited로 마크하고 queue에 집어 넣는다. 이제 queue에서 하나씩 빼내어 주변을 탐색한다. 만약 visited가 아니면 하나씩 돌면서 queue에 다시 넣고, 방문한 것으로 처리한다. 이것은 한 레벨씩 증가하면서 탐색을 하고 만약 값이 1인데 visited가 아닌 것을 만나면 이때의 step의 숫자를 출력한다.
아래는 BFS와 DFS를 사용한 것인데, DFS를 recursion으로 한것과 iteration으로 한것을 각각 구현하였다.
class Solution {
public int shortestBridge(int[][] A) {
int m = A.length, n = A[0].length;
boolean[][] visited = new boolean[m][n];
int[][] dirs = new int[][]{ {1, 0}, {-1, 0}, {0, 1}, {0, -1} };
Queue<int[]> q = new LinkedList<>();
boolean found = false;
// 1. dfs to find an island, mark it in `visited`
for (int i = 0; i < m; i++) {
if (found) {
break;
}
for (int j = 0; j < n; j++) {
if (A[i][j] == 1) {
dfs(A, visited, q, i, j, dirs);
found = true;
break;
}
}
}
// 2. bfs to expand this island
int step = 0;
while (!q.isEmpty()) {
int size = q.size();
while (size-- > 0) {
int[] cur = q.poll();
for (int[] dir : dirs) {
int i = cur[0] + dir[0];
int j = cur[1] + dir[1];
if (i >= 0 && j >= 0 && i < m && j < n && !visited[i][j]) {
if (A[i][j] == 1) {
return step;
}
q.offer(new int[]{i, j});
visited[i][j] = true;
}
}
}
step++;
}
return -1;
}
// DFS by recursion
private void dfs(int[][] A, boolean[][] visited, Queue<int[]> q, int i, int j, int[][] dirs) {
Stack<int[]> stack = new Stack<>();
visited[i][j] = true;
q.offer(new int[]{i, j}); //Insert all the 1s of island to the queue
stack.push(new int[]{i, j});
while (!stack.isEmpty()) {
int[] s = stack.pop();
int y = s[0];
int x = s[1];
for (int[] dir : dirs) {
int nextY = y + dir[0];
int nextX = x + dir[1];
if (nextY < 0 || nextX < 0 || nextY >= A.length || nextX >= A[0].length || visited[nextY][nextX] || A[nextY][nextX] == 0) {
continue;
}
visited[nextY][nextX] = true;
q.offer(new int[]{nextY, nextX}); //Insert all the 1s of island to the queue
stack.push(new int[]{nextY, nextX});
}
}
}
// DFS by recursion
private void dfs(int[][] A, boolean[][] visited, Queue<int[]> q, int i, int j, int[][] dirs) {
if (i < 0 || j < 0 || i >= A.length || j >= A[0].length || visited[i][j] || A[i][j] == 0) {
return;
}
visited[i][j] = true;
q.offer(new int[]{i, j}); //Insert all the 1s of island to the queue
for (int[] dir : dirs) {
dfs(A, visited, q, i + dir[0], j + dir[1], dirs);
}
}
}
leetcode에 있는 DFS관련한 문제를 풀어보자. 모두 hard difficulty의 문제들이다.
mac 터미널에서 오래 걸리는 작업을 실행할 경우 작업의 종료를 알기 위해서는 터미널의 해당 탭으로 가서 작업 상황을 확인해야 하는 번거로움이 있다. 이를 해결해보자.
터미널에서 수행한 작업이 끝나면 소리와 pop-up 창으로 작업 종료를 알 수 있게 만들자.
~/scripts folder 아래에 notification.sh 파일을 만들고 다음 내용을 붙여 넣는다.
alias noti="say \'task complete\';osascript -e 'display notification \"task complete\" with title \"terminal\"'"
.bashrc 또는 .zshrc 파일에 다음을 추가해서 터미널이 실행시 alias가 등록되도록 한다.
#Custom Scripts
. ~/scripts/notification.sh
터미널을 재시작하거나 또는 아래 명령을 통해 alias를 등록한다.
% source .bashrc
or
% source .zshrc
다음과 같이 사용한다.
% some_long_running_command && noti
이렇게 하면 some_long_running_command가 종료거나 중간에 에러가 발생해서 더이상 진행되지 못할 경우 소리와 pop-up window를 통해 그 상황을 바로 알 수 있다.
mac iterm2에서 ssh로 다른 host에 접속할 경우 새로 탭을 열어서 원하는 profile과 함께 연결되도록 하자.
mac iterm2에서 현재 폴더에서 gossh명령을 실행시키면 현재 탭이 아닌 다른 탭을 열어서 ssh로 정해진 host로 접속되도록 하자. 이때 되도록 알맞은 profile을 선택해서 실행하자.
~/scripts folder 아래에 remote.scpt를 만들고 아래 내용을 붙여 넣는다.
#!/usr/bin/osascript
tell application "iTerm 2" to activate
tell application "iTerm 2" to tell current window to create tab with profile "iterm_profile_name"
tell application "System Events" to tell process "iTerm 2" to keystroke "ssh ssh_address"
tell application "System Events" to tell process "iTerm 2" to key code 52
위에서 ssh_address대신 실제 접속할 host의 address를 붙여넣는다. 그리고, 미리 iterm에 profile을 만들어서 연결해주거나 또는 프로파일 관련 부분을 삭제한다.
~/scripts folder 아래에 remote.sh 파일을 만들고 다음 내용을 붙여 넣는다.
function gossh {
osascript /Users/hochshin/scripts/remote.scpt
}
.bashrc 또는 .zshrc 파일에 다음을 추가해서 터미널이 실행시 function이 등록되도록 한다.
#Custom Scripts
. ~/scripts/remote.sh
터미널을 재시작하거나 또는 아래 명령을 통해 alias를 등록한다.
% source .bashrc
or
% source .zshrc
다음과 같이 사용한다.
% gossh
이렇게 하면 새로운 탭이 원하는 profile과 함께 열리며 자동으로 ssh_address에 접속하게 된다.
mac iterm2에서 작업을 실행할 경우 새로 탭을 열어서 그 폴더로 이동해서 작업을 실행해야 하는 경우가 종종 있다. 이를 한번에 하도록 하자.
mac iterm2에서 현재 폴더에서 명령을 실행시킬 때 현재 탭이 아닌 다른 탭을 열어서 실행되도록 하자. 이때 되도록 알맞은 profile을 선택해서 실행하자.
~/scripts folder 아래에 newtab.scpt를 만들고 아래 내용을 붙여 넣는다.
#!/usr/bin/osascript
on run argv
tell application "iTerm 2" to activate
tell application "iTerm 2" to tell current window to create tab with profile "iTerm_Profile_name"
#tell application "iTerm 2" to create window with profile "iTerm_Profile_name"
tell application "System Events" to tell process "iTerm 2" to keystroke item 1 of argv
tell application "System Events" to tell process "iTerm 2" to key code 52
tell application "System Events" to tell process "iTerm 2" to keystroke item 2 of argv
tell application "System Events" to tell process "iTerm 2" to key code 52
end run
만약 새로운 탭이 아닌 새로운 윈도우 창을 열어서 실행시키고 싶은 경우 위의 주석처리한 줄의 주석 마크(#)를 지우고, 그 바로 위의 줄을 주석처리한다. 그리고 미리 iterm에 profile을 만들어서 연결해주거나 또는 프로파일 관련 부분을 삭제한다.
~/scripts folder 아래에 newtab.sh 파일을 만들고 다음 내용을 붙여 넣는다.
function run {
_d_curDir=`pwd`
osascript /Users/hochshin/scripts/newtab.scpt "cd $_d_curDir" "$1"
}
.bashrc 또는 .zshrc 파일에 다음을 추가해서 터미널이 실행시 function이 등록되도록 한다.
#Custom Scripts
. ~/scripts/newtab.sh
터미널을 재시작하거나 또는 아래 명령을 통해 alias를 등록한다.
% source .bashrc
or
% source .zshrc
다음과 같이 사용한다.
% run some_long_running_command
or argument가 있거나 여러 명령을 함께 수행하는 경우
% run "some_long_running_command arguments && noti"
이렇게 하면 새로운 탭이 열리며 some_long_running_command가 현재 명령이 실행하는 폴더에서 실행되게 된다.
mac이나 linux의 터미널에서 directory 이동을 편리하게 해주는 quick-directory-alias에 몇가지 기능을 추가해서 사용하고 있다. 나름 만족해서 사용하고 있어서 블로그를 통해 공유한다.
기존의 quick-directory-alias는 directory의 alias의 추가, 삭제, 확인이 가능하고, 무엇보다 그 alias로 바로 jump하는데 유용하다. alias의 자동완성 또한 지원한다.
기존 스크립트로도 사실 잘 사용하고 있지만, 자주 사용하다보니 아쉬운 기능이 있어 다음과 같은 기능을 추가했다.
자세한 내용은 아래 설명을 참조하자.
https://github.com/dakoo/shell-directory-management/blob/master/README.md
Note: Before running the following, change
RC_FILE
to match your preferred shell’s rc file, or any other file that you source when a new shell/terminal is created.
RC_FILE=~/.bashrc
SCRIPT_DIRECTORY=~/scripts
mkdir -p $SCRIPT_DIRECTORY
wget -O $SCRIPT_DIRECTORY/quick-directory-aliases.sh https://raw.githubusercontent.com/mcwoodle/shell-directory-management/master/quick-directory-aliases.sh
printf "\n. $SCRIPT_DIRECTORY/quick-directory-aliases.sh\n" >> $RC_FILE
. $RC_FILE
The default name for the command is “d”. Edit the
quick-directory-aliases.sh
script and change the function named()
to a name of your choosing.
% cd /any/really/long/or/short/directory/path/thats/hardoreasy/to/remember
% d + shortAliasName
Note: changes take effect immediately across terminals/shells.
Also you can add a tag to the alias.
% cd /any/really/long/or/short/directory/path/thats/hardoreasy/to/remember
% d + shortAliasName "some tag or comment"
% d shortAliasName
% pwd
/any/really/long/or/short/directory/path/thats/hardoreasy/to/remember
% d - shortAliasName
% d
workspace = /home/mcwoodle/workspaces/someWorkspaceDirectory -> workspace
bin = /usr/bin -> bin folder
nhl = /home/mcwoodle/go/leafs/go -> .
% d c all
% d ?
% d e workspace ij
% d e workspace st
% d e workspace op
% d e workspace pwd
If the command consists of multiple words, wrap it with double quotes.
% d e workspace "ls -al"
You could modify the following block of the script.
if $_d_excuteCommand;
then
_d_cmd=`printf "$_d_aliasRow" | sed -e "s,.* = \(.*\) -> .*,\1,"`
printf "cd $_d_cmd\n"
case "$2" in
ij) /usr/local/bin/idea $_d_cmd;;
st) stree $_d_cmd;;
op) open $_d_cmd;;
*) "$2" $_d_cmd;;
esac
return 1
fi
Autocomplete is currently only supported using bash and zsh (or any script supporting complete\compgen
or compctl
built-ins).
Installation is automatic and works like any other bash/zsh tab based autocomplete.