| Новости | FAQ | Авторы | Документация | В действии | Библиотека |
| Инструменты | Полезные ссылки | Хостинги | Скачать | Примеры | Форум |
Yuriy V. Vorontsov (Че) 25.04.2004 19:39 / 25.04.2004 19:48
Неплохо доработал класс:# коммен- # тарий @method[params][locals] ...code ...Т.е. отельно комментарий, название метода, сам код!
type parent value comment code
file /library/autodocs//autodocs.p
MyCLASS not avaliable MAIN Расширение базовых функций Parser3
method MAIN @auto[] \n$CONTENT[^table::create{path}]\n\n\n
global MAIN $CONTENT
defined @auto[] $CONTENT
method MAIN @create[init] \n Конструктор\n 1....
global MAIN $PATH
global MAIN $MASK
global MAIN $INSIDE
global MAIN $MAKEFILE
defined @create[init] $PATH
defined @create[init] $MASK
defined @create[init] $INSIDE
defined @create[init] $MAKEFILE
...Структура файла type – тип объекта ( file – имя обработанного файла, MyCLASS – данные из @CLASS, MyUSE – данные из @USE, MyBASE – данные из @BASE, method – имя макроса (метода), global – статическое поля класса, defined – определённая переменная в методе ) parent – владелец переменной value – значение объекта (имя класса, метода, переменной или значение поля) comment – комментарий к данному code – код метода, только для методовЗамеченные баги:
@default[param1;param2]
$result[^if(def $param1){$param1}{$param2}]
@checked[param;value;isDefault]
$result[^if($param eq $value || (!def $param && def $isDefault)){checked}]
@main[]
<title>Самодокументирование парсерного кода</title>
<form method="GET">
Путь к папке: <input name="library" value="^default[$form:library;/]"><br>
Просматривать:
<input type="radio" name="mask" id="a" value="\.p^$" ^checked[$form:mask;\.p^$;x]>
<label for=a>Библиотеки (.p)</label> /
<input type="radio" name="mask" id="b" value="\.html^$" ^checked[$form:mask;\.html^$]>
<label for=b>Файлы (.html)</label> /
<input type="radio" name="mask" id="c" value="\.(html|p)^$" ^checked[$form:mask;\.(html|p)^$]>
<label for=c>Библиотеки и файлы (.p и .html)</label>
<br>
Просмотривать вложенные папки:
<input type="radio" name="in" id="1" value="1" ^checked[$form:in;1;x]>
<label for=1>Да</label> /
<input type="radio" name="in" id="0" value="0" ^checked[$form:in;0]>
<label for=0>Нет</label>
<br>
Кэш файл формировать?:
<input type="radio" name="file" id="I" value="1" ^checked[$form:file;1]>
<label for=I>Да</label> /
<input type="radio" name="file" id="II" value="0" ^checked[$form:file;0;x]>
<label for=II>Нет</label>
<br>
<input type="hidden" name="run" value="1">
<input name="do" type="submit">
</form>
^if(def $form:run){
<HR width="100%">
$autodocs[^autodocs::create[
$.path[$form:library]
$.mask[^untaint[as-is]{$form:mask}]
$.in(^form:in.int(0))
$.file(^form:file.int(0))
]]
^autodocs.scan[]
}
########################################
@CLASS
autodocs
@auto[]
$CONTENT[^table::create{path}]
# Конструктор
# 1. init = путь к папку где сканировать
# 2. init.path = путь к папку где сканировать
# init.mask = маска в regexp
# init.in = (1/0) открывать вложенные папки
@create[init]
$PATH[/]
$MASK[\.p^$]
$INSIDE(0)
$MAKEFILE(0)
^if($init is string){
$PATH[$init]
}{
^if($init is hash){
^if(def $init.path){
$PATH[$init.path]
}
^if(def $init.mask){
$MASK[$init.mask]
}
^if(def $init.in){
$INSIDE(^init.in.int(1))
}
^if(def $init.file){
$MAKEFILE(^init.file.int(1))
}
}{
^throw[autodocs.create;$init;Входной параметр задан не верно, это может быть string или hash.]
}
}
# Начать сканирование
@scan[]
^scandir[$PATH]
^if($CONTENT){
^CONTENT.menu{
^open[$CONTENT.path]
}
}
#$result[]
# Рекурсивный просмотр папок
@scandir[folder][folder;list]
$list[^file:list[$folder]]
^list.menu{
^if(^list.name.match[$MASK][]){
^add[$folder/$list.name]
}
^if($INSIDE && (-d "$folder/$list.name")){
^scandir[$folder/$list.name]
}
}
#$result[]
# Добавить файл в стэк обработки
@add[file]
^CONTENT.append{$file}
#$result[]
# Обрезать ужас моего не знания regexp'а
@cut[string;also]
^if(def $string){
$string[^string.match[\n$also][g]{}]
$result[^string.match[\n+^$][g]{}]
}{
$result[]
}
# Обрезать ужас моего не знания regexp'а и символы комментариев
@change_comment[string]
^if(def $string){
$result[^string.match[#+][g]{}]
}{
$result[]
}
@unescape_br[string]
^if(def $string){
$string[^string.match[^^\s*][g]{}]
$string[^string.match[\s*^$][g]{}]
$string[^string.match[\n\n+][g]{<p>}]
$string[^string.match[\n][g]{<br>}]
$result[$string]
}{
$result[]
}
# открыть файл
@open[file][f;HELP;table;GHELP]
^if(-f $file){
$f[^file::load[text;$file]]
$f[$f.text]
$HELP[^table::create{method comment code}]
$GHELP[^hash::create[]]
$table[^f.match[
# Сам текст комментария
(
(?:
(?:^^|\n)\#+
^[^^\n^]*
)*
)?
# Разделитель между комментарием и методом
(?:
\s*
)?
# Макрос / Метод / CLASS / BASE / USE
(
\n@^[^^\n^]*
)
# Код / Содержание
(
(?:
\n^[^^\n^]*
(?!
(?:
(?:
\n\#+^[^^\n^]*
)*
)?
(?:
\s+
)?
(?:
\n@^[^^\n^]*
)
)
)*
)
][gxs]]
$f[]
^table.menu{
^if(^table.2.match[@(CLASS|BASE|USE)][]){
$GHELP.[My^cut[$table.2;@]][
$.value[^cut[$table.3]]
$.comment[^change_comment[$table.1]]
]
}{
^HELP.append{^cut[$table.2] ^change_comment[$table.1] $table.3}
}
}
$table[]
^make[$file;$GHELP;$HELP]
$HELP[]
$GHELP[]
# $result[]
}{
^throw[autodocs.open;$file;${file}: Такой файл не найден]
}
# Получить локальные переменные
# except имена какие исключить
@getlocals[string;except]
^if(def $string &&
(def $except && $except is table || !def $except)
){
$string[^string.match[
# Сам текст комментария
(
(?:
(?:^^|\n)\#+
^[^^\n^]*
)*
)?
# Объект
(?:
# Пока буду брать только вменяемые имена (у egr'а вариант такой ^^^$@^;()#)
# \n\s*(\^$^[^^\n^]+)
\n\s*(\^$^[\w\d\-_^]+)^[\^[\^{\(^]
)
][gxs]]
$string[^string.select(!^string.2.match[^^\^$result^$][])]
$result[^table::create{name comment}]
^string.menu{
^if(!^result.locate[name;$string.2] &&
(def $except && !^except.locate[name;$string.2] || !def $except)
){
^result.append{$string.2 $string.1}
}
}
}{
$result[^table::create{name comment}]
}
# Получить параметры макроса, в том числе и локальные переменные, copy paste с egr'а
@getparams[string][table]
^if(def $string){
$table[^string.match[
^^\s*
# Имя метода
@([^^^$@^;()#]+?)
# Передаваемые параметры
\^[
(.*?)
\^]
# Локальные переменные
(?:
\^[
(.*?)
\^]
)?
\s*^$
][gxs]]
# Параметры и переменные
$table[^;${table.2}^;${table.3}^;]
$table[^table.split[^;]]
$table[^table.select(def $table.piece)]
$result[^table::create{name}]
^table.menu{
^result.append{^$$table.piece}
}
}{
$result[^table::create{name}]
}
##########################
# taint to sql
@sql-taint[string][ws_pack_replace]
$ws_pack_replace[^table::create[nameless]{\ \\
^taint[^#0A] \n
^taint[^#09] \t}]
^if(def $string){
$result[^string.replace[$ws_pack_replace]]
;
$result[]
}
##########################
# taint to sql
@sql-untaint[string][ws_unpack_replace]
$ws_unpack_replace[^table::create[nameless]{\n ^taint[^#0A]
\t ^taint[^#09]
\\ \}]
^if(def $string){
$result[^string.replace[$ws_unpack_replace]]
;
$result[]
}
############################################################
# метод для записи таблицы в файл, с предварительной заменой символов перевод строки и табуляция на \n и \t
# copy paste с Misha.3
@table_save[table;file_name][col;tmp]
$col[^table.columns[]]
$tmp[^col.menu{$col.column}[^#09]^#0A^table.menu{^col.menu{^sql-taint[$table.[$col.column]]^#09}}[^#0A]]
^tmp.save[$file_name]
$result[]
# Сделать структуру
@make[file;GHELP;HELP][container;VARS;PARAMS;GLOBAL;MyCLASS]
$container[^table::create{type parent value comment code}]
$GLOBAL[^table::create{name comment method}]
# $file:
^container.append{file $file }
# GHELP
# конфигурационные данные
^if(def $GHELP.MyCLASS){
^container.append{MyCLASS not avaliable $GHELP.MyCLASS.value $GHELP.MyCLASS.value }
$MyCLASS[$GHELP.MyCLASS.value]
}{
^container.append{MyCLASS not avaliable MAIN Расширение базовых функций Parser3 }
$MyCLASS[MAIN]
}
^if(def $GHELP.MyBASE){
^container.append{MyBASE $MyCLASS $GHELP.MyBASE.value $GHELP.MyBASE.comment }
}
^if(def $GHELP.MyUSE){
^container.append{MyUSE $MyCLASS $GHELP.MyUSE.value $GHELP.MyUSE.comment }
}
# HELP
^if($HELP){
^HELP.menu{
^container.append{method $MyCLASS $HELP.method $HELP.comment $HELP.code}
^if(def $HELP.code){
# Переменные метода
$VARS[^getlocals[$HELP.code;^getparams[$HELP.method]]]
^if($VARS){
^VARS.menu{
^if(!^GLOBAL.locate[name;$VARS.name]){
^GLOBAL.append{$VARS.name $VARS.comment $HELP.method}
^container.append{global $MyCLASS $VARS.name $VARS.comment }
}
}
}
$VARS[^getlocals[$HELP.code]]
^if($VARS){
^VARS.menu{
^container.append{defined $HELP.method $VARS.name $VARS.comment }
}
}
}
}
}
# Сделать файл?
^if($MAKEFILE){
^table_save[$container;^file.match[[/\.]][g]{_}.cfg]
}
$result[^show[$file;$GHELP;$HELP;$GLOBAL]]
@show[file;GHELP;HELP;GLOBAL][VARS]
$result[
^if(def $GHELP.MyCLASS){
<H1>Класс: $GHELP.MyCLASS.value</H1>
^if(def $GHELP.MyCLASS.comment){
<h4><ul>^unescape_br[$GHELP.MyCLASS.comment]</ul></h4>
}
}{
<H1>Класс: MAIN</H1>
<h3>Расширение базовых функций Parser3</h3>
}
<H2>Файл $file</H2>
^if($GLOBAL){
<H2>Статические поля класса:</H2>
<ol>
^GLOBAL.menu{
<li>
<strong>$GLOBAL.name</strong> (определяется в <a href="#$GLOBAL.method">$GLOBAL.method</a>):
^if(def $GLOBAL.comment){
<br> <i>^change_comment[$GLOBAL.comment]</i>
}
</li>
}[<p>]
</ol>
}
^if($HELP){
<table border=1>
^HELP.menu{
<tr>
<td align="left" valign="top" width="10%">
<a name="$HELP.method"/>
<pre>$HELP.method</pre>
<ul>^unescape_br[$HELP.comment]</ul>
# <p>^unescape_br[$HELP.code]
$VARS[^getlocals[$HELP.code]]
^if($VARS){
<p>Объявленные в методе переменные:
<ol>
^VARS.menu{
<li>
<strong>$VARS.name</strong>:
^if(def $VARS.comment){
<br> <i>^change_comment[$VARS.comment]</i>
}
</li>
}[<p>]
</ol>
}
</td>
</tr>
}
</table>
}
<HR width=100%>
]