12

I am trying to configure the Eclipse PHP formatter to keep the opening and closing php tags on 1 line if there is only 1 line of code between them (while keeping the default new line formatting if there are more lines of code).

Example:

<td class="main"><?php
echo drm_draw_input_field('fax') . '&nbsp;' . (drm_not_null(ENTRY_FAX_NUMBER_TEXT) ? '<span class="inputRequirement">' . ENTRY_FAX_NUMBER_TEXT . '</span>' : '');
?></td>

Should be formatted to:

<td class="main"><?php echo drm_draw_input_field('fax') . '&nbsp;' . (drm_not_null(ENTRY_FAX_NUMBER_TEXT) ? '<span class="inputRequirement">' . ENTRY_FAX_NUMBER_TEXT . '</span>': ''); ?></td>

Is there any way to achieve this with Eclipse? Or another suggestion/formatter?

EDIT: It seems Eclipse does not have such a formatting option, as explained in the comments below. Any existing alternatives that can do this?

Nikita 웃
  • 2,042
  • 20
  • 45
  • As i know you can't do such thing in `eclipse` as `eclipse` has only options to format code part i mean the text part inside php tags ``, but i can suggest as alternative creation of simple php script which will read given php file content format it and overwrite it – Armen Jan 22 '16 at 06:31
  • Yes, it seems you are right about `Eclipse` formatting options. The question is also asking for an existing alternative that can do that. If you know one, kindly post it :) – Nikita 웃 Jan 22 '16 at 06:33

2 Answers2

4

As i already mentioned under question comment "As i know you can't do such thing in eclipse as eclipse has only options to format code part i mean the text part inside php tags <?php ...code text... ?>"

But you can achieve it with this php script

Very important before start: Backup your php project which you are going to mention in dirToArray() function

// Recursive function to read directory and sub directories
// it build based on php's scandir - http://php.net/manual/en/function.scandir.php
function dirToArray($dir) {

    $result = array();      
    $cdir = scandir($dir);

    foreach ($cdir as $key => $value){
        if (!in_array($value,array(".",".."))){
            if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){
                $result = array_merge(
                       $result, 
                       dirToArray($dir . DIRECTORY_SEPARATOR . $value) 
                );
            }else{
                $result[] = $dir . DIRECTORY_SEPARATOR . $value;
            }
        }
    }

    return $result;
}

// Scanning project files
$files = dirToArray("/home/project"); // or C:/project... for windows

// Reading and converting to single line php blocks which contain 3 or less lines
foreach ($files as $file){

    // Reading file content
    $content = file_get_contents($file);

    // RegExp will return 2 arrays 
    // first will contain all php code with php tags
    // second one will contain only php code
    // UPDATED based on Michael's provided regexp in this answer comments
    preg_match_all( '/<\?php\s*\r?\n?(.*?)\r?\n?\s*\?>/i', $content, $blocks );

    $codeWithTags = $blocks[0];
    $code = $blocks[1];

    // Loop over matches and formatting code
    foreach ($codeWithTags as $k => $block){
        $content = str_replace($block, '<?php '.trim($code[$k]).' ?>', $content );
    }

    // Overwriting file content with formatted one
    file_put_contents($file, $content);
}

NOTE: This is just simple example and of course this script can be improved

// Result will be that this
text text text<?php 
   echo "11111"; 
?>
text text text<?php 
   echo "22222"; ?>
text text text<?php echo "33333"; 
?>
<?php
   echo "44444";
   echo "44444";
?>

// will be formated to this
text text text<?php echo "11111"; ?>
text text text<?php echo "22222"; ?>
text text text<?php echo "33333"; ?>
<?php
   echo "44444";
   echo "44444";
?>
Armen
  • 4,064
  • 2
  • 23
  • 40
  • 1
    Looking good! If you can improve your code to read directories directly and take only blocks with 3 line breaks, please edit your answer. It will make it a winner! :) – Annie Trubak Jan 27 '16 at 08:21
  • 1
    This regexp matches all onliners. Should make your code much simpler: https://regex101.com/r/jV7rG2/2 `<\?php\s*\n(.*?)\n\s*\?>` – Michael Jan 28 '16 at 04:56
  • Thanks @Michael i updated regexp based on your suggestion – Armen Jan 28 '16 at 07:32
  • 1
    @AnnieTrubak i added directory scanning part – Armen Jan 28 '16 at 07:32
  • @Michael actually your `regexp` after tests appears to be not working with windows files so i reverted to old one, actually i was looking for `regexp` which will select php block which contain only 3 line breaks – Armen Jan 28 '16 at 07:58
  • Why would Windows be different? Different newlines perhaps? "which will select php block which contain only 3 line breaks" — that's what mine did – Michael Jan 28 '16 at 08:31
  • @Michael yes there is 3 different type of line backs you can see here in answer: http://stackoverflow.com/questions/255511/php-echo-line-breaks, for windows it `\r\n` – Armen Jan 28 '16 at 08:48
  • I was thinking that so you could replace `\n` with `[\n\r]{1,2}` or `\r?\n`. – Michael Jan 28 '16 at 08:54
  • @Michael i think replace is not good idea as in that case all line breaks in file should be replaced and user might not want that – Armen Jan 28 '16 at 09:01
  • 1
    @Armen that is not the case. It is only onliner PHP blocks that will match. Check the regexp I sent you—updated with `\r` https://regex101.com/r/jV7rG2/3 – Michael Jan 28 '16 at 09:53
  • @Michael that helps thank you, i just a bit modified it to this `/<\?php\s*\r?\n?(.*?)\r?\n?\s*\?>/i` so that will match to code where no line break present from code beginning or end as in result example in answer – Armen Jan 28 '16 at 11:48
  • @Armen, doesn't it need to end with `/ig` instead of `/i` like `preg_match_all( '/<\?php\s*\r?\n?(.*?)\r?\n?\s*\?>/ig', $content, $blocks );` – Nikita 웃 Jan 28 '16 at 11:51
  • @CreativeMind no as `preg_match_all` already selects all matches, you no need `g` if you try to add `g` php will trow you notice you can try and see – Armen Jan 28 '16 at 11:53
0

In sublimetext, the manual command is ctrl + J.

Automagically, might i suggest you take a look at this:

https://github.com/heroheman/Singleline

CodeshowS
  • 24
  • 4