?

Log in

No account? Create an account
Как вы пишете мелкие программки для генерации многих вариантов какого-либо текста? - Юрий Панчул [entries|archive|friends|userinfo]
Money can buy bandwidth. Latency requires bribing God.

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Как вы пишете мелкие программки для генерации многих вариантов какого-либо текста? [Dec. 27th, 2015|11:11 pm]
Yuri Panchul
Господа! Меня заинтересовала статистика: какими инструментальными средствами пользуются мои читатели, когда им нужно сгенерировать много вариантов некоего структурированного текста, скажем скелет для иерархии на Verilog или текст какой-нибудь таблицы в HTML? C/C++, Java, Perl, Python, или чего-то менее популярное?

Возьмем конкретный пример: я решил задокументировать вариант MIPSfpga который я сделал осенью для семинаров в России, и для этой документации мне нужны картинки иерархии модулей. Рисовать картинки в графическом редакторе мне лень, так как вариантов иерархии несколько сотен, и в картинке должны быть HTML-ные ссылки на гитхаб.

Посему я вчера написал вот такую программку, которая генерит HTML тексты http://github.com/MIPSfpga/mipsfpga-plus/tree/master/documentation/figure_generator

Прошу не вопить про использование коротких идентификаторов, препроцессора и передачу параметров через глобальные переменные - от решения требуется краткость для чтения и быстрота написания, а не scalability и verifiability. Я осознаю, что данным кодом можно троллировать juan_gandhi и prof_killjoy, особенно если добавить к коду goto. Но, господа, малые программы пишутся по другим законам, чем большие.

А как бы решили такую задачу вы? Особенно интересует мнение пуристов функциональных языков.

Примеры картинок, генерируемых в зависимости от параметров (всех вариантов генерируемых скриптом - несколько сотен):










Моя программка на Си, которая генерирует картинки:

http://github.com/MIPSfpga/mipsfpga-plus/tree/master/documentation/figure_generator

https://github.com/MIPSfpga/mipsfpga-plus/blob/master/documentation/figure_generator/utilities.cpp

# include "stdio.h"
# include "string.h"

char const mipsfpga_plus_github_location [] = "http://github.com/MIPSfpga/mipsfpga-plus/blob/master";
char const mipsfpga_download_instruction [] = "http://www.silicon-russia.com/2015/12/11/mipsfpga-download-instructions";

const char * module_names [1000];
int          n_module_names;

const char * current_module_name;
int          current_module_is_already_described;

int level = 0;

//----------------------------------------------------------------------------

#define p         printf

#define header    p ("<font size=2 face=\"Verdana, Arial, Helvetica, sans_serif\">\n");
#define footer    p ("</font>\n");

#define tr        p ("<tr>\n");
#define td        p ("<td valign=top>\n");
#define _tr       p ("</tr>\n");
#define _td       p ("</td>\n");
#define hbreak    _td td
#define vbreak    _td _tr tr td
#define ellipsis  p (". . . . . . . . . .<br><br>\n");

//----------------------------------------------------------------------------

void module
(
    const char * file_url      = NULL,
    const char * module_name   = NULL,
    const char * instance_name = NULL,
    const char * description   = NULL,
    int          colspan       = 1
)
{
    level ++;

    if (current_module_name == NULL && module_name != NULL)
        module_names [n_module_names ++] = module_name;

    int the_module_is_current

        =    current_module_name != NULL
          && module_name         != NULL
          && strcmp (module_name, current_module_name) == 0;

    // if (! the_module_is_current || current_module_is_already_described)
    //     description = NULL;

    if (the_module_is_current)
        current_module_is_already_described = 1;

    char buf [BUFSIZ];

    if (file_url != NULL && strstr (file_url, "http") == NULL)
    {
        sprintf (buf, "%s/%s", mipsfpga_plus_github_location, file_url);
        file_url = buf;
    }

    p ("<table width=%s", level == 1 ? "1000" : "100%%");

    char const * level_colors []
        = { "A3FFD1", "A3FFFF", "A3D1FF" };

    p (" bgcolor=#%s", the_module_is_current ? "FFFF29"
        : level_colors [level % (sizeof (level_colors) / sizeof (* level_colors))]);
        
    if (module_name != NULL || instance_name != NULL || description != NULL) p (" border=2");

    p (" cellpadding=10 cellspacing=0 rules=none>\n");

    if (module_name != NULL || instance_name != NULL || description != NULL)
    {
        // p ("<tr><td valign=top nowrap=nowrap");
        p ("<tr><td valign=top");
        
        if (colspan != 1)
            p (" colspan=%d", colspan);
        
        p (">\n");

        if (module_name != NULL || instance_name != NULL) p ("<b>");
        
        if (module_name != NULL)
        {
            if (file_url != NULL) p ("<a href=\"%s\">", file_url);
        
            p ("%s", module_name);
        
            if (file_url != NULL) p ("</a>");
        }
        
        if (module_name != NULL && instance_name != NULL) p (" ");
        
        if (instance_name != NULL) p ("%s", instance_name);
        
        if (module_name != NULL || instance_name != NULL) p ("</b>");
        
        if ((module_name != NULL || instance_name != NULL) && description != NULL) p ("<br><br>\n");
        
        if (description != NULL) p ("%s", description);
        
        p ("\n</td></tr>\n");
    }

    p ("<tr><td valign=top>\n");

    colspan = 1;
}

