<commit_before><?php

namespace Grav\Plugin;

use Grav\Common\Plugin;
use Grav\Common\Grav;
use Grav\Common\Page\Page;
use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Exception\ParseException;

class PygmentsPlugin extends Plugin
{
    private static $pattern = '#<pre><code>---(?<head>.*?)\n---(?<body>.*?)</code></pre>#s';

    public static function getSubscribedEvents()
    {
        return [
            'onPageContentProcessed' => ['onPageContentProcessed', 0],
        ];
    }

    public function onPageContentProcessed(Event $event)
    {
	// Set a unicode locale for accented characters
	$locale = 'en_US.UTF-8';
	setlocale(LC_ALL, $locale);
	putenv('LC_ALL='.$locale);

        $page = $event['page'];
        $content = $page->getRawContent();

        if (!preg_match_all(self::$pattern, $content, $matches, PREG_SET_ORDER)) {
            return;
        }

        $yaml = new Parser();

        foreach ($matches as $match) {
            $full = $match[0];

            /* Get and parse headers */
            try {
                $head = $yaml->parse(trim($match['head']));
            } catch (ParseException $e) {
                continue;
            }

            /* Get and decode body. This isn't a problem since we stay between
               <code> tags. */
            $body = html_entity_decode(trim($match['body']));

            if (isset($head['file'])) {
                try {
                    $file = $this->grav['locator']->findResource($head['file']);
                } catch (\InvalidArgumentException $e) {
                    if (substr($head['file'], 0, 1) == DIRECTORY_SEPARATOR) {
                        $file = $head['file'];
                    } else {
                        $file = $page->path().DIRECTORY_SEPARATOR.$head['file'];
                    }
                }

                if (is_file($file)) {
                    $body = file_get_contents($file);
                } else {
                    $body = "File '{$head['file']}' does not exist";
                }
            }

            /* Craft command line */

            // Send body via command line
            $cmd = 'printf '.escapeshellarg(str_replace(['\\','%'], ['\\\\','%%'], $body));

            // Base command
            $cmd .= ' | '.$this->config->get('plugins.pygments.pygmentize.command', 'pygmentize');

            // Find the language if given
            if (isset($head['language'])) {
                if ($head['language'] == 'guess') {
                    $cmd .= ' -g';
                } else {
                    $cmd .= ' -l '.escapeshellarg($head['language']);
                }
            }

            // Guess or not (depending on the config) otherwise
            else {
                if ($this->config->get('plugins.pygments.guess_by_default', true)) {
                    $cmd .= ' -g';
                } else {
                    $cmd .= ' -l text';
                }
            }
<commit_msg>fix printf for files starting with '-'<commit_after><?php

namespace Grav\Plugin;

use Grav\Common\Plugin;
use Grav\Common\Grav;
use Grav\Common\Page\Page;
use RocketTheme\Toolbox\Event\Event;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Exception\ParseException;

class PygmentsPlugin extends Plugin
{
    private static $pattern = '#<pre><code>---(?<head>.*?)\n---(?<body>.*?)</code></pre>#s';

    public static function getSubscribedEvents()
    {
        return [
            'onPageContentProcessed' => ['onPageContentProcessed', 0],
        ];
    }

    public function onPageContentProcessed(Event $event)
    {
	// Set a unicode locale for accented characters
	$locale = 'en_US.UTF-8';
	setlocale(LC_ALL, $locale);
	putenv('LC_ALL='.$locale);

        $page = $event['page'];
        $content = $page->getRawContent();

        if (!preg_match_all(self::$pattern, $content, $matches, PREG_SET_ORDER)) {
            return;
        }

        $yaml = new Parser();

        foreach ($matches as $match) {
            $full = $match[0];

            /* Get and parse headers */
            try {
                $head = $yaml->parse(trim($match['head']));
            } catch (ParseException $e) {
                continue;
            }

            /* Get and decode body. This isn't a problem since we stay between
               <code> tags. */
            $body = html_entity_decode(trim($match['body']));

            if (isset($head['file'])) {
                try {
                    $file = $this->grav['locator']->findResource($head['file']);
                } catch (\InvalidArgumentException $e) {
                    if (substr($head['file'], 0, 1) == DIRECTORY_SEPARATOR) {
                        $file = $head['file'];
                    } else {
                        $file = $page->path().DIRECTORY_SEPARATOR.$head['file'];
                    }
                }

                if (is_file($file)) {
                    $body = file_get_contents($file);
                } else {
                    $body = "File '{$head['file']}' does not exist";
                }
            }

            /* Craft command line */

            // Send body via command line
            $cmd = 'printf -- '.escapeshellarg(str_replace(['\\','%'], ['\\\\','%%'], $body));

            // Base command
            $cmd .= ' | '.$this->config->get('plugins.pygments.pygmentize.command', 'pygmentize');

            // Find the language if given
            if (isset($head['language'])) {
                if ($head['language'] == 'guess') {
                    $cmd .= ' -g';
                } else {
                    $cmd .= ' -l '.escapeshellarg($head['language']);
                }
            }

            // Guess or not (depending on the config) otherwise
            else {
                if ($this->config->get('plugins.pygments.guess_by_default', true)) {
                    $cmd .= ' -g';
                } else {
                    $cmd .= ' -l text';
                }
            }

{'fraction_non_alphanumeric': 0.15696328150843533, 'fraction_numerical': 0.0016539861065167053, 'mean_word_length': 1.5122559202326546, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2584544', 'n_tokens_mistral': 1749, 'n_tokens_neox': 1624, 'n_words': 352}