Skip to content

Commit

Permalink
@inludes and @require
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaitsev committed Apr 4, 2015
1 parent 2eaf695 commit 23960a4
Show file tree
Hide file tree
Showing 42 changed files with 454 additions and 48 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"mthaml/mthaml-bundle": "<1.1.0"
},
"autoload": {
"classmap": ["lib/MtHamlPHP/Node/Tag.php"],
"classmap": ["lib/MtHamlPHP/Node/Tag.php","lib/MtHamlPHP/Parser/Buffer.php"],
"psr-0": {
"MtHamlPHP\\": "lib/"
}
Expand Down
2 changes: 1 addition & 1 deletion lib/MtHamlPHP/Filter/Haml.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ protected function renderFilter(Renderer $renderer, Filter $node)
$array = Yaml::parse($yaml);

//patching to access enviroment
$class = new ReflectionClass("MtHaml\NodeVisitor\RendererAbstract");
$class = new ReflectionClass(get_class($renderer));
$property = $class->getProperty("env");
$property->setAccessible(true);

Expand Down
120 changes: 101 additions & 19 deletions lib/MtHamlPHP/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,22 @@
use MtHamlPHP\Filter\Haml;
use MtHaml\Node\Text;
use MtHaml\Node\TagAttribute;
use ReflectionClass;

/**
* MtHamlPHP Parser
*/
class Parser extends \MtHaml\Parser {
// add Envirmonent object, MtHaml-More see README.md : Development Rool 2
private $env;

/**
* @return \MtHaml\Environment
*/
public function getEnv() {
return $this->env;
}
private $env;

public function __construct( \MtHaml\Environment $env = null ) {
parent::__construct();
$this->env = $env;
}

protected function parseStatement( $buf ) {
//first parse filters, so we can parse :haml with confit first
//first parse filters, so we can parse :haml with configs first
// Dbg::emsgd($this->env->getOptions());
if ( null !== $node = $this->parseFilter( $buf ) ) {
if ( $node->getFilter() == 'haml' ) {
Expand All @@ -41,14 +35,18 @@ protected function parseStatement( $buf ) {
}

protected function parseTagAttributesShortcut( $buf ) {
/**
* @var $buf \MtHaml\Parser\Buffer
*/
$attrs = array();
// short notation for classes and ids

$arr = $this->env->getOption( 'shortcut' );
if ( empty( $arr ) ) {
return parent::parseTagAttributes( $buf );
}
//$arr=[];
// Dbg::emsgd($arr);
// if ( empty( $arr ) ) {
// return parent::parseTagAttributes( $buf );
// }
//add default . and # as shortcut
if ( empty( $arr['.'] ) || ! empty( $arr['.']['tag'] ) ) {
$arr['.'] = array( 'attr' => 'class' );
}
Expand All @@ -63,7 +61,6 @@ protected function parseTagAttributesShortcut( $buf ) {
$shortcuts[ $s ] = $p;
}
}
// echo Dbg::emsgds($shortcuts);
$prefixes = implode( '|', $prefixes );
while ( $buf->match( '/(?P<type>' . $prefixes . ')(?P<name>[\w-]+)/A', $match ) ) {
if ( ! empty( $shortcuts[ $match['type'] ]['attr'] ) ) {
Expand Down Expand Up @@ -132,21 +129,102 @@ protected function parseTagAttributesShortcut( $buf ) {
return $attrs;
}

protected function parseTag( $buf ) {
$arr = $this->env->getOption( 'shortcut' );
if ( empty( $arr ) ) {
return parent::parseTag( $buf );
function path_is_absolute( $path ) {
/*
* This is definitive if true but fails if $path does not exist or contains
* a symbolic link.
*/
if ( realpath( $path ) == $path ) {
return true;
}

if ( strlen( $path ) == 0 || $path[0] == '.' ) {
return false;
}

// Windows allows absolute paths like this.
if ( preg_match( '#^[a-zA-Z]:\\\\#', $path ) ) {
return true;
}

// A path starting with / or \ is absolute; anything else is relative.
return ( $path[0] == '/' || $path[0] == '\\' );
}

protected function injectFile( $buf, $type ) {
/**
* @var $buf \MtHaml\Parser\Buffer
*/

$class = new ReflectionClass( get_parent_class() );
$property = $class->getProperty( "indent" );
$property->setAccessible( true );
$path = trim( $buf->getLine() );
if ( null == $base_dir = $this->env->getOption( 'includes_dir' ) ) {
$base_dir = getcwd();
};
$filename = false;
if ( ( $this->path_is_absolute( $path ) && file_exists( $path ) ) ) {
$filename = $path;
} elseif ( file_exists( trim( $base_dir ) . DIRECTORY_SEPARATOR . $path ) ) {
$filename = trim( $base_dir ) . DIRECTORY_SEPARATOR . $path;
} elseif ( 'require' === $type ) {
throw $this->syntaxError( $buf, "@require $path : file not found \n includes_dir: $base_dir\n " . $base_dir . DIRECTORY_SEPARATOR . $path . "\n" );
}
$inj = @file_get_contents( $filename, true );
if ( $inj !== false ) {

$this->injectLines( $buf, $inj );

return null;//restart Parser
}

return null;
}

/**
* @param $buf \MtHaml\Parser\Buffer
* @param $string string - multi-line string to inject
*/
protected function injectLines( $buf, $string ) {
$level = $this->indent->getLevel();
$prepend = str_repeat( $this->indent->getChar(), $level * $this->indent->getWidth() );
$lines = preg_split( '~\r\n|\n|\r~', $string );
$lines = array_map(
function ( $v ) use ( $prepend ) {
return $prepend . $v;
},
array_filter( $lines, function ( $v ) {
return ! empty( $v );
} )
);
if ( empty( $lines ) ) {
return false;
}

return $buf->injectLines( $lines, 1 );
}

protected function parseTag( $buf ) {
$arr = (array) $this->env->getOption( 'shortcut' );
// if ( empty( $arr ) ) {
// return parent::parseTag( $buf );
// }
$shortcuts = array();
$prefixes[] = '\%';

foreach ( $arr as $s => $p ) {
if ( ! empty( $p['tag'] ) ) {
$prefixes[] = '\\' . $s;
$shortcuts[ $s ] = $p;
}
}
//inject @include and @require
$shortcuts['@'][] = 'include';
$shortcuts['@'][] = 'require';
$prefixes[] = '\@';

$prefixes = implode( '|', $prefixes );
$prefixes = implode( '|', array_unique( $prefixes ) );
// Dbg::emsgd($prefixes); return;
$tagRegex = '/
(?P<shortcut>' . $prefixes . ')(?P<tag_name>[\w:-]+) # explicit tag name ( %tagname )
Expand All @@ -159,6 +237,10 @@ protected function parseTag( $buf ) {
$new_type = null;
$tag_name = empty( $match['tag_name'] ) ? 'div' : $match['tag_name'];
if ( ! empty( $shortcuts[ $match['shortcut'] ] ) ) {
//@include adn @require
if ( '@' === $match['shortcut'] && ( 'require' === $match['tag_name'] || 'include' === $match['tag_name'] ) ) {
return $this->injectFile( $buf, $match['tag_name'] );
}
$params = $shortcuts[ $match['shortcut'] ];
$tag_name = $params['tag'];
//Dbg::emsgd($params['tag']);
Expand Down
146 changes: 146 additions & 0 deletions lib/MtHamlPHP/Parser/Buffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?php

namespace MtHaml\Parser;

use MtHamlPHP\Dbg;

class Buffer {
protected $lines;
protected $line;

protected $lineno;
protected $column;

public function __construct( $string, $lineno = 1 ) {
$this->lines = preg_split( '~\r\n|\n|\r~', $string );
$this->lineno = $lineno - 1;
}

public function injectLines( $lines, $column) {


// //remove @inlcude line
if ( empty( $lines ) ) {
return false;
}
$this->lines = array_merge( $lines, $this->lines );
// $this->line = trim($this->getLine());
$this->line ="-#This comment is do magic, do not remove : inject start , reset parser. ";
$this->column = $column;

return true;
}

public function nextLine() {
$this->line = array_shift( $this->lines );
if ( null !== $this->line ) {
++ $this->lineno;
$this->column = 1;

return true;
}

return false;
}

public function peekLine() {
if ( isset( $this->lines[0] ) ) {
return $this->lines[0];
}
}

public function hasNextLine() {
return isset( $this->lines[0] );
}

public function mergeNextLine() {
if ( ! isset( $this->lines[0] ) ) {
return;
}
++ $this->lineno;
$this->line .= "\n" . array_shift( $this->lines );
}

public function replaceLine( $string ) {
$this->line = $string;
}

public function isEol() {
return $this->line === '';
}

public function peekChar() {
if ( isset( $this->line[0] ) ) {
return $this->line[0];
}
}

public function eatChar() {
if ( isset( $this->line[0] ) ) {
$char = $this->line[0];
$this->line = (string) substr( $this->line, 1 );
++ $this->column;

return $char;
}
}

public function eatChars( $n ) {
$chars = (string) substr( $this->line, 0, $n );
$this->line = (string) substr( $this->line, $n );
$this->column += strlen( $chars );

return $chars;
}

public function match( $pattern, &$match = null, $eat = true ) {
if ( $count = preg_match( $pattern, $this->line, $match, PREG_OFFSET_CAPTURE ) ) {
$pos = array();

foreach ( $match as $key => &$capture ) {
$pos[ $key ] = array(
'lineno' => $this->lineno,
'column' => $capture[1],
);
$capture = $capture[0];
}
unset( $capture ); // ref

$match['pos'] = $pos;

if ( $eat ) {
$this->eat( $match[0] );
}
}

return $count > 0;
}

public function eat( $string ) {
$this->line = (string) substr( $this->line, strlen( $string ) );
$this->column += strlen( $string );
}

public function skipWs() {
$this->match( '~[ \t]+~A' );
}

public function getColumn() {
return $this->column;
}

public function getLineno() {
return $this->lineno;
}

public function getPosition() {
return array(
'lineno' => $this->lineno,
'column' => $this->column,
);
}

public function getLine() {
return $this->line;
}
}
1 change: 1 addition & 0 deletions lib/MtHamlPHP/todo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//todo add base pach or inludes path
16 changes: 8 additions & 8 deletions test/MtHamlPHP/Tests/HamlPHPTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@
use MtHaml\NodeVisitor\Printer;
use MtHamlPHP\Dbg;

require_once __DIR__ . '/TestCase.php';
require_once __DIR__ . './TestCase.php';
//error_reporting(E_ALL);

/**
* Class HamlPHPTest
* @package MtHamlPHP\Tests
*/
class HamlPHPTest extends TestCase
{
/** @dataProvider getHamlPHPTests */
public function testHamlPHP($file)
{
$parts = $this->parseTestFile($file);
echo "$describe\n";
file_put_contents($file . '.haml', $parts['HAML']);
file_put_contents($file . '.php', $parts['FILE']);
file_put_contents($file . '.exp', $parts['EXPECT']);
if (isset( $parts['SNIP'])) file_put_contents($file . '.snip', $parts['SNIP']);

if (!empty($parts['SKIP'])) {
$this->markTestIncomplete(
$describe.':'.$parts['SKIP']
);
$this->markTestIncomplete('skipped');
return;
}

Expand All @@ -41,7 +41,7 @@ public function testHamlPHP($file)

file_put_contents($file . '.out', $out);

$this->assertSame($parts['EXPECT'], $out,$describe);
$this->assertSame($parts['EXPECT'], $out);

if (isset($parts['EXECUTED'])) {
ob_start();
Expand Down Expand Up @@ -70,7 +70,7 @@ public function getHamlPHPTests()
if (false !== $tests = getenv('ENV_TESTS')) {
$files = explode(' ', $tests);
} else {
$files = glob(__DIR__ . '/fixtures/hamlphp/*.test');
$files = glob(__DIR__ . '/MtHamlPHP/fixtures/environment/*.test');
}
$t = array();
foreach ($files as $file){
Expand Down
Loading

0 comments on commit 23960a4

Please sign in to comment.