//----------------------------------------------------------------------------

#define _module  p ("</td></tr>\n</table>\n"), level --;

#define group   module ();
#define _group  _module

//----------------------------------------------------------------------------

void leaf
(
    const char * file_url      = NULL,
    const char * module_name   = NULL,
    const char * instance_name = NULL,
    const char * description   = NULL
)
{
    module
    (
        file_url,
        module_name,
        instance_name,
        description
    );

    _module
}

https://github.com/MIPSfpga/mipsfpga-plus/blob/master/documentation/figure_generator/generator.cpp

#include "utilities.cpp"

struct board_descriptor
{
    char const * module_name;
    int          testbench;
    int          clock_frequency;
    int          altera;
    int          static_7_segment_display;
    int          dynamic_7_segment_display;
    char const * description;
}
boards [] =
{
    { "mfp_testbench" , 1 ,   0 , 0 , 0 , 0 , "Testbench for RTL simulation"                                    },
    { "nexys4_ddr"    , 0 , 100 , 0 , 0 , 1 , "Wrapper for Digilent Nexys 4 DDR board with Xilinx Artix-7 FPGA" },
    { "de0_cv"        , 0 ,  50 , 1 , 1 , 0 , "Wrapper for Terasic DE0-CV board with Altera Cyclone V FPGA"     }, 
    { "de0_nano"      , 0 ,  50 , 1 , 0 , 0 , "Wrapper for Terasic DE0-Nano board with Altera Cyclone IV FPGA"  },
    { "basys3"        , 0 , 100 , 0 , 0 , 1 , "Wrapper for Digilent Basys 3 board with Xilinx Artix-7 FPGA"     },
    { "marsohod3"     , 0 ,  50 , 1 , 0 , 0 , "Wrapper for Marsohod 3 board with Altera MAX10 FPGA"             }
};

int i_board;
int narrow_write_support;
int switchable_clock;
int light_sensor;
int serial_loader;

