#TIL #csharp 객체 이니셜라이저 (object initializers)

Cat cat = new Cat()
cat.Age = 10;
cat.Name = "Fluffy";

unity가 아무리 옛날 .NET Framework 3.5를 지원한다고 해도 그렇지. 이건 이상하다. 이렇게 불편할 리가 없는데.

Cat cat = new Cat { Age = 10, Name = "Fluffy" };

그래. 최소한 이거지. 객체 이니셜라이저를 사용할 수 있다. unity에서도 사용할 수 있다. 객체 이니셜라이저는 C# 3.0에 추가됐고 .NET Framework 3.5에 포함됐다.

참고 - 객체 및 컬렉션 이니셜라이저(C# 프로그래밍 가이드) - docs.microsoft.com

#TIL #linux CR LF를 LF로 바꿔야 할 때는 dos2unix

standard_init_linux.go:175: exec user process caused "no such file or directory"

docker for windows에서 본 에러 메시지. 뭐가 문제인 거지?

root@bbfb0023c2df:/usr/local/bin# ./entrypoint.sh
bash: ./entrypoint.sh: /bin/bash^M: bad interpreter: No such file or directory

조물딱 거리다 보니 다른 에러 메시지가 나왔다. 아~ 라인엔딩 때문이다. windows 환경에서 작성한 entrypoint.sh 파일을 docker 컨테이너에서 실행한다. LF만 쓰는 리눅스에서 CR LF를 사용한 파일을 실행하다 문제가 생긴 거.

RUN apt-get update && apt-get install -y dos2unix
COPY entrypoint.sh /entrypoint.sh
RUN dos2unix /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

복사 후 dos2unix 프로그램으로 라인엔딩을 바꿔주면 된다.

참고 - Docker for Windows: Dealing With Windows Line Endings - willi.am/blog

#TIL #bash #batch 스크립트 파일이 있는 부모 디렉터리로 cd

cd "$(dirname "$0")/.."

bash에서는 $0 스페셜 파라미터를 사용한다.

$ cat script_path_test
echo "$(dirname "$0")/.."

이런 스크립트 파일이 있을 때, 어디에서 실행하느냐에 따라 출력 결과가 달라진다.

$ pwd
/c/Users/ohyecloudy/test

$ ./script_path_test
./..

스크립트 파일이 있는 디렉터리에서 실행한 결과.

$ pwd
/c/Users/ohyecloudy

$ test/script_path_test
test/..

부모 디렉터리에서 실행한 결과.

다른 디렉터리에서 실행할 수 있기 때문에 그냥 cd .. 명령을 쓰면 안 된다. 대신 $0 스페셜 파라미터를 사용하면 된다. 위 예에선 각각 ./script_path_test, test/script_path_test로 확장한다. dirname을 사용해 디렉터리를 추출하고 부모 디렉터리로 cd를 하면 스크립트 파일이 있는 부모 디렉터리로 작업 디렉터리를 바꿀 수 있다.

pushd %cd%
cd %~dp0..
popd

batch 스크립트에서는 %~dp0 스페셜 파라미터를 사용하면 된다. 스크립트 환경 분리가 안 돼서 현재 디렉터리를 push, pop 해줘야 스크립트 실행 후 작업 디렉터리가 바뀌지 않는다.

참고

#TIL #batch #bash redirection 연산자를 앞으로 당겨도 되잖아

 >result.txt echo first line
>>result.txt echo second line
>>result.txt echo third line

이렇게 써도 되다니. 칼각에 마음이 평온해진다. batch, bash 모두 된다. 자연스럽게 공백 방지도 된다.

참고 - The redirection can come anywhere on the line, and you can use that to get rid of the spaces - The Old New Thing

#TIL #vim b 키와 방향은 같지만 도착지는 다른 ge 키

| ge | Backward to the end of word |
| gE | Backward to the end of WORD |

몰라도 불편한 건 없다. 낮은 사용 빈도 때문인지 키도 두 개 눌러야 한다. 몰라서 나쁠 건 없다. 특히 매크로 정의할 때, 몰라도 어찌 할 수 있지만 번거로운 건 사실이다.

evil backward-word en|d

ge

evil backward-wor|d end

ge

evil backward|-word end

이전 위치에서 gE

evi|l backward-word end

참고

#TIL #vim 이전 visual mode로 선택한 영역을 다시 선택하려면

V 키를 눌러 visual mode 진입 후 영역을 선택한다. < 키를 눌러 왼쪽으로 옮긴다. 에이 2< 키 누를걸. 한 번 더 밀어야 하잖아. 이때 gv 키를 눌러 이전과 똑같은 영역을 선택한다. 그리고 다시 < 키를 누르면 된다.

참고

#TIL #vim 변경이 일어난 곳을 기억한다

vim은 변경이 일어난 곳을 기억한다. 끝이 안 보이는 문서에서 마지막 수정한 위치로 가려고 u 키로 undo를 해서 가던 무식한 날들은 이제 안녕.

| :changes | Print the change list                              |
| g;       | Go to [count] older position in change list        |
| g,       | Go to [count] newer cursor position in change list |

참고

#TIL #bash 큰따옴표 안에 있는 물결표(Tilde)는 확장 안 된다

$ MD="~/My Documents"
$ echo "${MD}"
~/My Documents
$ cd "${MD}"
bash: cd: ~/My Documents: No such file or directory

물결표(~)는 HOME 환경 변수값으로 확장한다. 그런데, 확장이 안 된다. 이상하다.

$ MD=~/My\ Documents
$ echo "${MD}"
/c/Users/ohyecloudy/My Documents
$ cd "${MD}"
$ pwd
/c/Users/ohyecloudy/My Documents

큰따옴표(double quotes) 안에 있으면 확장 안 되는 것 아닐까? 큰따옴표를 쓰니 물결표 그대로 쓰이는 것 같다.

Enclosing characters in double quotes (‘”’) preserves the literal value of all characters within the quotes, with the exception of ‘$’, ‘`’, ‘\’, and, when history expansion is enabled, ‘!’. - 3.1.2.3 Double Quotes

아~ 확장되는 문자 중에 물결표는 없어요.

$ MD="$HOME/My Documents"
$ cd "${MD}"
$ pwd
/c/Users/ohyecloudy/My Documents

큰따옴표 안 쓰면 된다. 아니면 물결표 대신 $HOME 환경 변수값으로 확장해주면 된다.

참고

#TIL #bash 셸 파라미터 확장 - 공백을 포함한 path

$ cd My\ Documents
$ pwd
/c/Users/ohyecloudy/My Documents

parameter에 공백이 있는 경로를 할당하고 cd 명령어 인자로 넘기려면?

$ MD=My\ Documents
$ cd $MD
bash: cd: too many arguments
$ cd "$MD"
$ pwd
/c/Users/ohyecloudy/My Documents

path가 공백을 포함하려면 큰따옴표(double quotes)로 감싸야 한다.

$ MD="My Documents"
$ cd $MD
bash: cd: too many arguments
$ cd "$MD"

이건 또 왜? 이미 큰따옴표로 감쌌잖아. 그냥 써도 될 것 같은데. 셸 파라미터 확장(shell parameter expansions) 후에 뭔가 일어나는 것 같다.

After the preceding expansions, all unquoted occurrences of the characters ‘\’, ‘’’, and ‘”’ that did not result from one of the above expansions are removed. - 3.5.9 Quote Removal

맞네. \, ‘, ” 문자는 제거된다. 그래서 큰따옴표로 감싸야 한다.

참고

#TIL #vim goto file, goto definition

g d 키는 로컬 정의(local definition)로 이동하고 g D 키는 글로벌 정의로 이동한다. 소스 코드에서 많이 사용한다. g d 키를 눌러서 정의를 보고 Ctrl o 키를 눌러서 원래 자리로 온다.

g f 키는 파일 이름처럼 생긴 문자열이 커서에 있으면 파일을 연다. g F 키는 더 친절하다. eval.c:10 식으로 라인 번호가 있으면 라인까지 데려다준다.

참고

#TIL #vim rain 위에서 * 키는 rainbow를 찾지 못한다

/ddiary/assets/2018-01-31-til-vim-search-unbounded-word-forward-00.gif

* 키는 /\<rain\> 검색 패턴으로 찾는다. \<, \> 패턴으로 감쌌기 때문에 단어가 일치해야 한다. 반면 g * 키는 /rain 검색 패턴으로 찾는다. 단어 일치를 검사하지 않는다.

참고 - Search patterns - vim.wikia.com

#TIL #macOS 스크린샷 찍는 단축키

Command(⌘)-Shift-3

전체 화면 찍기.

Command(⌘)-Shift-4

영역을 선택할 수 있다.

Command(⌘)-Shift-4, 스페이스 바

이걸 이번에 알았다. 메뉴막대 혹은 윈도우를 깔끔하게 찍을 수 있다.

참고 - Mac에서 스크린샷을 찍는 방법 - support.apple.com

#TIL #elixir iex에서 모듈을 재컴파일하는 법

iex> c("lib/worker.ex")

모듈을 정의한 파일을 컴파일했는데

iex> r(Test.Worker)

그냥 모듈 이름만 넣어도 된다. iex에서 로드할 때, 파일 정보도 기록하는 모냥.

M-x alchemist-iex-reload-module

emacs를 사용한다면 alchemist를 놓칠 수 없다. 편집하던 버퍼에서 함수를 호출하면 된다.

링크 - IEx.Helpers.r/1

#TIL #elixir 생각해보니 MapSet.subset?

MapSet.size(MapSet.difference(a, b)) == 0

잠깐. 이상하잖아.

MapSet.subset?(a, b)

뭘 저렇게 복잡하게 하려고 했나? MapSet.subset?/2 함수랑 같다.

#TIL #elixir ! 문자로 끝나는 함수 이름 컨벤션

Enum.fetch/2, Enum.fetch!/2 함수의 차이점은? 에러 발생 여부다

iex> Enum.fetch([2, 4, 6], 2)
{:ok, 6}

iex> Enum.fetch([2, 4, 6], 4)
:error

:error 리턴. 튜플 리턴이 기본값.

iex> Enum.fetch!([2, 4, 6], 2)
6

iex> Enum.fetch!([2, 4, 6], 4)
** (Enum.OutOfBoundsError) out of bounds error

에러 발생. 원소값 리턴이 기본값.

느낌표 따위 함수 이름으로 얼마든지 쓸 수 있다. 에러를 일으키는 함수 이름 끝에는 ! 문자를 붙인다.

#TIL #vim #visual_studio #emacs jump forward, backword 키바인딩 통일

vim은 커서 위치를 jump list로 관리한다. `, /, n 등 커맨드로 이동할 때, 위치를 기록해 놓는다. 커서 위치를 바꾼다고 모두 저장하진 않는다. hjkl 키처럼 깨작깨작 움직이는 커맨드는 제외한다. jump list에 기록된 위치를 CTRL-I 키와 CTRL-O 키로 앞뒤로 점프할 수 있다.

:ju[mps]

jump list를 볼 수 있다.

visual studio

View.NavigateBackward, View.NavigateForward 동작을 각각 CTRL-O, CTRL-I 키로 바인딩하면 똑같이 사용할 수 있다.

emacs evil-mode

| C-i    | evil-jump-forward  |
| C-o    | evil-jump-backward |
| :jumps | evil-show-jumps    |

emacs에서는 evil-mode 패키지를 설치하면 사용할 수 있다.

#TIL #xcode #jenkins CocoaPods를 사용하니 링크 에러가

unity ios 빌드는 xcode 워크스페이스 혹은 프로젝트를 만드는 것까지 책임진다. xcode로 바이너리를 뽑아내는 건 사용자가 해야 한다.

firebase를 추가하고 난 후에 링크 에러가 생겼다. 알고 보니 CocoaPods 때문. firebase에서 사용한다.

워크스페이스가 아니라 프로젝트로 빌드했기 때문이다. CocoaPods는 디펜던시를 빌드하는 Pods 프로젝트를 추가해서 워크스페이스를 구성해준다. 워크스페이스는 visual studio의 솔루션 같은 거다. 프로젝트 상위 개념. Jenkins Xcode Plugin에서 Xcode Workspace File 값을 채워줬다.

#TIL #git 충돌(conflict) 났다. 한쪽 변경 사항을 적용하고 싶은데, ours야 theirs야?

충돌(conflict)이 발생했을 때, 한쪽 변경 사항을 적용하고 싶다. 주로 테스트 데이터 커밋이다. 코드 변경 사항과 섞여 들어가지 않게 데이터만 따로 커밋을 만든다. push 전에 걸러내면 되니깐. 중앙 저장소에 있는 커밋을 로컬로 가져왔는데, 데이터에서 충돌이 발생했다. 이걸 머지? 노노 양 많으면 토한다. 그럴 땐, 한쪽을 그냥 사용하면 된다.

$ git pull
$ git checkout feature-1
$ git rebase master

충돌이 발생했다.

$ git checkout --ours  <file>
$ git checkout --theirs  <file>

둘 중 어떤 걸 사용하면 되나? 난 이거 할 때마다 헷갈린다. 왜냐면 feature-1은 내가 작업한 거니깐 이게 ours 처럼 느껴지기 때문이다.

하지만 땡! rebase를 할 때, master가 부모고 feature-1 브랜치의 커밋을 하나씩 자식으로 연결한다. 즉 master가 ours고 feature-1이 theirs가 된다.

정리한다고 했지만, 막상 사용할 때가 되면 또 헷갈린다. rebase –continue 명령을 하기 전에 확인하는 습관만 들이면 좀 헷갈려도 괜찮다. 확인하고 진행하니깐.

참고

#TIL #git head 커밋 아이디?

$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
246e5b84c1492682434d22448a22273b60e958aa

재미로 한두 번 이렇게 찾지 매번 이렇게 찾아야 하나?

$ git rev-parse HEAD
246e5b84c1492682434d22448a22273b60e958aa
$ git rev-parse --short HEAD
246e5b8
$ git rev-parse --short HEAD~1
42389d9

rev-parse 명령을 사용하면 된다.

참고 - https://git-scm.com/docs/git-rev-parse

#TIL #git gitignore에 / 문자가 앞에 있고 없고

$ cat .gitignore
*.c
$ git status --ignored --short
!! main.c
!! test/main_test.c

/ 문자가 없다. 모든 디렉터리를 대상으로 glob 패턴에 일치하는 파일을 무시한다.

$ cat .gitignore
/*.c
$ git status --ignored --short
?? test/main_test.c
!! main.c

/ 문자가 있다. 그것도 제일 앞에. pathname 시작과 일치해야 한다. 그 뒤에 따라오는 * 문자는 / 문자 같은 경로 구분자(path separator)와는 매치가 안 된다. 그래서 main.c 파일은 매치되고 test/main_test.c 파일은 매치 안 된다. 즉, 매치되는 main.c 파일만 무시된다.

참고 - https://git-scm.com/docs/gitignore