Showing posts with label cygwin. Show all posts
Showing posts with label cygwin. Show all posts

Friday, August 11, 2017

Cygwin terminal in IntelliJ

IntelliJ sports an excellent terminal emulator (the "Terminal" tab at bottom of the editor). By default it brings up a terminal native to your Operating System: CMD.EXE on Windows, $SHELL on Linux and Mac.

However I prefer Cygwin when I work on Windows. WSL is incredible, but there are still interoperability issues between its filesystem and Windows-native programs, and IntelliJ (which relies on java.exe, a Windows-native program) is still working on it.

So, how to open a Cygwin terminal in IntelliJ? Setting the program to start in Settings|Tools|Terminal|Shell path, the most obvious thing to do, does not quite work:

C:\cygwin64\bin\bash.exe

This is a non-interactive shell, and does not source your profile. The next try is:

C:\cygwin64\bin\bash.exe --login -i

This produces an error from IntelliJ that it cannot start the program correctly. A little checking says the leading command needs to be quoted, else IntelliJ treats the entire line as the name of the command, not as a command followed by flags. OK:

"C:\cygwin64\bin\bash.exe" --login -i

Hey, I have a shell! Unfortunately, it starts in my home directory, not in my project root. Starting in the project root is one of the nice features of the terminal in IntelliJ. Finally, two changes. First the IntelliJ setting:

"C:\cygwin64\bin\bash" -c "exec /usr/bin/env INTELLIJ=true $SHELL --login -i"

And an addition to my ~/.bashrc:

${INTELLIJ-false} && cd ${OLDPWD-.}

Ipso presto!

Saturday, April 29, 2017

Maven color logging on Cygwin

WORKAROUND: Thanks to comment by Zart Colwing, there is a workaround. Add -Djansi.passthrough=true to MAVEN_OPTS. It is not enough to add the flag to the command line; it needs to be seen by JANSI before maven begins parsing the command line. See No color for maven on Cygwin to track the issue.

Post

I'm quite happy Maven 3.5.0 has added color logging!

With earlier versions of maven, I used Jean-Christophe Guy's excellent maven-color extension. On Windows that involved some manual hacking of my maven installation, but on Mac, it was trivial with homebrew.

So now I'm getting color output from maven out of the box. Except when I don't.

You see, this new feature relies on the good JAnsi library. And JAnsi presently has an issue with color on Cygwin. When I'm at home, Cygwin is my mainstay, used on my gaming-cum-programming rig, so this is significant to me. What is the issue? No color—JAnsi detects I'm on Windows, and uses the native Windows console color handling, which doesn't work in Mintty or Xterm. Those use standard ANSI escape sequences, etc. rather than an OS-specific library.

Digging through the source for JAnsi, I find the trouble spot:

private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("win");

Aha! The special Windows-handling code kicks in when the os.name system property contains "win" (in any case). Using the jps and jinfo tools that come with the JDK, I double-checked against a long-running maven build (16848 just was the PID used by the JVM for this maven build; use jps to list all current PIDs):

$ jinfo -sysprops 16848 | grep os.name
os.name = Windows 10

Some experimenting found a way to work around that:

MAVEN_OPTS=-Dos.name=Cygwin mvn clean

(You need to use MAVEN_OPTS rather than passing -Dos.name=Cygwin to maven; once maven starts the value is immutable.)

Color is back. It turns out, any value for os.name will work (for example, "Bob") as long as it doesn't contain "win". I picked "Cygwin" for explicitness.

UPDATE: I have to rethink this. Sure I get color now, but at the expense of maven test failing as maven no longer believes I'm on Windows, so is unhappy at the lack of a /bin/sh and general UNIX filesystem. One step forward, two steps back.

Saturday, April 01, 2017

Kotlinc on Cygwin

There may be a better way, but I found that running kotlinc to bring up the Kotlin REPL, while in a Cygwin BASH shell using Mintty, did not respond to keyboard input. A little research indicated the issue is with JLine, which has some understandable difficulties reconciling running under Cygwin with running under CMD.

The workaround I used:

$ JAVA_OPTS='-Djline.terminal=unix' kotlinc
Welcome to Kotlin version 1.1.1 (JRE 1.8.0_121-b13)
Type :help for help, :quit for quit
>>> println("FOOBAR")
println("FOOBAR")
FOOBAR

Requesting JLine to use UNIX-y primitives for terminal access solved the problem. I would like to hear about other solutions.

UPDATE: Edited for clarity. And some additional reading:

Tuesday, August 21, 2007

Cygwin BASH wrapper for Maven deploy:deploy-file