void print_hierarchy ()
{
    current_module_is_already_described = 0;

    board_descriptor * b = & boards [i_board];

    char buf [BUFSIZ];

    sprintf
    (
        buf,
        "../run/hierarchy_%s%s%s%s%s%s%s.html",
        b -> module_name,
        narrow_write_support        ? "__narrow_write_support" : "",
        switchable_clock            ? "__switchable_clock"     : "", 
        light_sensor                ? "__light_sensor"         : "", 
        serial_loader               ? "__serial_loader"        : "",
        current_module_name != NULL ? "__"                     : "",  
        current_module_name != NULL ? current_module_name      : ""
    );

    freopen (buf, "w", stdout);

    char const * file_url = NULL;

    if (! b -> testbench)
    {
        sprintf (buf, "boards/%s/%s.v",
            b -> module_name,
            b -> module_name);

        file_url = buf;
    }

    header

    module
    (
        file_url,
        b -> module_name,
        NULL,
        b -> description
    );

        if (switchable_clock | b -> static_7_segment_display | b -> dynamic_7_segment_display)
        {
            group
            
            if (switchable_clock)
            {
                group
            
                    module ("mfp_switch_and_button_debouncers.v", "mfp_multi_switch_or_button_sync_and_debouncer");
                        leaf ("mfp_switch_and_button_debouncers.v", "mfp_switch_or_button_sync_and_debouncer", NULL,
                            "Debouncer for the switches that control the clock");
                    _module
            
                    vbreak
            
                if (b -> clock_frequency == 50)
                    module ("mfp_clock_dividers.v", "mfp_clock_divider_50_MHz_to_25_MHz_12_Hz_0_75_Hz");
                else if (b -> clock_frequency == 100)
                    module ("mfp_clock_dividers.v", "mfp_clock_divider_100_MHz_to_25_MHz_12_Hz_0_75_Hz");
            
                        leaf ("mfp_clock_dividers.v", "mfp_clock_divider");
            
                    _module
            
                    vbreak
            
                if (b -> altera)
                    leaf (NULL, "global", "gclk", "Needed for the divided clock");
                else
                    leaf (NULL, "BUFG", NULL, "Needed for the divided clock");
            
                _group
            }
            
            hbreak
            
            if (b -> static_7_segment_display)
            {
                group
                leaf ("mfp_seven_segment_displays.v", "mfp_single_digit_seven_segment_display", "digit_0");
                vbreak
                leaf ("mfp_seven_segment_displays.v", "mfp_single_digit_seven_segment_display", "digit_1");
                vbreak
                leaf ("mfp_seven_segment_displays.v", "mfp_single_digit_seven_segment_display", "digit_2");
                vbreak
                ellipsis
                _group
            }
            
            if (b -> dynamic_7_segment_display)
            {
                group
                leaf ("mfp_clock_dividers.v", "mfp_clock_divider_100_MHz_to_763_Hz", NULL, "Clock for 7-segment display");
                vbreak
                leaf ("mfp_seven_segment_displays.v", "mfp_multi_digit_display");
                _group
            }
            
            _group
            
            vbreak
        }

        module ("mfp_system.v", "mfp_system", NULL, NULL, 2 + light_sensor);
            group
            leaf (mipsfpga_download_instruction, "m14k_top", NULL, "The CPU core");
            vbreak
            leaf ("mfp_system.v", "mfp_ejtag_reset");
            _group

            hbreak

            if (serial_loader)
            {
                module ("mfp_ahb_lite_matrix_with_loader.v", "mfp_ahb_lite_matrix_with_loader", NULL, NULL, 2);
                    group
                    leaf ("mfp_uart_receiver.v", "mfp_uart_receiver", NULL, "Receives data bytes from the PC via UART");
                    vbreak
                    leaf ("mfp_srec_parser.v", "mfp_srec_parser", NULL, "Parses data received via UART as text in Motorola S-Record format and issues transactions to fill the system memory with this data");
                    vbreak
                    leaf ("mfp_srec_parser_to_ahb_lite_bridge.v", "mfp_srec_parser_to_ahb_lite_bridge", NULL, "Converts the transactions from S-Record parser into AHB-Lite protocol. Also converts virtual addresses into physical using fixed mapping");
                    _group

                    hbreak
            }

            module ("mfp_ahb_lite_matrix.v", "mfp_ahb_lite_matrix" );

                leaf ("mfp_ahb_lite_matrix.v", "mfp_ahb_lite_decoder" );
                vbreak

                module ("mfp_ahb_ram_slave.v", "mfp_ahb_ram_slave", "reset_ram");

                    if (narrow_write_support)
                    {
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i0");
                        vbreak
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i1");
                        vbreak
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i2");
                        vbreak
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i3");
                    }
                    else
                    {
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram");
                    }
                _module
            
                vbreak

                module ("mfp_ahb_ram_slave.v", "mfp_ahb_ram_slave", "ram");
                    if (narrow_write_support)
                    {
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i0");
                        vbreak
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram", "i1");
                        vbreak
                        ellipsis
                    }
                    else
                    {
                        leaf ("mfp_dual_port_ram.v", "mfp_dual_port_ram");
                    }
                _module
            
                vbreak
                leaf ("mfp_ahb_gpio_slave.v", "mfp_ahb_gpio_slave", "gpio");
                vbreak
                leaf ("mfp_ahb_lite_matrix.v", "mfp_ahb_lite_response_mux");

            _module

            if (serial_loader)
                _module

            if (light_sensor)
            {
                hbreak
                leaf ("mfp_pmod_als_spi_receiver.v", "mfp_pmod_als_spi_receiver", NULL, "Receives data from the light sensor using a version of SPI protocol");
            }

        _module

    _module
    footer
}

