diff --git a/WebIdeTemplateManager.php b/WebIdeTemplateManager.php
index bc3b621..f5c0e31 100755
--- a/WebIdeTemplateManager.php
+++ b/WebIdeTemplateManager.php
@@ -15,89 +15,29 @@
  * prompt$ php ./WebIdeTemplateManager push
  * or
  * prompt$ php ./WebIdeTemplateManager push force
- * or
- * prompt$ php ./WebIdeTemplateManager live-template-sort
- *
- * .git/hooks/pre-commit
- * @code
- * exec ./WebIdeTemplateManager.php "git-hook" "pre-commit"
- * if [[ $? -ne 0 ]]; then
- *    exit 1
- * fi
- * @endcode
  *
  * @see http://youtrack.jetbrains.com/issue/IDEA-89201
  * @see http://youtrack.jetbrains.com/issue/IDEABKL-6390
  */
 class WebIdeTemplateManager {
 
-  /**
-   * Determine the XML is ordered or not.
-   *
-   * @param DomXPath $xpath
-   *   XPath query handler.
-   *
-   * @return boolean
-   *   Return TRUE if the given Live Template XML ordered by "name".
-   */
-  public static function liveTemplateIsOrdered(DomXPath $xpath) {
-    $xpr = $xpath->query('/templateSet/template');
-    $name_previous = '';
-    $i = 0;
-
-    while (
-      $i < $xpr->length
-      &&
-      strnatcasecmp($name_previous, $xpr->item($i)->getAttribute('name')) < 0
-    ) {
-      $name_previous = $xpr->item($i)->getAttribute('name');
-      $i++;
-    }
-
-    return ($i == $xpr->length);
-  }
+  const OS_WINDOWS = 1;
+  const OS_MAC = 2;
+  const OS_LINUX = 3;
 
   /**
-   * Sort children of the root node in a Live Template XML.
-   *
-   * @param DOMXPath $xpath
-   *   XPath query handler.
-   */
-  public static function liveTemplateSortTemplateSet(DOMXPath $xpath) {
-    $xpr = $xpath->query('/templateSet');
-    $template_set = $xpr->item(0);
-    $xpr = $xpath->query('/templateSet/template');
-    $templates = array();
-    // 5.4.0 Added support for SORT_NATURAL and SORT_FLAG_CASE as sort_flags
-    // No sort function for array keys with natural ordering.
-    $templates_index = array();
-    for ($i = 0; $i < $xpr->length; $i++) {
-      $node = $xpr->item($i);
-      $name = $node->getAttribute('name');
-      $templates["$name:$i"] = $node;
-      $templates_index["$name:$i"] = $name;
-      $template_set->removeChild($node);
-    }
-
-    natcasesort($templates_index);
-    foreach (array_keys($templates_index) as $name) {
-      $template_set->appendChild($templates[$name]);
-    }
-  }
-
-  /**
-   * Major version of the PhpStorm.
+   * Minimum major version of the PhpStorm.
    *
    * @var integer
    */
-  protected $webIdeVersion = 4;
+  protected $webIdeVersionMin = '40';
 
   /**
-   * Always disabled.
+   * Maximum major version of the PhpStorm.
    *
-   * @var boolean
+   * @var integer
    */
-  protected $sortLiveTemplateItems = FALSE;
+  protected $webIdeVersionMax = NULL;
 
   /**
    * Indent characters.
@@ -149,6 +89,22 @@ class WebIdeTemplateManager {
   protected $templateHome = NULL;
 
   /**
+   * Pattern for WebIde configuration home.
+   *
+   * The keys are WebIdeTemplateManager::OS_* constants.
+   *
+   * @var string
+   */
+  protected $webIdeHomeGlobs = array(
+    // Win.
+    1 => '.WebIde*',
+    // Mac
+    2 => 'Library/Preferences/WebIde*',
+    // Linux
+    3 => '.WebIde*',
+  );
+
+  /**
    * WebIde configuration home.
    *
    * @var string
@@ -156,6 +112,20 @@ class WebIdeTemplateManager {
   protected $webIdeHome = NULL;
 
   /**
+   * Config directory under WebIde configuration home.
+   *
+   * This handle the differences between Mac and Linux.
+   *
+   * @var string
+   */
+  protected $webIdeHomeConfig = NULL;
+
+  /**
+   * @var string
+   */
+  protected $OS = NULL;
+
+  /**
    * Initialize the environment.
    *
    * @param array $args
@@ -164,27 +134,51 @@ class WebIdeTemplateManager {
    * @throws Exception
    */
   public function __construct($args) {
+    if (strpos(PHP_OS, 'Win') !== FALSE) {
+      $this->OS = self::OS_WINDOWS;
+    }
+    elseif (strpos(PHP_OS, 'Linux') !== FALSE) {
+      $this->OS = self::OS_LINUX;
+    }
+    else {
+      $this->OS = self::OS_MAC;
+    }
+
     $this->args = $args;
     $this->home = $_SERVER['HOME'];
 
     $this->templateHome = realpath($args[0]);
-    $limit = 8;
-    while (is_link($this->templateHome) && $limit) {
-      $this->templateHome = readlink($this->templateHome);
-      $limit--;
-    }
 
-    if (!$limit) {
-      throw new Exception('Template home');
+    if ($this->OS != self::OS_WINDOWS) {
+      $limit = 8;
+      while (is_link($this->templateHome) && $limit) {
+        $this->templateHome = readlink($this->templateHome);
+        $limit--;
+      }
+
+      if (!$limit) {
+        throw new Exception('Template home');
+      }
     }
+
     $this->templateHome = dirname($this->templateHome);
 
-    $this->webIdeHome = NULL;
+    $this->webIdeHome = $this->home;
     $webidehomes = array();
     try {
-      $iterator = new GlobIterator("{$this->home}/.WebIde*");
+      $iterator = new GlobIterator($this->home . '/' . $this->webIdeHomeGlobs[$this->OS]);
       foreach ($iterator as $item) {
-        if ($item->isDir()) {
+        if (
+          $item->isDir()
+          &&
+          ($version = $this->getWebIdeVersionFromPath($item->getPathname()))
+          &&
+          (
+            $version >= $this->webIdeVersionMin
+            &&
+            (!$this->webIdeVersionMax || $version <= $this->webIdeVersionMax)
+          )
+        ) {
           $webidehomes[] = $item->getPathname();
         }
       }
@@ -196,10 +190,16 @@ class WebIdeTemplateManager {
       // Get the latest.
       sort($webidehomes);
       $this->webIdeHome = array_pop($webidehomes);
-    } catch (UnexpectedValueException $e) {
+    }
+    catch (UnexpectedValueException $e) {
       throw new Exception('.WebIde not found');
     }
 
+    $this->webIdeHomeConfig = $this->webIdeHome;
+    if ($this->OS == self::OS_LINUX) {
+      $this->webIdeHomeConfig .= '/config';
+    }
+
     $this->stdout = fopen('php://stdout', 'w');
     $this->stderr = fopen('php://stderr', 'w');
 
@@ -219,6 +219,11 @@ class WebIdeTemplateManager {
     }
   }
 
+  protected function getWebIdeVersionFromPath($path) {
+    $matches = NULL;
+    return (preg_match('/\d+$/', $path, $matches)) ? $matches[0] : 0;
+  }
+
   /**
    * Recommended exit code.
    *
@@ -256,12 +261,6 @@ class WebIdeTemplateManager {
     elseif ($this->args[1] == 'push') {
       $this->push();
     }
-    elseif ($this->args[1] == 'live-template-sort') {
-      $this->liveTemplateSort();
-    }
-    elseif ($this->args[1] == 'git-hook') {
-      $this->gitHook();
-    }
     else {
       fwrite($this->stderr, "Unknown parameter.\n");
       fwrite($this->stderr, print_r($this->args, TRUE));
@@ -274,40 +273,58 @@ class WebIdeTemplateManager {
    */
   protected function pull() {
     $this->pullLiveTemplates();
+    $this->pullFileTemplates();
+    $this->pullFileTypes();
   }
 
-  /**
-   * Retrieve the updated templates from ~/.WebIde40/config.
-   */
-  protected function pullLiveTemplates() {
-    $templates = new GlobIterator("{$this->templateHome}/templates/*.xml");
-    if (!$templates->count()) {
-      fwrite($this->stdout, "No matches\n");
-      return;
-    }
-
+  protected function pullCopyFiles($options) {
+    fwrite($this->stdout, "{$options['name']}\n");
+    $templates = new GlobIterator("{$this->templateHome}/{$options['directory']}/{$options['glob']}");
     foreach ($templates as $template) {
       $filename = $template->getFilename();
       $pathname_git = $template->getPathname();
-      $pathname_config = "{$this->webIdeHome}/config/templates/$filename";
+      $pathname_config = "{$this->webIdeHomeConfig}/{$options['directory']}/$filename";
       if (is_file($pathname_config)) {
         $content_config = file_get_contents($pathname_config);
-        // @todo The sorting always breaks the equality.
         if ($content_config != file_get_contents($pathname_git)) {
           file_put_contents($pathname_git, $content_config);
-          if ($this->sortLiveTemplateItems) {
-            $this->liveTemplateSortByFilePath($pathname_git);
-          }
-          fwrite($this->stdout, "Copy: $filename\n");
+          fwrite($this->stdout, $this->indent . "Copy: $filename\n");
         }
         else {
-          fwrite($this->stdout, "Up to date: $filename\n");
+          fwrite($this->stdout, $this->indent . "Up to date: $filename\n");
         }
       }
     }
   }
 
   /**
+   * Retrieve the updated templates from ~/.WebIde40/config.
+   */
+  protected function pullLiveTemplates() {
+    $this->pullCopyFiles(array(
+      'glob' => '*.xml',
+      'name' => 'Live Templates',
+      'directory' => 'templates',
+    ));
+  }
+
+  protected function pullFileTemplates() {
+    $this->pullCopyFiles(array(
+        'glob' => '*.*',
+        'name' => 'File Templates',
+        'directory' => 'fileTemplates',
+      ));
+  }
+
+  protected function pullFileTypes() {
+    $this->pullCopyFiles(array(
+      'glob' => '*.xml',
+      'name' => 'File types',
+      'directory' => 'filetypes',
+    ));
+  }
+
+  /**
    * Copy templates from Git to WebIde.
    */
   protected function push() {
@@ -328,187 +345,76 @@ class WebIdeTemplateManager {
    *   -directory: Required.
    *    Destination directory.
    */
-  protected function pushSymlinks(array $options) {
+  protected function pushCopyFiles(array $options) {
     fwrite($this->stdout, "{$options['name']}\n");
     $templates = new GlobIterator("{$this->templateHome}/{$options['directory']}/{$options['glob']}");
     foreach ($templates as $template) {
       $filename = $template->getFilename();
       $pathname_git = $template->getPathname();
-      $pathname_config = "{$this->webIdeHome}/config/{$options['directory']}/$filename";
+      $pathname_config = "{$this->webIdeHomeConfig}/{$options['directory']}/$filename";
       if (!file_exists($pathname_config)) {
-        symlink($pathname_git, $pathname_config);
-        fwrite($this->stdout, "  Symlink: {$filename}\n");
+        copy($pathname_git, $pathname_config);
+        fwrite($this->stdout, $this->indent . "Copy: {$filename}\n");
       }
       elseif (is_link($pathname_config)) {
         $target = readlink($pathname_config);
         if ($pathname_git == $target) {
-          fwrite($this->stdout, "  Untouched: {$filename}\n");
+          unlink($pathname_config);
+          copy($pathname_git, $pathname_config);
+        }
+        else {
+          fwrite($this->stdout, $this->indent . "Point to elsewhere: {$filename}\n");
+        }
+      }
+      elseif (is_file($pathname_config)) {
+        if (!empty($options['force'])) {
+          file_put_contents($pathname_config, file_get_contents($pathname_git));
+          fwrite($this->stdout, $this->indent . "Force: $filename\n");
         }
         else {
-          fwrite($this->stdout, "  Point to elsewhere: {$filename}\n");
+          fwrite($this->stdout, $this->indent . "Skip: $filename\n");
         }
       }
       else {
-        fwrite($this->stdout, "  Exists: {$filename}\n");
+        copy($pathname_git, $pathname_config);
       }
     }
   }
 
   /**
-   * Deploy the file type definitions.
-   */
-  protected function pushFileTypes() {
-    $this->pushSymlinks(array(
-      'glob' => '*.xml',
-      'name' => 'File types',
-      'directory' => 'filetypes',
-    ));
-  }
-
-  /**
    * Copy live template files from Git to WebIde settings home.
    */
   protected function pushLiveTemplates() {
-    fwrite($this->stdout, "Live Templates\n");
-    $templates = new GlobIterator("{$this->templateHome}/templates/*.xml");
-    if (!$templates->count()) {
-      fwrite($this->stdout, "  No matches\n");
-      return;
-    }
-
-    $force = (count($this->args) > 2 && $this->args[2] == 'force');
-    foreach ($templates as $template) {
-      $filename = $template->getFilename();
-      $pathname_git = $template->getPathname();
-      $pathname_config = "{$this->webIdeHome}/config/templates/$filename";
-      if (is_file($pathname_config)) {
-        if ($force) {
-          file_put_contents($pathname_config, file_get_contents($pathname_git));
-          fwrite($this->stdout, "  Force: $filename\n");
-        }
-        else {
-          fwrite($this->stdout, "  Skip: $filename\n");
-        }
-      }
-      else {
-        file_put_contents($pathname_config, file_get_contents($pathname_git));
-        fwrite($this->stdout, "  Copy: $filename\n");
-      }
-    }
+    $this->pushCopyFiles(array(
+      'glob' => '*.xml',
+      'name' => 'Live Templates',
+      'directory' => 'templates',
+      'force' => (count($this->args) > 2 && $this->args[2] == 'force'),
+    ));
   }
 
   /**
    * Copy file template files from Git to WebIde settings home.
    */
   protected function pushFileTemplates() {
-    $this->pushSymlinks(array(
+    $this->pushCopyFiles(array(
       'glob' => '*.*',
       'name' => 'File templates',
       'directory' => 'fileTemplates',
+      'force' => (count($this->args) > 2 && $this->args[2] == 'force'),
     ));
   }
 
   /**
-   * Command line task handler.
-   */
-  protected function liveTemplateSort() {
-    $file_names = array_slice($this->args, 2);
-
-    if (!$file_names) {
-      $templates = new GlobIterator("{$this->templateHome}/templates/*.xml");
-      foreach ($templates as $template) {
-        $file_names[] = $template->getFilename();
-      }
-    }
-    else {
-      foreach (array_keys($file_names) as $i) {
-        $file_names[$i] = preg_replace('@^templates/@', '', $file_names[$i]);
-      }
-    }
-
-    foreach ($file_names as $file_name) {
-      $file_path = "{$this->templateHome}/templates/{$file_name}";
-      if (!is_file($file_path)) {
-        fwrite($this->stderr, "Unknown file: {$file_name}\n");
-        continue;
-      }
-
-      $this->liveTemplateSortByFilePath($file_path);
-    }
-  }
-
-  /**
-   * Sort the Live Template items.
-   *
-   * @param string $file_path
-   *   Path to Live Template XML.
-   */
-  protected function liveTemplateSortByFilePath($file_path) {
-    $doc = new DOMDocument();
-    $doc->preserveWhiteSpace = TRUE;
-    $doc->formatOutput = TRUE;
-    $doc->loadXML(file_get_contents($file_path));
-    $xpath = new DOMXPath($doc);
-
-    if (!self::liveTemplateIsOrdered($xpath)) {
-      self::liveTemplateSortTemplateSet($xpath);
-      $xml = preg_replace('@(<templateSet group="[^"]+">)(\s*)(?=<template name=")@', "\\1\n  ", $doc->saveXML());
-      $xml = preg_replace('@</template></templateSet>\s*$@', "</template>\n</templateSet>\n", $xml);
-      $xml = preg_replace('@(\n\s*</template>)(<template)@', "\\1\n  \\2", $xml);
-      file_put_contents($file_path, $xml);
-    }
-  }
-
-  /**
-   * Run a Git hook.
-   */
-  protected function gitHook() {
-    $hook = isset($this->args[2]) ? $this->args[2] : NULL;
-    switch ($hook) {
-      case 'pre-commit':
-        $this->gitHookPreCommit();
-        break;
-
-      default:
-        fwrite($this->stderr, "Unknown Git hook.\n");
-        fwrite($this->stderr, print_r($this->args, TRUE));
-        $this->exitCode = 1;
-        break;
-    }
-  }
-
-  /**
-   * Validate all templates.
-   */
-  protected function gitHookPreCommit() {
-    $this->gitHookPreCommitLiveTemplates();
-  }
-
-  /**
-   * Validate the Live Templates.
+   * Deploy the file type definitions.
    */
-  protected function gitHookPreCommitLiveTemplates() {
-    if ($this->sortLiveTemplateItems) {
-      $templates = new GlobIterator("{$this->templateHome}/templates/*.xml");
-      $unordered_templates = array();
-      foreach ($templates as $template) {
-        $doc = new DOMDocument();
-        $doc->loadXML(file_get_contents($template->getPathname()));
-        $xpath = new DOMXPath($doc);
-        if (!self::liveTemplateIsOrdered($xpath)) {
-          $unordered_templates[] = $template->getFilename();
-        }
-      }
-
-      if ($unordered_templates) {
-        fwrite($this->stderr,
-          "Unordered templates:\n{$this->indent}" .
-          implode("\n{$this->indent}", $unordered_templates) . "\n"
-        );
-
-        $this->setExitCode(1);
-      }
-    }
+  protected function pushFileTypes() {
+    $this->pushCopyFiles(array(
+      'glob' => '*.xml',
+      'name' => 'File types',
+      'directory' => 'filetypes',
+      'force' => (count($this->args) > 2 && $this->args[2] == 'force'),
+    ));
   }
 }
 
