gofmt에도 비슷한 서식 유도 동작이 있었던 것으로 기억하고, 그런 포매터가 rustfmt보다 더 마음에 듦
그래도 포매터가 아예 없는 것보다는 어떤 형태의 서식 자동화라도 있는 편이 낫다고 봄
“포매터가 없는 것보다 뭐든 있는 게 낫다”는 말은 그냥 넘기기 어렵다 자동 포매터는 평범함을 강제하고, 서식을 못 쓰는 사람들을 끌어올리지만 잘 쓰는 사람들도 끌어내린다
협업할 때 다른 사람들이 원하거나 그들의 개인 서식 규율을 신뢰하기 어렵다면 쓰겠지만, 혼자 작업할 때는 절대 쓰지 않음
내 취향도 있고 포매터의 취향도 있는데, 둘은 화해 불가능하게 다르다
다만 이 글에서 보여준 내용 자체는 인상적임
그 문장은 Fiddler on the Roof에서 중매쟁이 Yente가 “나쁜 남편이라도—신이여 막아주소서—남편이 없는 것보다는 낫다!”라고 한 대사를 떠올리게 함
기억하기로 Elm 포매터도 비슷하게 동작했고, 원래 서식을 고려하지 않는 포매터들에 비해 꽤 좋게 느껴졌음
일부 C++ 프로젝트에서 clang-format을 쓰는데 끔찍함
버전 간 안정성이 너무 낮아서 clang-format 업그레이드가 코드 모든 줄을 건드리는 서식 커밋으로 이어짐
포매터가 없는 것보다 나은지 정말 확신이 안 듦
예전에는 “어떤 포매터든 없는 것보다 낫다”고 오래 생각했지만, 최근에는 완전히 생각이 바뀜
자동 포매터는 주로 풀 리퀘스트에서 자전거 헛간 논쟁을 없애는 사람 문제를 해결함
그런데 이제 에이전트형 개발로 넘어가면서 그 문제는 점점 덜 중요해짐
지금 여러 프로젝트에서 기계가 대부분의 작업을 하고 있는데, 그렇게 되면 포매터를 돌리지 않는 편이 더 낫다는 쪽으로 느껴짐
Python에서 명령줄 인자를 만들 때는 튜플을 리스트에 스플랫하는 방식을 좋아해서, 글의 마지막 예제는 이렇게 쓸 것 같음
마지막으로 봤을 때 zig fmt에는 80열 제한을 100열 제한 대신 쓰도록 설정하는 방법이 없었는데, 아직도 그런가?
하루에 여러 시간 작업하면 눈이 덜 피로해서 터미널 글꼴 크기를 키워 쓰는데, 80열과 100열 차이는 vim 분할 두 개와 nerd tree를 나란히 둘 수 있느냐를 가름함
zig fmt에는 열 제한이 없음
포매터가 전혀 없던 팀에 rigid formatter를 도입한 사람으로서, 가끔은 수동으로 서식에 영향을 줄 수 있는 능력이 그리움
그런 면에서 Zig가 유연한 건 정말 멋짐
훌륭하다!
이런 식의 TS/JS 포매터가 있을까? maplibre-gl을 쓰는 프로젝트가 있는데 스타일 명세 표현식이 가끔 너무 과하게 서식화돼서 아무것도 안 보임
지금은 포매터 사용을 멈췄지만, 디버깅하고 복사하고 주석 처리하다 보니 코드가 지저분해지고 있음
어쩌면 Zig 포매터를 다른 언어도 포매팅하도록 만들 수 있을지도 :)
Prettier에도 비슷한 기능이 있지만, 구체적으로는 객체 리터럴에 한정되고 “한 줄에 전부”와 “각 요소를 다른 줄에” 중에서만 고를 수 있음
예를 들어 한 줄에 네 요소씩 두라고 포매터에 지시할 방법은 없음
또한 객체 리터럴이 너무 길어지면 입력 텍스트가 어떻게 되어 있든 Prettier가 결국 “각 요소를 다른 줄에” 형식으로 바꿔버림
가벼운 방식의 포매터, 사실상 줄바꿈만 하는 포매터에는 실망한 적이 있어서, 더 엄격한 예시 안에서 이런 유연성을 갖는다는 발상이 부럽고 마음에 듦 :p
최근 fedi에서 비례폭 글꼴로 Lisp를 작성하고 서식화하는 질문에 답하면서, 의미 있는 공백을 쓰는 s-expression 변형들, 즉 wisp, Readable/Sweet expressions, SRFI 119와 110을 짚었음
이 문법 계열은 선택적 중위 표기 확장을 활용해 줄바꿈에 대한 제어권을 일부 돌려준다는 관찰도 덧붙였음
흥미로운 설계지만 마음에 드는지는 잘 모르겠음
내 포매터에서는 다르게 처리함: 포매터가 후행 쉼표를 무시하고 서식을 결정한 뒤, 여러 줄로 나뉘면 항상 후행 쉼표를 추가하고 한 줄이면 항상 후행 쉼표를 제거함
그래서 “유도”는 못 하지만 f(1, 2, 3)은 후행 쉼표 유무나 토큰 사이 공백의 양과 종류와 관계없이 일관되게 포매팅됨
어느 정도의 유도는 필요함
예를 들어 긴 리스트 리터럴 [<expr1>, <expr2>, ..., <expr100>]이 있으면 대부분의 포매터는 각 표현식을 한 줄에 하나씩 두겠지만, 가능한 한 많이 한 줄에 넣고 싶을 수 있음
이 둘을 후행 쉼표로 결정하는 건 이상하다고 보고, 일반적으로는 선택지가 2개가 아니라 N개일 수 있음
이런 목적에는 속성이 더 잘 맞는다고 생각함
예를 들어 이미 있을지도 모르지만, 문장 앞에 #[rustfmt::list_layout(flow)] 같은 것을 붙여 해당 문장 안의 리스트 리터럴 서식에 영향을 주는 식이 가능함
유도가 너무 많으면 전체 생태계의 코드 서식을 일관되게 만들고 코드 리뷰를 쉽게 하는 포매터의 목적을 해치므로 제한된 경우에만 해야 함
긴 리스트 리터럴은 정말 필요한 예라고 봄
내 프로젝트에도 테스트 기대값 리뷰에 서식이 도움이 되는 예가 있는데, 여기가 그렇다
Dart 포매터에도 다른 “유도” 동작이 하나 떠오름: 긴 리스트 리터럴에서 주석 줄을 추가해 줄들을 그룹화할 수 있음
예를 들어 [1, 2, 3, ..., 1000]이면 각 요소를 한 줄에 하나씩 두지만, 수동으로 이렇게 그룹화할 수 있음
[1, 2, 3, 4, 5, //
6, 7, 8, 9, 10, //
...]
이런 기능을 의도적으로 넣은 것인지, 주석 처리 방식에서 나온 부산물인지는 모르겠음
그 방식이 정확히 rustfmt의 동작이고, 그게 미치게 만듦
가끔은 줄 길이 제한을 넘기더라도 함수 호출을 나누지 않는 편이 더 읽기 좋은 경우가 있고, 거기에 대한 내 판단을 반영할 수 있으면 좋겠음
떠오르는 한 가지 사례는 OpenGL임
보통 하나의 리소스를 수정하거나 사용하면서, 예를 들어 텍스처 초기화처럼 gl.* 호출을 연속으로 많이 하게 되는데 rustfmt는 “줄이 너무 김. 줄을 쪼개야 함”이라는 로봇 같은 목적 말고는 아무 감각 없이 밀어버림
이 예제는 동작을 보여주기 위한 인위적인 것이고 실제 rustfmt 동작과 완전히 같지는 않음
줄도 그렇게 길지는 않음
지금 휴대폰으로 쓰고 있어서 100% 정확한 예제를 만들 도구가 없음
이런 식으로 이어지는 gl.tex_parameteri 호출을 여러 줄로 쪼개는데, 사실 각 호출은 한 줄에 완전히 펼쳐 두는 편이 더 낫다
열이 맞춰지면 두 줄의 차이를 훨씬 쉽게 찾을 수 있기 때문임
쪼갠 버전은 시각적 근접성이 떨어지고 읽기 더 어렵다
눈으로 두 줄을 쉽게 비교할 수 없게 됨
또 줄을 문자 수 제한 안에 맞게 포매팅할 수 없을 때 완전히 실패하는 우스운 일도 생김
컴파일러 코드를 쓰며 문자열 리터럴로 진단 메시지를 만들 때 이런 일이 자주 일어나는데, 메시지가 꽤 길어질 수 있음 rustfmt는 이를 어떻게 나눌지 몰라서 포기하고 해당 문장 전체를 포매팅하지 않음
흔히 이런 식임
match something {
// ... match arms above this one ...
_ => emit_diagnostic(&mut state, "This is a very long message to try and illustrate the problem. Help: please consult a doctor.")
}
여기서 emit_diagnostic 호출이 표현식일 뿐이라는 이유로 전체 match 문의 포매팅을 포기하는데, 그냥 어리석다
내 코드를 최대 100열로 밀어붙이려 하지 않았다면 전부 피할 수 있었음
끝부분의 코멘트를 보고 나처럼 찾아봐야 했던 사람을 위해 적자면, ++는 배열 연결 연산자임
그래서 배열을 두 개로 나누면 서로 다르게 포매팅할 수 있음
Lobste.rs 의견들
gofmt에도 비슷한 서식 유도 동작이 있었던 것으로 기억하고, 그런 포매터가rustfmt보다 더 마음에 듦그래도 포매터가 아예 없는 것보다는 어떤 형태의 서식 자동화라도 있는 편이 낫다고 봄
자동 포매터는 평범함을 강제하고, 서식을 못 쓰는 사람들을 끌어올리지만 잘 쓰는 사람들도 끌어내린다
협업할 때 다른 사람들이 원하거나 그들의 개인 서식 규율을 신뢰하기 어렵다면 쓰겠지만, 혼자 작업할 때는 절대 쓰지 않음
내 취향도 있고 포매터의 취향도 있는데, 둘은 화해 불가능하게 다르다
다만 이 글에서 보여준 내용 자체는 인상적임
그 문장은 Fiddler on the Roof에서 중매쟁이 Yente가 “나쁜 남편이라도—신이여 막아주소서—남편이 없는 것보다는 낫다!”라고 한 대사를 떠올리게 함
clang-format을 쓰는데 끔찍함버전 간 안정성이 너무 낮아서
clang-format업그레이드가 코드 모든 줄을 건드리는 서식 커밋으로 이어짐포매터가 없는 것보다 나은지 정말 확신이 안 듦
자동 포매터는 주로 풀 리퀘스트에서 자전거 헛간 논쟁을 없애는 사람 문제를 해결함
그런데 이제 에이전트형 개발로 넘어가면서 그 문제는 점점 덜 중요해짐
지금 여러 프로젝트에서 기계가 대부분의 작업을 하고 있는데, 그렇게 되면 포매터를 돌리지 않는 편이 더 낫다는 쪽으로 느껴짐
Python에서 명령줄 인자를 만들 때는 튜플을 리스트에 스플랫하는 방식을 좋아해서, 글의 마지막 예제는 이렇게 쓸 것 같음
마지막으로 봤을 때
zig fmt에는 80열 제한을 100열 제한 대신 쓰도록 설정하는 방법이 없었는데, 아직도 그런가?하루에 여러 시간 작업하면 눈이 덜 피로해서 터미널 글꼴 크기를 키워 쓰는데, 80열과 100열 차이는
vim분할 두 개와nerd tree를 나란히 둘 수 있느냐를 가름함zig fmt에는 열 제한이 없음포매터가 전혀 없던 팀에 rigid formatter를 도입한 사람으로서, 가끔은 수동으로 서식에 영향을 줄 수 있는 능력이 그리움
그런 면에서 Zig가 유연한 건 정말 멋짐
훌륭하다!
이런 식의 TS/JS 포매터가 있을까?
maplibre-gl을 쓰는 프로젝트가 있는데 스타일 명세 표현식이 가끔 너무 과하게 서식화돼서 아무것도 안 보임지금은 포매터 사용을 멈췄지만, 디버깅하고 복사하고 주석 처리하다 보니 코드가 지저분해지고 있음
어쩌면 Zig 포매터를 다른 언어도 포매팅하도록 만들 수 있을지도 :)
예를 들어 한 줄에 네 요소씩 두라고 포매터에 지시할 방법은 없음
또한 객체 리터럴이 너무 길어지면 입력 텍스트가 어떻게 되어 있든 Prettier가 결국 “각 요소를 다른 줄에” 형식으로 바꿔버림
가벼운 방식의 포매터, 사실상 줄바꿈만 하는 포매터에는 실망한 적이 있어서, 더 엄격한 예시 안에서 이런 유연성을 갖는다는 발상이 부럽고 마음에 듦 :p
최근 fedi에서 비례폭 글꼴로 Lisp를 작성하고 서식화하는 질문에 답하면서, 의미 있는 공백을 쓰는 s-expression 변형들, 즉 wisp, Readable/Sweet expressions, SRFI 119와 110을 짚었음
이 문법 계열은 선택적 중위 표기 확장을 활용해 줄바꿈에 대한 제어권을 일부 돌려준다는 관찰도 덧붙였음
흥미로운 설계지만 마음에 드는지는 잘 모르겠음
내 포매터에서는 다르게 처리함: 포매터가 후행 쉼표를 무시하고 서식을 결정한 뒤, 여러 줄로 나뉘면 항상 후행 쉼표를 추가하고 한 줄이면 항상 후행 쉼표를 제거함
그래서 “유도”는 못 하지만
f(1, 2, 3)은 후행 쉼표 유무나 토큰 사이 공백의 양과 종류와 관계없이 일관되게 포매팅됨어느 정도의 유도는 필요함
예를 들어 긴 리스트 리터럴
[<expr1>, <expr2>, ..., <expr100>]이 있으면 대부분의 포매터는 각 표현식을 한 줄에 하나씩 두겠지만, 가능한 한 많이 한 줄에 넣고 싶을 수 있음이 둘을 후행 쉼표로 결정하는 건 이상하다고 보고, 일반적으로는 선택지가 2개가 아니라 N개일 수 있음
이런 목적에는 속성이 더 잘 맞는다고 생각함
예를 들어 이미 있을지도 모르지만, 문장 앞에
#[rustfmt::list_layout(flow)]같은 것을 붙여 해당 문장 안의 리스트 리터럴 서식에 영향을 주는 식이 가능함유도가 너무 많으면 전체 생태계의 코드 서식을 일관되게 만들고 코드 리뷰를 쉽게 하는 포매터의 목적을 해치므로 제한된 경우에만 해야 함
긴 리스트 리터럴은 정말 필요한 예라고 봄
내 프로젝트에도 테스트 기대값 리뷰에 서식이 도움이 되는 예가 있는데, 여기가 그렇다
Dart 포매터에도 다른 “유도” 동작이 하나 떠오름: 긴 리스트 리터럴에서 주석 줄을 추가해 줄들을 그룹화할 수 있음
예를 들어
[1, 2, 3, ..., 1000]이면 각 요소를 한 줄에 하나씩 두지만, 수동으로 이렇게 그룹화할 수 있음이런 기능을 의도적으로 넣은 것인지, 주석 처리 방식에서 나온 부산물인지는 모르겠음
rustfmt의 동작이고, 그게 미치게 만듦가끔은 줄 길이 제한을 넘기더라도 함수 호출을 나누지 않는 편이 더 읽기 좋은 경우가 있고, 거기에 대한 내 판단을 반영할 수 있으면 좋겠음
떠오르는 한 가지 사례는 OpenGL임
보통 하나의 리소스를 수정하거나 사용하면서, 예를 들어 텍스처 초기화처럼
gl.*호출을 연속으로 많이 하게 되는데rustfmt는 “줄이 너무 김. 줄을 쪼개야 함”이라는 로봇 같은 목적 말고는 아무 감각 없이 밀어버림이 예제는 동작을 보여주기 위한 인위적인 것이고 실제
rustfmt동작과 완전히 같지는 않음줄도 그렇게 길지는 않음
지금 휴대폰으로 쓰고 있어서 100% 정확한 예제를 만들 도구가 없음 이런 식으로 이어지는
gl.tex_parameteri호출을 여러 줄로 쪼개는데, 사실 각 호출은 한 줄에 완전히 펼쳐 두는 편이 더 낫다열이 맞춰지면 두 줄의 차이를 훨씬 쉽게 찾을 수 있기 때문임
쪼갠 버전은 시각적 근접성이 떨어지고 읽기 더 어렵다
눈으로 두 줄을 쉽게 비교할 수 없게 됨
또 줄을 문자 수 제한 안에 맞게 포매팅할 수 없을 때 완전히 실패하는 우스운 일도 생김
컴파일러 코드를 쓰며 문자열 리터럴로 진단 메시지를 만들 때 이런 일이 자주 일어나는데, 메시지가 꽤 길어질 수 있음
rustfmt는 이를 어떻게 나눌지 몰라서 포기하고 해당 문장 전체를 포매팅하지 않음흔히 이런 식임 여기서
emit_diagnostic호출이 표현식일 뿐이라는 이유로 전체match문의 포매팅을 포기하는데, 그냥 어리석다내 코드를 최대 100열로 밀어붙이려 하지 않았다면 전부 피할 수 있었음
끝부분의 코멘트를 보고 나처럼 찾아봐야 했던 사람을 위해 적자면,
++는 배열 연결 연산자임그래서 배열을 두 개로 나누면 서로 다르게 포매팅할 수 있음