//----------------------------------------------------------------------------

int main ()
{
    for (i_board              = 0; i_board < sizeof (boards) / sizeof (* boards); i_board ++)
    for (narrow_write_support = 0; narrow_write_support <= 1; narrow_write_support ++)
    for (switchable_clock     = 0; switchable_clock     <= 1; switchable_clock     ++)
    for (light_sensor         = 0; light_sensor         <= 1; light_sensor         ++)
    for (serial_loader        = 0; serial_loader        <= 1; serial_loader        ++)
    {
        int features =   narrow_write_support
                       + switchable_clock + light_sensor + serial_loader;

        if (    i_board == 0 && (switchable_clock + light_sensor + serial_loader) != 0
             || i_board != 0 && narrow_write_support == 0
             || i_board >  2 )
        {
            continue;
        }

        // module_names and n_module_names are extracted when current_module_name is NULL

        n_module_names      = 0;
        current_module_name = NULL;

        print_hierarchy ();

        for (int i = 0; i < n_module_names; i ++)
        {
            current_module_name = module_names [i];

            if (current_module_name != NULL)
                print_hierarchy ();
        }
    }

    return 0;
}




Пример кода на HTML, автоматически сгенеренного программкой:

<font size=2 face="Verdana, Arial, Helvetica, sans_serif"> <table width=1000 bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b>mfp_testbench</b><br><br> Testbench for RTL simulation </td></tr> <tr><td valign=top> <table width=100%% bgcolor=#A3D1FF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top colspan=2> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_system.v">mfp_system</a></b> </td></tr> <tr><td valign=top> <table width=100%% bgcolor=#A3FFD1 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://www.silicon-russia.com/2015/12/11/mipsfpga-download-instructions">m14k_top</a></b><br><br> The CPU core </td></tr> <tr><td valign=top> </td></tr> </table> </td> </tr> <tr> <td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_system.v">mfp_ejtag_reset</a></b> </td></tr> <tr><td valign=top> </td></tr> </table> </td></tr> </table> </td> <td valign=top> <table width=100%% bgcolor=#A3FFD1 border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_lite_matrix.v">mfp_ahb_lite_matrix</a></b> </td></tr> <tr><td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_lite_matrix.v">mfp_ahb_lite_decoder</a></b> </td></tr> <tr><td valign=top> </td></tr> </table> </td> </tr> <tr> <td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_ram_slave.v">mfp_ahb_ram_slave</a> reset_ram</b> </td></tr> <tr><td valign=top> <table width=100%% bgcolor=#A3D1FF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_dual_port_ram.v">mfp_dual_port_ram</a></b> </td></tr> <tr><td valign=top> </td></tr> </table> </td></tr> </table> </td> </tr> <tr> <td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_ram_slave.v">mfp_ahb_ram_slave</a> ram</b> </td></tr> <tr><td valign=top> <table width=100%% bgcolor=#A3D1FF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_dual_port_ram.v">mfp_dual_port_ram</a></b> </td></tr> <tr><td valign=top> </td></tr> </table> </td></tr> </table> </td> </tr> <tr> <td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_gpio_slave.v">mfp_ahb_gpio_slave</a> gpio</b> </td></tr> <tr><td valign=top> </td></tr> </table> </td> </tr> <tr> <td valign=top> <table width=100%% bgcolor=#A3FFFF border=2 cellpadding=10 cellspacing=0 rules=none> <tr><td valign=top> <b><a href="http://github.com/MIPSfpga/mipsfpga-plus/blob/master/mfp_ahb_lite_matrix.v">mfp_ahb_lite_response_mux</a></b> </td></tr> <tr><td valign=top> </td></tr> </table> </td></tr> </table> </td></tr> </table> </td></tr> </table> </font>


А как бы эту задачу решили вы?

С
6(11.1%)
С++
6(11.1%)
C#
4(7.4%)
Java
4(7.4%)
Perl
6(11.1%)
Python
10(18.5%)
PHP
3(5.6%)
Rust
0(0.0%)
Haskell
1(1.9%)
Erlang
0(0.0%)
Tcl/Tk
0(0.0%)
Fortran
0(0.0%)
Scala
0(0.0%)
Verilog
0(0.0%)
Lisp
1(1.9%)
Если писать наспор, то могу и на ассемблере
2(3.7%)
Графическим редактором
3(5.6%)
Я бы выбрал(а) другую цветовую гамму для картинок, чем выбрал Панчул
4(7.4%)
Другое (пояснить в комментариях)
4(7.4%)
Из-за бугра плюете?
0(0.0%)
LinkReply