I frequently use Maven's deploy:deploy-file mojo for building project-local repositories.

Many interesting 3rd-party Java libraries are not (yet) available from public Maven repositories (the otherwise excellent dev.java.net projects are particularly weak in this respect), but I want to use them in my project POM. What to do?

I store them with my project. This is not an ideal solution, but it is practical.

To help me deploying jars, sources and javadocs I wrote a simple BASH wrapper script for Cygwin (to run under Linux/UNIX requires a trivial change). Here is typical use:

$ mvn-file-deploy ~/IdeaProjects/Scratch/lib cool-library-1.0.4.jar org.cool.library:cool-library:1.0.4
$ mvn-file-deploy -S ~/IdeaProjects/Scratch/lib cool-library-1.0.4-sources.jar org.cool.library:cool-library:1.0.4
$ mvn-file-deploy -J ~/IdeaProjects/Scratch/lib cool-library-1.0.4-javadocs.jar org.cool.library:cool-library:1.0.4

And the script itself:

#!/bin/bash

function help()
{
    cat <<'EOH' | fmt
Usage: mvn-file-deploy [options] REPO_PATH FILE_PATH DESCRIPTOR [CLASSIFIER]

Use mvn-file-deploy as a helper for 'mvn deploy:deploy-file' when using Cygwin.

EOH
    cat <<'EOH'
Options:
  -h, --help          Print this help message
      --version       Print program version
  -S, --sources       Deploy sources
  -J, --javadocs      Deploy javadocs
  -q, --quiet         Do not print maven command
EOH
    cat <<'EOH' | fmt

Other options are passed to Maven.  (BROKEN)

Examples:

The most common use is to run it like this:

    $ mvn-file-deploy C:/my/project/lib C:/some/interesting.jar groupId:artifactId:version

Or if you use a classifier (e.g., jdk5):

But sometimes like this.

    $ mvn-file-deploy C:/my/project/lib C:/some/interesting.jar groupId:artifactId:version classifier

Report bugs to <binkley@alumni.rice.edu>.
EOH
}

function version()
{
    cat <<'EOV' | fmt
mvn-file-deploy 1.0
Copyright (C) 2007 JPMorganChase, Inc.  All rights reserved.
EOV
}

function fatal()
{
    echo "$0: $*" >&2
    exit 2
}

function usage() 
{
    cat <<'EOU' | fmt >&2
usage: mvn-file-deploy [options] REPO_PATH FILE_PATH DESCRIPTOR [CLASSIFIER]
EOU
}

eval set -- "$(getopt -o hJSq --long help,javadocs,sources,quiet,version -n "$0" -- "$@")"

declare -a maven_opts
declare -a args

for opt
do
    shift
    case "$opt" in
        -h|--help ) help ; exit 0 ;;
        -J|--javadocs ) classifier=-Dclassifier=javadocs ;;
        -S|--sources ) classifier=-Dclassifier=sources ;;
        --version ) version ; exit 0 ;;
        -q|--quiet ) quiet=t ; maven_opts=("${maven_opts[@]}" "$opt") ;;
        -- ) break ;;
        -* ) maven_opts=("${maven_opts[@]}" "$opt") ;;
    esac
done

case $# in
    3 ) repo_path="$1"
        file_path="$2"
        descriptor="$3" ;;
    4 ) repo_path="$1"
        file_path="$2"
        descriptor="$3"
        classifier=-Dclassifier="$4" ;;
    * ) usage ; exit 2 ;;
esac

(cd "$repo_path" 2>/dev/null) || \
    fatal "No such repository path: $repo_path"

repo_url="file://$(cygpath -am "$repo_path")"
file_path="$(cygpath -am "$file_path")"

[[ -r "$file_path" ]] || \
    fatal "No such artifact: $file_path"

triplet=($(echo $descriptor | tr : ' '))

(( 3 == ${#triplet[*]} )) || \
    fatal "Descriptor not groupId:artifactId:version format: $descriptor"

packaging=-Dpackaging="${file_path##*.}"

[[ -n "$quiet" ]] ||
    echo mvn "${maven_opts[@]}" deploy:deploy-file -Durl="$repo_url" \
        -DrepositoryId=project -Dfile="$file_path" -DgroupId=${triplet[0]} \
        -DartifactId=${triplet[1]} -Dversion=${triplet[2]} \
        $packaging $classifier
exec mvn "${maven_opts[@]}" deploy:deploy-file -Durl="$repo_url" \
    -DrepositoryId=project -Dfile="$file_path" -DgroupId=${triplet[0]} \
    -DartifactId=${triplet[1]} -Dversion=${triplet[2]} \
    $packaging $classifier