#
# linter.py
# Linter for SublimeLinter3, a code checking framework for Sublime Text 3
#
# Written by roadhump
# Copyright (c) 2014 roadhump
#
# License: MIT
#

"""This module exports the ESLint plugin class."""

import sublime
import os
import re
from SublimeLinter.lint import NodeLinter


class ESLint(NodeLinter):

    """Provides an interface to the eslint executable."""

    syntax = ('javascript', 'html', 'javascriptnext', 'javascript (babel)', 'javascript (jsx)', 'jsx-real')
    npm_name = 'eslint'
    cmd = ('eslint', '--format', 'compact', '--stdin', '--stdin-filename', '__RELATIVE_TO_FOLDER__')
    version_args = '--version'
    version_re = r'v(?P<version>\d+\.\d+\.\d+)'
    version_requirement = '>= 1.0.0'
    regex = (
        r'^.+?: line (?P<line>\d+), col (?P<col>\d+), '
        r'(?:(?P<error>Error)|(?P<warning>Warning)) - '
        r'(?P<message>.+)'
    )
    config_fail_regex = re.compile(r'^Cannot read config file: .*\r?\n')
    crash_regex = re.compile(
        r'^(.*?)\r?\n\w*Error: \1',
        re.MULTILINE
    )
    line_col_base = (1, 1)
    selectors = {
        'html': 'source.js.embedded.html'
    }

    def find_errors(self, output):
        """
        Parse errors from linter's output.

        We override this method to handle parsing eslint crashes.
        """

        match = self.config_fail_regex.match(output)
        if match:
            return [(match, 0, None, "Error", "", match.group(0), None)]

        match = self.crash_regex.match(output)
        if match:
            msg = "ESLint crashed: %s" % match.group(1)
            return [(match, 0, None, "Error", "", msg, None)]

        return super().find_errors(output)

    def split_match(self, match):
        """
        Extract and return values from match.

        We override this method to silent warning by .eslintignore settings.
        """

        match, line, col, error, warning, message, near = super().split_match(match)
        if message and message == 'File ignored because of your .eslintignore file. Use --no-ignore to override.':
            return match, None, None, None, None, '', None

        return match, line, col, error, warning, message, near

    def communicate(self, cmd, code=None):
        """Run an external executable using stdin to pass code and return its output."""

        if '__RELATIVE_TO_FOLDER__' in cmd:

            relfilename = self.filename
            window = self.view.window()

            # can't get active folder, it will work only if there is one folder in project
            if int(sublime.version()) >= 3080 and len(window.folders()) < 2:

                vars = window.extract_variables()

                if 'folder' in vars:
                    relfilename = os.path.relpath(self.filename, vars['folder'])

            cmd[cmd.index('__RELATIVE_TO_FOLDER__')] = relfilename

        elif not code:
            cmd.append(self.filename)

        return super().communicate(cmd, code)

@@ -488,16 +488,65 @@
     
+executables = %7B%0A        'eslint': %7B%0A            '
 npm_name
  = '
@@ -541,18 +541,18 @@
 npm_name
- =
+':
  'eslint
@@ -556,18 +556,28 @@
 int'
+,
 %0A    
+        '
 cmd
- =
+':
  ('e
@@ -664,16 +664,146 @@
 DER__')%0A
+        %7D,%0A        'eslint_d': %7B%0A            'npm_name': 'eslint_d',%0A            'cmd': ('eslint_d', 'lint', '@')%0A        %7D%0A    %7D%0A
     vers
@@ -3153,8 +3153,322 @@
 , code)%0A
+%0A    def cmd(self):%0A        %22%22%22Support eslint_d.%22%22%22%0A%0A        executable = self.executables%5B'eslint'%5D%0A%0A        if self.get_view_settings().get('eslint_d', False):%0A            executable = self.executables%5B'eslint_d'%5D%0A%0A        self.npm_name = executable%5B'npm_name'%5D%0A%0A        return self.build_cmd(executable%5B'cmd'%5D)%0A

Add basic support of eslint_d