Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quarto: new parser #3677

Merged
merged 3 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tmain/list-subparsers-all.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ OpenAPI Yaml base <> sub {bidirectional}
PlistXML XML base <> sub {bidirectional}
PythonLoggingConfig Iniconf base <> sub {bidirectional}
QtMoc C++ base <> sub {bidirectional}
Quarto Markdown base <= sub {dedicated}
R6Class R base <> sub {bidirectional}
RMarkdown Markdown base <= sub {dedicated}
RSpec Ruby base => sub {shared}
Expand Down
3 changes: 3 additions & 0 deletions Units/parser-quarto.r/simple.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--sort=no
--extras=+{guest}
--fields=+{end}{line}{language}
2 changes: 2 additions & 0 deletions Units/parser-quarto.r/simple.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
defun input.qmd /^#| label: defun$/;" l line:2 language:Quarto end:6
f input.qmd /^def f():$/;" f line:4 language:Python end:5
7 changes: 7 additions & 0 deletions Units/parser-quarto.r/simple.d/input.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```{python}
#| label: defun
#| fig-cap: "Define a function"
def f():
pass
```

3 changes: 3 additions & 0 deletions Units/parser-quarto.r/unexecuted-block.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--sort=no
--extras=+{guest}
--fields=+{end}{line}{language}
4 changes: 4 additions & 0 deletions Units/parser-quarto.r/unexecuted-block.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
__anon53b260bc0100 input.qmd /^```{python}$/;" l line:1 language:Quarto end:4
__anon53b260bc0200 input.qmd /^```{{python}}$/;" l line:6 language:Quarto end:9
f input.qmd /^def f():$/;" f line:2 language:Python end:3
g input.qmd /^def g():$/;" f line:7 language:Python end:8
9 changes: 9 additions & 0 deletions Units/parser-quarto.r/unexecuted-block.d/input.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
```{python}
def f():
pass
```

