diff --git a/.gitignore b/.gitignore index 6775fcf7..3be1b022 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /init.vim /doc/tags .* +*.obj diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9aa11446..e263d37f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,7 @@ 1. [Guidelines](#guidelines) 2. [Creating Pull Requests](#pull-requests) +3. [Creating Pull Requests](#compiling) @@ -40,6 +41,21 @@ table and list. # 2.2. Adding New Options If you add new options to the plugin, make sure to document those new options in the [README.md](README.md) file, and also -in the [help file](doc/ale.txt). Follow the format of other options in each. Global options should appear in the README +in the [help file](doc/ale.txt). Follow the format of other options in each. Global options should appear in the README file, and in the relevant section in the help file, and options specific to a particular linter should go in the section for that linter. + + + +# 3. Compiling the Windows stdin wrapper + +To compile the stdin wrapper program for Windows, when updating the D program, you will need to compile the program with +[LDC](https://github.com/ldc-developers/ldc) in release mode. Download and install the Community edition of Visual Studio +from [the Visual Studio website](https://www.visualstudio.com/downloads/) first before installing LDC. LDC typically comes in +a ZIP you can just extract somewhere. + +Make sure to compile with the 32-bit architecture flag, otherwise the EXE will not run on 32-bit machines. + +``` +ldc2 -m32 -Oz -release stdin_wrapper.d -of=stdin-wrapper.exe +``` diff --git a/README.md b/README.md index a3b2f672..8f2e74f9 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,11 @@ name. That seems to be the fairest way to arrange this table. | Bourne Shell | [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/) | | C | [gcc](https://gcc.gnu.org/) | | CoffeeScript | [coffeelint](https://www.npmjs.com/package/coffeelint) | -| CSS | [csslint](http://csslint.net/)^ | -| Cython (pyrex filetype) | [cython](http://cython.org/)^ | +| CSS | [csslint](http://csslint.net/) | +| Cython (pyrex filetype) | [cython](http://cython.org/) | | D | [dmd](https://dlang.org/dmd-linux.html)^ | | Fortran | [gcc](https://gcc.gnu.org/) | -| Haskell | [ghc](https://www.haskell.org/ghc/)^ | +| Haskell | [ghc](https://www.haskell.org/ghc/) | | HTML | [tidy](http://www.html-tidy.org/) | | JavaScript | [eslint](http://eslint.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/) | | JSON | [jsonlint](http://zaa.ch/jsonlint/) | @@ -44,9 +44,9 @@ name. That seems to be the fairest way to arrange this table. | SASS | [sass-lint](https://www.npmjs.com/package/sass-lint) | | SCSS | [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint) | | Scala | [scalac](http://scala-lang.org) | -| TypeScript | [tslint](https://github.com/palantir/tslint)^ | -| Vim | [vint](https://github.com/Kuniwak/vint)^ | -| YAML | [yamllint](https://yamllint.readthedocs.io/)^ | +| TypeScript | [tslint](https://github.com/palantir/tslint) | +| Vim | [vint](https://github.com/Kuniwak/vint) | +| YAML | [yamllint](https://yamllint.readthedocs.io/) | *^ Supported only on Unix machines via a wrapper script.* diff --git a/plugin/ale/util.vim b/plugin/ale/util.vim index 38e1d95d..fd9bb356 100644 --- a/plugin/ale/util.vim +++ b/plugin/ale/util.vim @@ -13,6 +13,10 @@ function! s:FindWrapperScript() let path = expand(parent . '/' . 'stdin-wrapper') if filereadable(path) + if has('win32') + return path . '.exe' + endif + return path endif endfor diff --git a/stdin-wrapper.exe b/stdin-wrapper.exe new file mode 100644 index 00000000..d79f6785 Binary files /dev/null and b/stdin-wrapper.exe differ diff --git a/stdin_wrapper.d b/stdin_wrapper.d new file mode 100644 index 00000000..8714bc2a --- /dev/null +++ b/stdin_wrapper.d @@ -0,0 +1,84 @@ +// Author: w0rp +// Description: This file provides a D program for implementing +// the stdin-wrapper on Windows. + +import std.algorithm; +import std.array; +import std.file; +import std.process; +import std.stdio; +import std.path; + +@safe +auto createTemporaryFilename(string fileExtension) { + import std.uuid; + + string filename; + + do { + const randomPart = randomUUID().toString.replace("-", "_"); + + filename = buildPath(tempDir(), "ale_" ~ randomPart ~ fileExtension); + } while (exists(filename)); + + return filename; +} + +@trusted +void readStdinToFile(ref File tempFile) { + stdin.byChunk(4096).copy(tempFile.lockingTextWriter()); +} + +// Expand program names like "csslint" to "csslint.cmd" +// D is not able to perform this kind of expanstion in spawnProcess +@safe +string expandedProgramName(string name) { + auto extArray = environment["PATHEXT"].split(";"); + + foreach(pathDir; environment["PATH"].split(";")) { + foreach(extension; extArray) { + const candidate = buildPath(pathDir, name ~ extension); + + if (exists(candidate)) { + return candidate; + } + } + } + + // We were given a full path for a program name, so use that. + if (exists(name)) { + return name; + } + + return ""; +} + +@trusted +int runLinterProgram(string[] args) { + const expandedName = expandedProgramName(args[0]); + + writeln(expandedName); + + if (expandedName) { + return wait(spawnProcess([expandedName] ~ args[1..$])); + } + + return 1; +} + +@safe +int main(string[] args) { + const filename = createTemporaryFilename(args[1]); + + auto tempFile = File(filename, "w"); + + scope(exit) { + tempFile.close(); + remove(filename); + } + + readStdinToFile(tempFile); + tempFile.close(); + + return runLinterProgram(args[2..$] ~ [filename]); +}