Comments:
[User Picture]From: raydac
2015-12-28 07:18 am (UTC)
когда мне надо структурировать проект с ссылками на сырцы, то я юзаю это https://plugins.jetbrains.com/plugin/8045?pr=idea
но это конечно не автоматическая генерилка

Edited at 2015-12-28 07:22 am (UTC)
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 07:24 am (UTC)
А это поддерживает иерархию эеземпляторов модулей (вложенность) и возможность генерации сотен вариантов картинок в зависимости от параметров, без графического редактирования?
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: m3chman
2015-12-28 07:19 am (UTC)
python + lib к нему соответсвующую. `C` тут имхо избыточно.
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 07:25 am (UTC)
Я бы писал на питоне, но на Си я пишу как дышу (с 9 класса), а питон пришлось бы учить с подглядыванием в книжку.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: spamsink
2015-12-28 08:05 am (UTC)
Квалифицированные инженеры пишут макросы так, чтобы программа имела правильный синтаксис даже без знания содержимого макросов - ради корректности автоматической индентации.
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 08:13 am (UTC)
Я последний раз применял автоматическую индентацию в 1988 году и мне она не понравилась.

Я понимаю, что ";" внутри макроса приводит к труднонаходимым ошибкам с вложенными if-ами, но для фактически скриптов на две страницы я считаю это допустимым, а в проектах на сотни тысяч строк - недопустимым.

Я сам могу выписать штук 20 претензий квалифицированных инженеров к моему данному коду.


UPD: На самом деле интересно: что тебя еще задело сразу кроме использования (); внутри макросов? Мой и твой список из 20 ужасов может не совпадать.


Edited at 2015-12-28 08:26 am (UTC)
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: lyuden
2015-12-28 08:17 am (UTC)
Вы конечно сказали, что препроцессоры не нужны. Но для генерирования html страниц, я бы взял jinja2

http://jinja.pocoo.org/docs/dev/

Это темплейтный язык для питона. Который поддерживает допустим наследование шаблонов. Разделяя допустим оформление стиля заголовка и основного содержимого страницы.

(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 08:21 am (UTC)
*** Вы конечно сказали, что препроцессоры не нужны ***

Я сказал? Хде?

Вы просто поняли мою фразу наоборот.

Я написал "Прошу не вопить про использование коротких идентификаторов, препроцессора"
имея в виду "Прошу не упрекать меня в использовании препроцессора"

Темплейты посмотрю, спасибо
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: norian
2015-12-28 08:32 am (UTC)
коты бы упаковали унутренности в класс

тогда ужасные глобальные переменные стали бы кошерными внутриклассовыми

вместо if (module_name != NULL || instance_name != NULL) можно писать if (module_name || instance_name)

дефайны лучше заменить на константы и коллбэки (ну или юзать потоки для вывода и передавать их)

:о))