```{{python}}
def g():
pass
```
6 changes: 3 additions & 3 deletions Units/parser-rmarkdown.r/frontmatter.d/expected.tags
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
S1 input.rmd /^# S1$/;" chapter line:4 language:Markdown end:17
xyX input.rmd /^```{r xyX}$/;" chunklabel line:6 language:RMarkdown extras:subparser
xyX input.rmd /^```{r xyX}$/;" chunklabel line:6 language:RMarkdown extras:subparser end:16
S2 input.rmd /^# S2$/;" chapter line:18 language:Markdown end:28
__anon9d4e183a0100 input.rmd /^```{r, cache = TRUE, dependson = "xyX"}$/;" chunklabel line:20 language:RMarkdown extras:subparser,anonymous
__anon9d4e183a0200 input.rmd /^```{python}$/;" chunklabel line:24 language:RMarkdown extras:subparser,anonymous
__anon9d4e183a0100 input.rmd /^```{r, cache = TRUE, dependson = "xyX"}$/;" chunklabel line:20 language:RMarkdown extras:subparser,anonymous end:22
__anon9d4e183a0200 input.rmd /^```{python}$/;" chunklabel line:24 language:RMarkdown extras:subparser,anonymous end:28
S3 input.rmd /^# S3$/;" chapter line:29 language:Markdown end:30
x input.rmd /^x <- 1$/;" globalVar line:8 language:R extras:guest end:8
foo input.rmd /^foo <- function () {$/;" function line:9 language:R extras:guest end:12
Expand Down
6 changes: 3 additions & 3 deletions Units/parser-rmarkdown.r/simple-rmarkdown.d/expected.tags
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
S1 input.rmd /^# S1$/;" chapter line:1 language:Markdown end:14
xyX input.rmd /^```{r xyX}$/;" chunklabel line:3 language:RMarkdown extras:subparser
xyX input.rmd /^```{r xyX}$/;" chunklabel line:3 language:RMarkdown extras:subparser end:13
S2 input.rmd /^# S2$/;" chapter line:15 language:Markdown end:25
__anon4a45a9700100 input.rmd /^```{r, cache = TRUE, dependson = "xyX"}$/;" chunklabel line:17 language:RMarkdown extras:subparser,anonymous
__anon4a45a9700200 input.rmd /^```{python}$/;" chunklabel line:21 language:RMarkdown extras:subparser,anonymous
__anon4a45a9700100 input.rmd /^```{r, cache = TRUE, dependson = "xyX"}$/;" chunklabel line:17 language:RMarkdown extras:subparser,anonymous end:19
__anon4a45a9700200 input.rmd /^```{python}$/;" chunklabel line:21 language:RMarkdown extras:subparser,anonymous end:25
S3 input.rmd /^# S3$/;" chapter line:26 language:Markdown end:27
x input.rmd /^x <- 1$/;" globalVar line:5 language:R extras:guest end:5
foo input.rmd /^foo <- function () {$/;" function line:6 language:R extras:guest end:9
Expand Down
1 change: 1 addition & 0 deletions docs/news.rst
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ The following parsers have been added:
* PythonLoggingConfig
* QemuHX *optlib*
* QtMoc
* Quarto *Markdown based subparser*
* R
* R6Class *R based subparser*
* Rake *Ruby based subparser*
Expand Down
1 change: 1 addition & 0 deletions main/parsers_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
PythonLoggingConfigParser, \
QemuHXParser, \
QtMocParser, \
QuartoParser, \
RMarkdownParser, \
RParser, \
RakeParser, \
Expand Down
53 changes: 45 additions & 8 deletions parsers/markdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,26 +212,53 @@ static void getFootnoteMaybe (const char *line)
vStringDelete (footnote);
}

static bool extractLanguageForCodeBlock (const char *langMarker,
vString *codeLang)
static markdownSubparser * extractLanguageForCodeBlock (const char *langMarker,
vString *codeLang)
{
subparser *s;
bool r = false;
subparser *s = NULL;
bool b = false;
markdownSubparser *r = NULL;

foreachSubparser (s, false)
{
markdownSubparser *m = (markdownSubparser *)s;
enterSubparser(s);
if (m->extractLanguageForCodeBlock)
r = m->extractLanguageForCodeBlock (m, langMarker, codeLang);
b = m->extractLanguageForCodeBlock (m, langMarker, codeLang);
leaveSubparser();
if (r)
if (b)
{
r = m;
break;
}
}

return r;
}

static void notifyCodeBlockLine (markdownSubparser *m, const unsigned char *line)
{
subparser *s = (subparser *)m;
if (m->notifyCodeBlockLine)
{
enterSubparser(s);
m->notifyCodeBlockLine (m, line);
leaveSubparser();
}
}

static void notifyEndOfCodeBlock (markdownSubparser *m)
{
subparser *s = (subparser *)m;

if (m->notifyEndOfCodeBlock)
{
enterSubparser(s);
m->notifyEndOfCodeBlock (m);
leaveSubparser();
}
}

static void findMarkdownTags (void)
{
vString *prevLine = vStringNew ();
Expand All @@ -249,6 +276,7 @@ static void findMarkdownTags (void)

nestingLevels = nestingLevelsNewFull (0, fillEndField);

markdownSubparser *marksub = NULL;
while ((line = readLineFromInputFile ()) != NULL)
{
int lineLen = strlen ((const char*) line);
Expand Down Expand Up @@ -296,7 +324,8 @@ static void findMarkdownTags (void)
startLineNumber = startSourceLineNumber = lineNum + 1;

vStringClear (codeLang);
if (! extractLanguageForCodeBlock (langMarker, codeLang))
marksub = extractLanguageForCodeBlock (langMarker, codeLang);
if (! marksub)
{
vStringCopyS (codeLang, langMarker);
vStringStripLeading (codeLang);
Expand All @@ -309,7 +338,12 @@ static void findMarkdownTags (void)
if (vStringLength (codeLang) > 0
&& startLineNumber < endLineNumber)
makePromise (vStringValue (codeLang), startLineNumber, 0,
endLineNumber, 0, startSourceLineNumber);
endLineNumber, 0, startSourceLineNumber);
if (marksub)
{
notifyEndOfCodeBlock(marksub);
marksub = NULL;
}
}

lineProcessed = true;
Expand All @@ -330,6 +364,9 @@ static void findMarkdownTags (void)
lineProcessed = true;
}

if (marksub)
notifyCodeBlockLine (marksub, line);

/* code block or comment */
if (inCodeChar || inComment)
lineProcessed = true;
Expand Down
37 changes: 37 additions & 0 deletions parsers/markdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,46 @@ typedef struct sMarkdownSubparser markdownSubparser;

struct sMarkdownSubparser {
subparser subparser;
/* ```something
---^ The rest of string is passed as LANGMARKER.

A sub parser analyses LANGMARKER.
If the sub parser can extract a name of language from LANGMARKER,
the parser puts the name to LANGNAME, and returns true.
If not, return false.

e.g.

```{python}

Fot this input, ctags pases "{python}" as LANGMARKER. */
bool (* extractLanguageForCodeBlock) (markdownSubparser *s,
const char *langMarker,
vString *langName);

/* ```something
...
<code block>
...
```

ctags passes each LINE in the code block to the sub parser
that returns true when ctags calls extractLanguageForCodeBlock()
with the sub parser. */
void (* notifyCodeBlockLine) (markdownSubparser *s,
const unsigned char *line);

/* ```something
...
codeblock
...
```
^ The end of code block.

ctags notifies the sub parser that the end of code block
is found.
*/
void (* notifyEndOfCodeBlock) (markdownSubparser *s);
};

#endif
Loading