Using ESLint in Komodo Edit

In the Syntax Checking portion of the Preferences menu, there is an option to “Choose a custom or update jshint”…Is it possible to use ESLint as the custom linter? If so, what file is required for this?

I’m new to Komodo Edit and have never bothered changing linters in a code editor. My intent is to have a linter that can handle JSX syntax. With JSHint I’m getting “Unclosed regular expression” errors when I reference a component in my JSX markup. I love how powerful Komodo Edit is as far as code editors go. If there’s another way to go about getting JSX support, please let me know.

Thanks

There’s no way to use ESLint. You’d want to file an enhancement request for that.

I’m not familiar with ESLint, but if you can invoke it in some way to output JSHint-style errors and warnings, then it may be possible to use it.

There’s a unix format:
file:line:column: message [category].

I wrote my own Linter for ES but I don’t know how to invoke it.

ESLint requires a config file to be generated in the cwd directory (eslint --init), so I think the tmp thing won’t do the trick.

You can pass path to the using -c but I don’t know how to get current directory from this scope.

# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at http://mozilla.org/MPL/2.0/.

import logging

from xpcom import components
import koLintResult
from koLintResult import KoLintResult, SEV_ERROR, SEV_WARNING, SEV_INFO
from koLintResult import createAddResult as add_result
from koLintResults import koLintResults

import os, sys, re, which
import tempfile
import process
import koprocessutils

log = logging.getLogger('eslint')

eslint_error_re = re.compile(r'.+?:(\d+):(\d+):\s([^\n]+)')

class JavascriptEsLinter(object):
    _com_interfaces_ = [components.interfaces.koILinter]
    _reg_desc_ = "Javascript EsLinter"
    _reg_clsid_ = "{741a5498-e66b-4df6-958c-71b0ef135539}"
    _reg_contractid_ = "@defman.me/JavascriptEsLinter;1"
    _reg_categories_ = [
         ("category-komodo-linter", 'JavaScript'),
         ]

    def __init__(self):
        try:
            self._userPath = koprocessutils.getUserEnv()["PATH"].split(os.pathsep)
        except:
            msg = "JavascriptEsLinter: can't get user path"
            if msg not in _complained:
                _complained[msg] = None
                log.exception(msg)
            self._userPath = None
        
    def lint(self, request):
        text = request.content.encode(request.encoding.python_encoding_name)
        return self.lint_with_text(request, text)

    def lint_with_text(self, request, text):
        if not text:
            return None
        prefset = request.prefset
        if not prefset.getBooleanPref("lint_js_with_eslint"):
            return
        try:
            eslint_exe = which.which("eslint", path=self._userPath)
            if not eslint_exe:
                return
            if sys.platform.startswith("win") and os.path.exists(eslint_exe + ".cmd"):
                eslint_exe += ".cmd"
        except which.WhichError:
            msg = "eslint not found"
            if msg not in _complained:
                _complained[msg] = None
                log.error(msg)
            return
        tmpfilename = tempfile.mktemp() + '.js'
        fout = open(tmpfilename, 'wb')
        fout.write(text)
        fout.close()
        textlines = text.splitlines()
        cwd = request.cwd
        cmd = [eslint_exe, "--no-color", "--format", "unix", tmpfilename]
        # We only need the stderr result.
        try:
            p = process.ProcessOpen(cmd, cwd=cwd, stdin=None)
            _, stderr = p.communicate()
            warnLines = stderr.splitlines(0) # Don't need the newlines.
        except:
            log.exception("Problem running %s", coffeeExe)
            warnLines = []
        finally:
            os.unlink(tmpfilename)
        ptn = eslint_error_re
        results = koLintResults()
        for line in warnLines:
            m = ptn.match(line)
            if m:
                lineNo = int(m.group(1))
                colNo = int(m.group(2))
                desc = "%s (on column %d)" % (m.group(3), colNo)
                severity = koLintResult.SEV_ERROR
                koLintResult.createAddResult(results, textlines, severity,
                                             lineNo, desc, columnStart=colNo)
        return results

I think what you’d want to do is create a bash script or some executable that invokes ESLint with the proper arguments. Then point Komodo’s “JSHint” at that executable. That way Komodo thinks it’s calling JSHint, but you’re really invoking ESLint and spitting out JSHint-style errors and warnings – Komodo wouldn’t know the difference.

Bash script is not something that Komodo will recognize. Komodo will try to run it using Mozilla’s JS executable. So you’d have to write a javascript thing. I’ll look in that.

UPD: I’m not going to do that.

  • ESLint does not have a special version of the script for SpiderMonkey, so I can’t load it (it will cause errors).
  • SpiderMonkey does not have an ability to run bash commands.

The only one way is actually creating a linter for it.

Is there a particular reason why you’d want to use ESLint instead of JSHint?

That’s a serious question, not trying to start a A is better than B debate, simply would like to know the feasibility of supporting both.

ESLint supports JSX.

Gotcha. Worth looking into.

As a workaround you could use JSXHint, it appears deprecated in favor of ESLint but it should at least be compatible with JSHint.

Seems that Komodo could use much more configurable options for building, debugging, linting, anything that uses external scripts/commands. The Javascript world is moving at a rather radical pace right now, with dozens? of commonly used build systems, linters, transpilers, et al. Basically over the last few months, virtually everyone I know who works with Javascript professionally has moved from just running their code, to running Bower and WebPack, to Browserify with Babelify with Minifyify, and all sorts of other combinations within. And there are other tools that are coming in the near future (Rollup?) … A common factor amongst almost everyone’s development system now, is that lots and lots of people have moved from using jshint to eslint.

Upgrading jshint to 2.9.3 from the default 2.6.3 does provide a lot of functionality, although there are a fair number of glitches in Komodo involved afterwards, such as getting some code intel notifications stuck on top of all other windows, and it seems to wildly mess up code colorization and linting when using template literals sometimes.

Probably the biggest thing that eslint provides, is the easily extensible and shareable configuration – virtually everyone i know is now using the AirBNB style guide that is packaged as a NPM module plugin for ESlint . . . or some close derivative of it. As far as I can tell, there is no quick way to migrate between the two … and ESlint’s configuration is very simple to extend … just { “extends”: “airbnb”, “rules”: { … rules override object … } }

I’ve been a KEdit user for many years now, but the rapidly changing requirements for Javascript … and the fact that I’m now working almost 100% in Javascript (with a little QML thrown in… which is basically Javascript … and Komodo doesn’t support) instead of spending time switching between PHP, Python, Javascript, HTML, and others … has me investigating VSCode right now… and although VSCode is quite painful to configure, I have suspicions that it could become a second favorite to me (after KEdit) …

adding ESlint support would at least make Komodo Edit fit into the new specifications that I have to work with. :slight_smile: