code - вставка фрагментов кода
Описание
Вставка фрагментов кода из файлов проекта.
Формат:
@@code file=FILENAME part=PARTNAME lang=LANG title=ЗАГОЛОВОК
где:
file
- имя файла из проекта, откуда вставлять текст. Может быть абсолютным и относительным (см: Ссылки). Если содержит'#'
, то считается что указывает на файл с groovy-классом (или java-классом) для генерации текста файла (см: Генерация файлов для вставки). Кроме того, может быть именем класса.part
- имя поименнованного фрагмента из файла (см. ниже). Если не указан, вставляется весь текст файлаlang
- имя языка для подсветки синтаксиса. Если не указано, определяется по расширению файлаtitle
- заголовок. Обычно тут указывается имя файла.mode
- режим вывода при генерации (см: Генерация файлов для вставки).
Особые соглашения по имени файла:
- если файл не абсолютный (не имеет
/
в начале), то он последовательно ищется в каталогах:_inc/ИМЯ-ФАЙЛА-СТАТЬИ
_inc/ИМЯ_ФАЙЛА_СТАТЬИ
_inc
- относительно текущего каталога
- если файл - это имя класса, то ищется файл
.java
или.groovy
, соответствующий классу
Например, мы имеем статью folder1/my-doc1.md
и в ней описана вставка кода:
@@code file=file1.java
Тогда будут искаться следующие файлы:
folder1/_inc/my-doc1/file.java
folder1/_inc/my_doc1/file.java
folder1/_inc/file.java
folder1/file.java
Первый найденный будет использован.
В случае, если в качестве файла указано имя класса:
@@code file=pak1.pak2.Class1
Будут искаться следующие файлы:
/pak1/pak2/Class1.java
/pak1/pak2/Class1.groovy
Поименнованные фрагменты файла
В некоторых типах файлов можно определять поименнованные фрагменты, которые позволяют вставлять не весь текст файла, а только его часть.
java/groovy/js
Начало фрагмента определяется коментарием //= PART-NAME
, конец фрагмента - //=
.
Начало фрагмента является концом предыдущего, поэтому если фрагменты идут один
за другим, конец фрагмента можно не указывать.
Пример:
def s = "hello"
//= part1
def n1 = 1
//= part2
def n2 = 2
//=
def n0 = 0
//= part3
def n3 = 3
//=
В этом примере определены 3 фрагмента со следующим содержимым:
Фрагмент part1:
def n1 = 1
Фрагмент part2:
def n2 = 2
Фрагмент part3:
def n3 = 3
В качестве имени фрагмента можно указать имя метода. В этом случае в качестве фрагмента
будет использоватся тело метода. Если тело метода содержит фрагмент body
, то этот
фрагмент будет использоватся в качестве тела метода. Фрагмент с именем имяМетода-all
содержит полное тело метода, без учета фрагмента body
.
Пример:
class A1 {
void m1() {
def n1 = 1
}
void m2() {
def n2 = 2
//= body
def n3 = 3
//=
def n4 = 4
}
}
В этом примере определены фрагменты:
Фрагмент m1:
def n1 = 1
Фрагмент m2:
def n3 = 3
Фрагмент m2-all:
def n2 = 2
def n3 = 3
def n4 = 4
xml/html
Начало фрагмента определяется коментарием <!-- = PART-NAME -->
,
конец фрагмента - <!-- = -->
.
Начало фрагмента является концом предыдущего, поэтому если фрагменты идут один
за другим, конец фрагмента можно не указывать.
Если PART-NAME
указан в формате PART-NAME:PATH
, то фрагмент будет
обернут в xml, который соответствует пути.
Например для такого файла:
<?xml version="1.0" encoding="utf-8"?>
<root>
<node1>
<node2>
<!-- = node3 -->
<node3/>
<!-- = -->
<!-- = node4:root/example -->
<node4/>
<!-- = -->
</node2>
</node1>
</root>
Будут такие фрагменты:
<node3/>
<root>
<example>
<node4/>
</example>
</root>
vue
Для vue-файла опредляются фрагменты: template
, script
, style
.
Текст фрагмента - тело соответсвующего раздела vue-файла.
Внутри скриптов и шаблона можно определять свои фрагменты.
В скрипте - по правилам фрагментов 'js', в шаблоне - по правилам фрагментов 'xml'.
Например для такого файла:
<template>
<div>
</div>
</template>
<script>
export default {
props: {},
//= data1
data() {
return {}
},
//=
methods: {},
}
</script>
<style>
.a {
color: red;
}
</style>
Будут такие фрагменты:
<div>
</div>
export default {
props: {},
data() {
return {}
},
methods: {},
}
.a {
color: red;
}
data() {
return {}
},
Генерация файлов для вставки
Для генерации файлов для вставки, создайте файл groovy (или java) в проекте с классом,
наследником от jandcode.mdoc.cm.BaseCodeGen
.
Любой публичный метод без параметров в таком классе - код генерации текста.
Для использования генератора укажите в атрибуте file
имя файла с генератором
и после знака '#'
имя его метода.
Если расширение файла не указано, подразумевается расширение .groovy
или .java
.
Дополнительно доступен атрибут mode
со значениями:
out
- (по умолчанию) показывается то, что выводитoutText
.body
- тело методаbodyout
- тело метода в перемешку с выводом
Пример:
import jandcode.commons.variant.*
import jandcode.mdoc.builder.*
import jandcode.mdoc.cm.*
/**
* Пример генератора файлов для команды @@code
*/
class CodeGen1 extends BaseCodeGen {
/**
* Метод генерации.
* Должен вернуть строку с содержимым виртуального файла.
*/
void gen1() {
// Доступно:
// Атрибуты, переданные в команде @@code (IVariantMap с расширениями).
// Из списка атрибутов исключены file, part, lang, title (они обрабатываются
// командой @@code).
Attrs attrs = getAttrs() // class: jandcode.mdoc.cm.BaseCodeGen.Attrs
// Установить расширение генерируемого файла.
// По умолчанию - txt
setExt("txt")
// В контексте какого OutBuilder выполняется.
OutBuilder builder = getOutBuilder()
// class: jandcode.mdoc.builder.OutBuilder
// В контексте какого OutFile выполняется.
OutFile outFile = getOutFile() // class: jandcode.mdoc.builder.OutFile
// Общий кеш, который существует все время работы outBuilder.
IVariantMap cache = getCache()
// Кеш для текущего класса, который существует все время работы outBuilder.
IVariantMap cacheThis = getCacheThis()
// возвращаем текст для вставки в @@code
outText("generated text for attrs: ${attrs}")
}
/**
* Еще один метод генерации.
*/
void gen2() {
outText("generated 2 text for attrs: ${attrs}")
}
}
Использование:
@@code file=CodeGen1#gen1 attr1=1 attr2=2
Результат:
generated text for attrs: [attr1:1, attr2:2, $list:[file=CodeGen1#gen1, attr1=1, attr2=2]]
Использование mode=body
:
@@code file=CodeGen1#gen1 attr1=1 attr2=2 mode=body
Результат:
// Доступно:
// Атрибуты, переданные в команде @@code (IVariantMap с расширениями).
// Из списка атрибутов исключены file, part, lang, title (они обрабатываются
// командой @@code).
Attrs attrs = getAttrs() // class: jandcode.mdoc.cm.BaseCodeGen.Attrs
// Установить расширение генерируемого файла.
// По умолчанию - txt
setExt("txt")
// В контексте какого OutBuilder выполняется.
OutBuilder builder = getOutBuilder()
// class: jandcode.mdoc.builder.OutBuilder
// В контексте какого OutFile выполняется.
OutFile outFile = getOutFile() // class: jandcode.mdoc.builder.OutFile
// Общий кеш, который существует все время работы outBuilder.
IVariantMap cache = getCache()
// Кеш для текущего класса, который существует все время работы outBuilder.
IVariantMap cacheThis = getCacheThis()
// возвращаем текст для вставки в @@code
outText("generated text for attrs: ${attrs}")
Использование mode=bodyout
:
@@code file=CodeGen1#gen1 attr1=1 attr2=2 mode=bodyout
Результат:
// Доступно:
// Атрибуты, переданные в команде @@code (IVariantMap с расширениями).
// Из списка атрибутов исключены file, part, lang, title (они обрабатываются
// командой @@code).
Attrs attrs = getAttrs() // class: jandcode.mdoc.cm.BaseCodeGen.Attrs
// Установить расширение генерируемого файла.
// По умолчанию - txt
setExt("txt")
// В контексте какого OutBuilder выполняется.
OutBuilder builder = getOutBuilder()
// class: jandcode.mdoc.builder.OutBuilder
// В контексте какого OutFile выполняется.
OutFile outFile = getOutFile() // class: jandcode.mdoc.builder.OutFile
// Общий кеш, который существует все время работы outBuilder.
IVariantMap cache = getCache()
// Кеш для текущего класса, который существует все время работы outBuilder.
IVariantMap cacheThis = getCacheThis()
// возвращаем текст для вставки в @@code
// generated text for attrs: [attr1:1, attr2:2, mode:bodyout, $list:[file=CodeGen1#gen1, attr1=1, attr2=2, mode=bodyout]]