Rakudoc
Rakudoc (aka Pod6)
코드에 문서를 붙일 때, 보기 좋은 형식으로 정리하면서도 소스 안에 자연스럽게 녹아들길 원할 거예요. Raku는 그런 문서 작성을 위한 마크업 언어인 Rakudoc을 제공해요. 예전에는 Pod6라고 불렸죠.
본문
Pod6는 이제 RakuDoc V1로 알려져 있고, 새로운 <RakuDoc V2 명세>가 존재해요.
Rakudoc은 사용하기 쉬운 마크업 언어예요. 언어 문서 작성, 프로그램·모듈 문서화, 그리고 다른 종류의 문서 구성에도 쓸 수 있어요.
모든 Rakudoc 문서는 =begin pod로 시작해서 =end pod로 끝나야 해요. 이 두 구분자 사이의 모든 것은 처리되어 문서 생성에 사용돼요.
=begin pod
A very simple Rakudoc document
=end pod
블록 구조 (Block structure)
Rakudoc 문서는 여러 Rakudoc 블록으로 구성될 수 있어요. 블록을 정의하는 방법은 네 가지예요: delimited(구분), paragraph(문단), abbreviated(축약), declarator(선언자). 처음 세 가지는 같은 결과를 내지만 네 번째는 달라요. 특정 문서화 작업에 가장 편리한 형태를 쓰면 돼요.
Delimited 블록
Delimited 블록은 =begin과 =end 마커로 둘러싸여 있어요. 둘 다 유효한 Raku 식별자가 뒤따르는데, 이것이 블록의 typename이에요. 전부 소문자인 typename(예: =begin head1)이나 전부 대문자인 typename(예: =begin SYNOPSIS)은 예약되어 있어요. 유효한 블록을 만들려면 =begin/=end 줄의 들여쓰기가 같아야 해요. 그렇지 않으면 오류나 예상치 못한 결과가 발생해요.
=begin head1
Top Level Heading
=end head1
설정 정보 (Configuration information)
typename 다음에 나오는 =begin 마커 줄의 나머지는 블록의 설정 정보로 취급돼요. 이 정보는 블록 유형에 따라 서로 다른 방식으로 사용되지만, 항상 Raku 스타일 옵션 페어로 지정돼요. 즉 다음 중 하나로요:
| 값이... | 이렇게 지정 | 또는 이렇게 | 또는 이렇게 |
|===================|==============|=============|=============|
| List | :key[$e1, $e2, ...] | :key($e1, $e2, ...) | :key<$e1 $e2 ...> |
| Hash | :key{$k1=>$v1, $k2=>$v2} | | |
| Boolean (true) | :key | :key(True) | :key[True] |
| Boolean (false) | :!key | :key(False) | :key[False] |
| String | :key<str> | :key('str') | :key("str") |
| Int | :key(42) | :key[42] | :42key |
| Number | :key(2.3) | :key[2.3] | |
여기서 $e1, $e2, ...은 String, Int, Number, Boolean 타입의 리스트 요소예요. 리스트는 혼합 요소 타입을 가질 수 있어요. 한 요소짜리 리스트는 요소 타입(String, Int, Number, Boolean)으로 변환된다는 점에 주의하세요. 필요하면 큰 정수(big integer)도 쓸 수 있어요.
해시의 경우 $k1, $k2, ...은 Str 타입의 키이고 $v1, $v2, ...은 String, Int, Number, Boolean 타입의 값이에요.
문자열은 단일·이중 따옴표로 구분돼요. 문자열 밖에서는 공백이 유의미하지 않아요. 해시 키는 유의미한 공백을 포함하지 않는 한 따옴표로 구분할 필요가 없어요. 각괄호 안에 입력된 문자열은 그 안에 공백이 있으면 리스트가 돼요.
모든 옵션 키와 값은 Rakudoc이 프로그래밍 언어가 아니라 명세 언어이므로 상수여야 해요. 특히 옵션 값은 클로저가 될 수 없어요. 다양한 Raku 페어 표기법에 대한 자세한 내용은 <Synopsis 2>를 보세요.
설정 섹션은 이후 줄에서 확장될 수 있어요. 각 후속 줄은 첫 번째 가상 열(virtual column)에 =로 시작해야 해요. 즉 Rakudoc 블록 선언의 =와 수직으로 정렬되어야 하고, 그 뒤에 가로 공백 문자를 하나 이상 가져야 해요. 예:
=for head1 :a-first-line-key<firstvalue> :another-first-line-key<xyz>
= :a-second-line-key(42)
= :a-third-line-key<third>
Content for the header block
이 옵션들 중 일부는 미리 정해진 값을 가져요. 특히 :numbered는 블록 항목이나 줄에 번호가 매겨질 것임을 지정해요.
=for defn :numbered
We
Need
Numbers
say $=pod[0].config<numbered>; # OUTPUT: «True»
이 설정 옵션은 해시 기호로 축약할 수 있어요:
=para #
We
Need
Numbers
say $=pod[0].config<numbered>; # OUTPUT: «1»
Paragraph 블록
Paragraph 블록은 =for 마커로 시작해서 다음 Pod6 지시문이나 첫 번째 빈 줄에서 끝나요. =for 마커 뒤에는 블록의 typename이 오고, 선택적으로 위에서 설명한 delimited 블록에서처럼 설정 데이터를 붙일 수 있어요.
=for head1
Top Level Heading
Abbreviated 블록
Abbreviated 블록은 = 기호로 시작하며, 바로 뒤에 블록의 typename이 와요. 그 뒤의 모든 데이터가 블록의 내용이므로 abbreviated 블록에는 설정 데이터를 지정할 수 없어요. 블록은 다음 Rakudoc 지시문이나 첫 번째 빈 줄에서 끝나요.
=head1 Top level heading
Declarator 블록
Declarator 블록은 특정 타입이 없고 대신 어떤 소스 코드에 붙는다는 점에서 다른 것들과 달라요.
Declarator 블록은 특수 주석 #| 또는 #=로 도입돼요. 이들은 바로 뒤에 공백이나 여는 중괄호가 와야 해요. 공백이 뒤따르면 블록은 줄 끝에서 끝나요. 여는 중괄호가 하나 이상 뒤따르면 블록은 짝이 맞는 닫는 중괄호 시퀀스에서 끝나요.
#|로 시작하는 블록은 그 뒤에 있는 코드에 붙고, #=로 시작하는 블록은 그 앞에 있는 코드에 붙어요.
Declarator 블록은 소스 코드에 붙기 때문에 클래스, 역할(role), 서브루틴, 일반적으로 어떤 문장이나 블록도 문서화하는 데 쓸 수 있어요.
WHY 메서드는 이 클래스·역할·서브루틴 등에 사용해서 붙어 있는 Pod6 값을 반환할 수 있어요.
#| Base class for magicians
class Magician {
has Int $.level;
has Str @.spells;
}
#| Fight mechanics
sub duel(Magician $a, Magician $b) {
}
#= Magicians only, no mortals.
say Magician.WHY; # OUTPUT: «Base class for magicians»
say &duel.WHY.leading; # OUTPUT: «Fight mechanics»
say &duel.WHY.trailing; # OUTPUT: «Magicians only, no mortals.»
이 선언들은 여러 블록으로 확장될 수 있어요:
#|( This is an example of stringification:
* Numbers turn into strings
* Regexes operate on said strings
* C<with> topicalizes and places result into $_
)
sub search-in-seq( Int $end, Int $number ) {
with (^$end).grep( /^$number/ ) {
.say for $_<>;
}
}
#=« Uses
* topic
* decont operator
»
()나 «» 같은 짝이 맞는 괄호 구성을 사용하면 주석을 여러 줄로 확장할 수 있어요. 이 형식은 보통 raku --doc로는 다중 줄 표시로 변환되지 않아요. 다만 Rakudo 2020.01 릴리스부터는 선행 declarator 블록에만 특수 환경 변수 RAKUDO_POD_DECL_BLOCK_USER_FORMAT 을 정의하면 그렇게 할 수 있는 방법이 있어요. 그 값이 설정되면 raku를 --doc 옵션으로 실행할 때 선행 declarator 블록의 텍스트를 원래 형식으로 보여줘야 해요. 그 기능에 대한 테스트는 <S26-documentation/block-leading-user-format.t> 파일에서 볼 수 있어요.
블록 타입 (Block types)
Rakudoc은 다양한 표준 블록 타입을 제공해요.
제목 (Headings)
제목은 =headN으로 정의할 수 있어요. 여기서 N은 0보다 커요 (예: =head1, =head2, …).
=head1 A top level heading
=head2 A second level heading
=head3 A third level heading
일반 문단 (Ordinary paragraphs)
일반 문단은 현재 중첩 수준에서 문서로 형식화될 텍스트로 구성돼요. 공백은 압축되고, 줄은 채워지며, 특수 인라인 마크업이 적용돼요.
일반 문단은 각각 비공백 문자로 시작하는 한 줄 이상의 연속된 텍스트 줄로 구성돼요. 문단은 첫 번째 빈 줄이나 블록 지시문에서 끝나요. 예:
=head1 This is a heading block
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled. It is terminated by
the first blank line.
This is another ordinary paragraph.
Its text will also be squeezed and
short lines filled. It is terminated by
the trailing directive on the next line.
=head2 This is another heading block
This is yet another ordinary paragraph,
at the first virtual column set by the
previous directive
일반 문단은 명시적 마커나 구분자가 필요 없어요. 대안으로 명시적 =para 마커를 써서 문단을 명시적으로 표시할 수도 있어요.
=para
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled.
추가로 더 긴 =begin para와 =end para 형태도 쓸 수 있어요. 예:
=begin para
This is an ordinary paragraph.
Its text will be squeezed and
short lines filled.
This is still part of the same paragraph,
which continues until an...
=end para
앞선 예에서 보듯 delimited =begin para·=end para 블록 안에서는 빈 줄이 보존돼요.
코드 블록 (Code blocks)
코드 블록은 재정렬(re-justification) 없이, 공백 압축 없이, 인라인 형식 코드를 인식하지 않고 렌더링해야 하는 소스 코드를 지정하는 데 쓰여요. 보통 코드·마크업·기타 텍스트 명세의 예를 보여주는 데 쓰이며, 고정 폭 글꼴로 렌더링돼요.
코드 블록은 각각 공백 문자로 시작하는 한 줄 이상의 텍스트로 암시적으로 지정될 수 있어요. 암시적 코드 블록은 그 뒤에 빈 줄에서 끝나요. 예:
This ordinary paragraph introduces a code block:
my $name = 'John Doe';
say $name;
코드 블록은 =begin code와 =end code로 감싸 명시적으로 정의할 수도 있어요:
=begin code
my $name = 'John Doe';
say $name;
=end code
입출력 블록 (I/O blocks)
Rakudoc은 프로그램의 입력과 출력을 지정하는 블록을 제공해요. =input 블록은 재정렬이나 공백 압축 없이 렌더링해야 하는 사전 형식화된 키보드 입력을 지정해요. =output 블록은 역시 재정렬·공백 압축 없이 렌더링해야 하는 사전 형식화된 터미널·파일 출력을 지정해요.
리스트 (Lists)
비순서 리스트 (Unordered lists)
Rakudoc의 리스트는 일련의 =item 블록으로 지정돼요. 예:
The three suspects are:
=item Happy
=item Sleepy
=item Grumpy
위는 다음과 같이 렌더링돼요:
- Happy
- Sleepy
- Grumpy
정의 리스트 (Definition lists)
용어나 명령을 정의하는 리스트는 HTML의 DL 리스트와 동등한 =defn을 사용해요.
=defn Happy
When you're not blue.
=defn Blue
When you're not happy.
위는 다음과 같이 렌더링돼요:
Happy : When you're not blue.
Blue : When you're not happy.
다중 레벨 리스트 (Multi-level lists)
리스트는 다중 레벨일 수 있으며, 각 레벨의 항목은 =item1, =item2, =item3 등의 블록으로 지정돼요. =item은 =item1의 축약형이에요. 예:
=item1 Animal
=item2 Vertebrate
=item2 Invertebrate
=item1 Phase
=item2 Solid
=item2 Liquid
=item2 Gas
- Animal
- Vertebrate
- Invertebrate
- Phase
- Solid
- Liquid
- Gas
다중 문단 리스트 (Multi-paragraph lists)
=item 블록의 delimited 형태(=begin item·=end item)를 사용하면 여러 문단을 포함하는 항목을 지정할 수 있어요. 예:
Let's consider two common proverbs:
=begin item
I<The rain in Spain falls mainly on the plain.>
This is a common myth and an unconscionable slur on the Spanish
people, the majority of whom are extremely attractive.
=end item
=begin item
I<The early bird gets the worm.>
In deciding whether to become an early riser, it is worth
considering whether you would actually enjoy annelids
for breakfast.
=end item
As you can see, folk wisdom is often of dubious value.
테이블 (Tables)
테이블 관련 문서는 <이 페이지>를 확인하세요.
Rakudoc 주석 (Rakudoc comments)
Rakudoc 주석은 Rakudoc 렌더러가 무시하는 주석이에요. 주석은 메타문서화(문서를 문서화하기)에 유용해요. 한 줄 주석은 =comment 마커를 써요:
=comment Add more here about the algorithm
여러 줄 주석은 delimited comment 블록을 써요:
=begin comment
This comment is
multi-line.
=end comment
암시적 블록도 쓸 수 있어요:
=comment
This comment is
multi-line.
B<this> is visible
시맨틱 블록 (Semantic blocks)
전부 대문자인 블록 typename은 표준 문서화, 출판, 소스 구성 요소, 메타 정보의 지정을 위해 예약되어 있어요.
=NAME
=AUTHOR
=VERSION
=TITLE
=SUBTITLE
형식 코드 (Formatting codes)
형식 코드는 텍스트 조각에 인라인 마크업을 추가하는 방법을 제공해요. 모든 Rakudoc 형식 코드는 단일 대문자 뒤에 단일·이중 각괄호 세트가 바로 이어지는 형태예요. 유니코드 이중 각괄호도 쓸 수 있어요. 형식 코드는 다른 형식 코드를 중첩할 수 있어요.
사용 가능한 코드는 B, C, E, I, K, L, N, P, R, T, U, V, X, Z예요.
Bold
텍스트를 굵게 하려면 B< >로 감싸요. Raku is B<awesome> → Raku is awesome.
Italic
I< >로 감싸요. Raku is I<awesome> → Raku is awesome.
Underlined
U< >로 감싸요. Raku is U<awesome> → Raku is awesome.
Code
텍스트를 코드로 표시하고 그대로(verbatim) 취급하려면 C< >로 감싸요. C<my $var = 1; say $var;> → my $var = 1; say $var;. 감싼 코드 안에 짝이 안 맞는 >가 있으면 C« »로 감싸요.
Links
링크를 만들려면 L< >로 감싸요. Raku homepage L<https://raku.org> → Raku homepage. 선택적으로 세로 막대를 사용해 레이블과 대상을 분리할 수 있어요. L<Raku homepage|https://raku.org> → Raku homepage.
상대 URL은 프로젝트 기준에 상대적이어요. 예를 들어 language 폴더의 다른 페이지로 링크할 수 있어요. 여기서는 선택적 프래그먼트를 사용해 제목으로 링크해요: L<Structure|/language/about#Structure>.
현재 문서의 프래그먼트로 링크를 지정할 수도 있어요: L<Comments|#Comments>. 마지막으로 URL 스타일 링크(예: L<Some reference|path/to/filename>) 외에도 모듈 스타일 표기(L<Some reference|path::to::filename>)도 동작해요.
배치 링크 (Placement links)
이 코드는 Pod::To::HTML에서 구현되지 않지만 Pod::To::BigPage에서는 부분적으로 구현돼요.
두 번째 종류의 링크 P<>(배치 링크)는 반대 방향으로 동작해요. 초점을 다른 문서로 보내는 대신, 다른 문서의 내용을 자신의 것으로 흡수하게 해요. 즉 P<> 형식 코드는 URI를 받아서 (가능하면) 해당 문서의 내용을 코드 자리 자리에 인라인으로 삽입해요.
P<> 코드는 문서 세트의 표준 요소를 재사용 가능한 컴포넌트로 분리해서 여러 문서에 직접 통합할 때 편리해요. 예:
=COPYRIGHT
P<file:/shared/docs/std_copyright.pod>
=DISCLAIMER
P<http://www.MegaGigaTeraPetaCorp.com/std/disclaimer.txt>
렌더러가 배치 링크의 외부 데이터 소스를 찾거나 접근할 수 없으면 경고를 발행하고 URI를 어떤 형태로든 직접 렌더링해야 해요. 어쩌면 외부 링크로요. 배치 링크에서
Comments
주석은 절대 렌더링되지 않는 텍스트예요. 만들려면 Z< >로 감싸요. Raku is awesome Z<Of course it is!> → Raku is awesome.
Notes
노트는 각주로 렌더링돼요. N< >로 감싸요. Raku is multi-paradigmatic N<Supporting Procedural, Object Oriented, and Functional programming>.
키보드 입력 (Keyboard input)
K< >로 감싸요. Enter your name K<John Doe> → Enter your name John Doe.
Replaceable
R<> 형식 코드는 포함된 텍스트가 replaceable item(자리표시자, 메타신택틱 변수)임을 지정해요. 문법이나 명세의 구성 요소 중 결국 실제 값으로 대체될 것을 나타내는 데 쓰여요. 예: The basic C<ln> command is: C<ln> R<source_file> R<target_file>.
터미널 출력 (Terminal output)
T< >로 감싸요. Hello T<John Doe> → Hello John Doe.
유니코드 (Unicode)
Rakudoc 문서에 유니코드 코드 포인트나 HTML5 문자 참조를 포함하려면 E< >로 감싸요.
E< >는 숫자를 감쌀 수 있는데, 이는 원하는 코드 포인트의 십진 유니코드 값으로 취급돼요. 명시적 진수의 숫자도 감쌀 수 있어요(이진·팔진·십진·십육진 표기의 Raku 표기를 사용). 유니코드 코드 포인트 이름도 감쌀 수 있어요.
Raku makes considerable use of the E<laquo> and E<raquo> characters.
Raku makes considerable use of the E<171> and E<187> characters.
Raku makes considerable use of the E<0xAB> and E<0xBB> characters.
Raku makes considerable use of the E<LEFT-POINTING DOUBLE ANGLE QUOTATION MARK> and E<RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK> characters.
위는 Raku makes considerable use of the « and » characters.으로 렌더링돼요. E<171;nbsp;raquo>처럼 ;로 구분된 목록에서 여러 코드 포인트를 제공할 수도 있어요.
Verbatim text
이 코드는 Pod::To::HTML에서 구현되지 않지만 Pod::To::BigPage에서는 구현돼요. V<> 형식 코드는 그 전체 내용을 verbatim으로 취급하며, 그 안의 모든 겉보기 형식 코드를 무시해요. 다만 V<> 코드는 내용이 파싱되는 방식만 바꾸지 렌더링되는 방식은 바꾸지 않아요. 즉 내용은 여전히 일반 텍스트처럼 감싸지고 형식화되며, V<> 코드를 둘러싼 형식 코드의 효과는 여전히 내용에 적용돼요.
인덱싱 용어 (Indexing terms)
X<> 코드에 감싼 것은 무엇이든 인덱스 엔트리예요. 코드의 내용은 문서에 형식화될 뿐 아니라 (대소문자 구분 없는) 인덱스 엔트리로도 사용돼요. 인덱스 텍스트와 인덱스 엔트리를 세로 막대로 구분해 서로 다르게 지정할 수도 있어요: An B<X<array|arrays>> .... 두 부분 형태에서 인덱스 엔트리는 막대 뒤에 오며 대소문자를 구분해요. 쉼표로 인덱싱 레벨을 구분해 계층적 인덱스 엔트리를 지정할 수 있어요: X<array|B<arrays, definition of>>. 하나의 인덱스 텍스트에 세미콜론으로 두 개 이상의 엔트리를 지정할 수도 있어요. 인덱스 텍스트는 비어 있을 수도 있어서 "zero-width" 인덱스 엔트리를 만들어요: B<X<|puns, deliberate>>.
Pod 렌더링 (Rendering Pod)
HTML
Pod에서 HTML을 생성하려면 <Pod::To::HTML 모듈>이 필요해요. 아직 설치되지 않았다면 zef install Pod::To::HTML로 설치해요. 설치 후 터미널에서 다음 명령을 실행해요:
raku --doc=HTML input.rakudoc > output.html
Markdown
Pod에서 Markdown을 생성하려면 <Pod::To::Markdown 모듈>이 필요해요. 아직 설치되지 않았다면 zef install Pod::To::Markdown로 설치해요. 설치 후:
raku --doc=Markdown input.rakudoc > output.md
Text
Pod에서 텍스트를 생성하려면 기본 Pod::To::Text 모듈을 사용할 수 있어요. 터미널에서:
raku --doc=Text input.rakudoc > output.txt
=Text 부분을 생략할 수도 있어요:
raku --doc input.rakudoc > output.txt
프로그램에 Rakudoc을 직접 내장하고, 다중 MAIN 서브루틴으로 전통적인 유닉스 커맨드라인 "--man" 옵션을 추가할 수도 있어요:
=begin pod
=head1 OVERVIEW
Hello, world!
=end pod
use Pod::To::Text;
multi MAIN(Bool :$man!) {
say pod2text $=pod;
}
multi MAIN() {
say "HELLO";
}
이제 myprogram --man은 Rakudoc이 man 페이지로 렌더링된 것을 출력해요.
Pod 접근 (Accessing Pod)
Raku 프로그램 안에서 Rakudoc 문서에 접근하려면 <variables 섹션>에 문서화된 특수 = 트와이질을 사용해야 해요. = 트와이질은 Rakudoc 구조에 대한 인트로스펙션을 제공하며, Rakudoc 문서의 전체 구조에 접근할 수 있는 Pod::Block 트리 루트를 제공해요.
예시로, 다음 코드는 자신의 Rakudoc 문서를 인트로스펙트해요:
=begin pod
=head1 This is a head1 title
This is a paragraph.
=head2 Subsection
Here some text for the subsection.
=end pod
for $=pod -> $pod-item {
for $pod-item.contents -> $pod-block {
$pod-block.raku.say;
}
}
위는 다음 출력을 만들어요:
Pod::Heading.new(level => 1, config => {}, contents => [Pod::Block::Para.new(config => {}, contents => ["This is a head1 title"])]);
Pod::Block::Para.new(config => {}, contents => ["This is a paragraph."]);
Pod::Heading.new(level => 2, config => {}, contents => [Pod::Block::Para.new(config => {}, contents => ["Subsection"])]);
Pod::Block::Para.new(config => {}, contents => ["Here some text for the subsection."]);