(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 08:48 am (UTC)
*** коты бы упаковали унутренности в класс тогда ужасные глобальные переменные стали бы кошерными внутриклассовыми ***

Да, хотя для программки на две страницы и одной instance это типо ханжество.

*** вместо if (module_name != NULL || instance_name != NULL) можно писать if (module_name || instance_name) ***

У меня был такой стиль примерно с 1985 по 1991, потом я его сменил, не помню почему, возможно влияние Microsoft Windows SDK, который меня в тот момент испортил.

*** дефайны лучше заменить на константы и коллбэки (ну или юзать потоки для вывода и передавать их) ***

После прочтения книжки про внутренний дизайн iostream library в середине 1990-х я отношусь к streams как к ереси хотя я использовал его потом по инерции еще лет пять. Но в XXI веке вернулся в уют printf.

(Reply) (Parent) (Thread) (Expand)
[User Picture]From: fabless
2015-12-28 08:44 am (UTC)
Разве в MIPS не используются кодогенераторы на C++ для создания ядра ISS?
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 08:56 am (UTC)
Вы про Instruction Set Simulator? Знание истории нескольких ISS в MIPS не способствует просветлению (три варианта MIPSsim разного качества, Imperas, Carbon, QEMU итд), хотя бОльшая хаоса по этому поводу стараниями Вакуленко в последние годы ликвидировано.

Но какое это имеет отношение к ISS? Эта программка - просто моя локальная нужда отдокументировать иерархию верилоговских модулей открытого обучающего проекта mipsfpga_plus параметризированным способом. Так сказать проект на Рождество.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: nicka_startcev
2015-12-28 09:05 am (UTC)
в зависимости от, или "С++ без класов" или баш.

на баше удобно делать мелочь типа

for A in *.vhdl ; do echo from `basename $A .vhdl`.txt to $A <br;> done
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 09:10 am (UTC)
sh/bash/csh/tcsh я раз пять за жизнь изучал/постепенно забывал, а Си как велосипед - забыть ездить трудно
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: Vadim Rumyantsev
2015-12-28 09:06 am (UTC)
Последние 25 лет я пишу такие вещи на rexx :)
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 09:08 am (UTC)
Вы заразились этим на OS/2 2.0 ? :-)
(Reply) (Parent) (Thread) (Expand)
(Deleted comment)
[User Picture]From: sash_kan
2015-12-28 10:11 am (UTC)
для работы с параметризованными шаблонами текста я бы воспользовался программой gnu/make.
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 05:13 pm (UTC)
Использовать make для генерации текста? Ну в принципе это возможно - в GNU make есть куча всяких if-ов, циклов, встроенных фукций и т.д. Но удобно ли это? Вы можете привести пример, чем именно это удобнее?
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: maxdz
2015-12-28 02:19 pm (UTC)
I'm making c++ generation of site/content too.
(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 05:28 pm (UTC)
И как это помогает украинской революции, антикоррупции, европейскому вектору, борьбе за возвращение Крыма и кредитам МВФ?
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: Николай Пузанов
2015-12-28 02:24 pm (UTC)
Конечно Scheme! С лямбдами, продолжениями и настоящими макросами. А если Racket, то там еще и шаблонизатор есть.

А вообще, пофиг на чем, главное чтоб работало.

(Reply) (Thread)
[User Picture]From: panchul
2015-12-28 05:26 pm (UTC)
Когда моя жена училась в Беркли по специальности "искусство", ей, как и всем студентам, кужно было взять курс программирования по выбору. Среди курсов были чего-то типа C, Java и Scheme. Я сказал "почему бы тебе не взять Scheme, все остальное - это слишком плоско". В результате моя жена получила F или D (типа кол или двойку) и ее идельный до тех пор GPA (она изначально была круглой отличницей) стал неидеальным.
(Reply) (Parent) (Thread) (Expand)
[User Picture]From: sergegers1
2015-12-29 02:19 am (UTC)
Так навскидку не особо понятно, какие вариации делаются, но, возможно, в данном конкретном случае можно сделать некий вариабельный XML и обрабатывать его XSLT. Применимость подхода зависит от того, как сильно меняется структура получившихся тестов. Есть некоторое количество online трансформаторов, типа этого http://xslttest.appspot.com/
(Reply) (Thread)
[User Picture]From: panchul
2015-12-29 04:39 pm (UTC)
Спасибо, посмотрю
(Reply) (Parent) (Thread)
[User Picture]From: incom2
2015-12-29 12:29 pm (UTC)
(Reply) (Thread)
[User Picture]From: ilirium
2016-01-04 07:45 am (UTC)
Если нужно нарисовать картинку или диаграмму, то использую Visio. В начале академической карьеры пробовал какой-то модуль в LaTeX, но он оказался полунерабочим, плюс уходило много времени, чтобы просто подвинуть надпись так, чтобы она смотрелась красиво, в добавок, компилировался долго, не все шрифты показывались так, как нужно и т.п.

Для генерация текстов моделей использую Python, и как выше писали, шаблонизатор jinja2, его можно использовать не только для html, но и для любых других задач. Плюс, в питоне есть встроенный шаблонизатор string.Template для крохотных задач самое оно.
(Reply) (Thread)
(Deleted comment)
From: ab_s
2016-01-14 09:07 pm (UTC)
awk/tcsh. Из принципа :)
(Reply) (Thread)
[User Picture]From: Anatoliy Sergiyenko
2016-01-23 08:38 pm (UTC)
На PHP как здесь:
http://kanyevsky.kpi.ua/GEN_MODUL/SQRT/index.php
(Reply) (Parent) (Thread)