Friday, February 28, 2020

Set Cmder (ConEmu) console emulator to open new tab in current directory with Bash shell

Windows is a truly bad operating system for almost everything except games. Unfortunately sometimes we have to use it for web development. If you're coming from a Linux/Mac environment, the operating systems of choice for web development because Linux servers dominate the Internet, the command line options in Windows are barbaric. The Windows developers have finally seen the light—after more than 20 years—and are working on incorporating native Linux with the Windows Subsystem for Linux project.

In the meantime, a popular console emulator that mimics Linux on Windows is Cmder, which is running ConEmu under the covers. I recommend downloading the Full version that includes Git for Windows since most developers are using Git and GitHub for project version control.

Cmder gives you back the the most common, familiar Linux commands. If you've been using the MacOS Terminal, you're used to opening a new tab in the current working directory with Cmd+T. Unfortunately Cmder doesn't do this be default and figuring out how to do it is maddeningly difficult. Thanks to this tip, I will explain how to do it.

ConEmu offers several choices for consoles, like the old-school cmd, the newer PowerShell, and Bash. I use {Bash::Git bash} as my preferred console.

You have a lot of control of the commands it runs when it opens a new window. You can find them under Settings (Win+Alt+P) > Startup and Settings > Startup > Tasks.

To use hotkey Ctrl+T to open a new tab with the Bash shell in the current directory, rather than the default directory:
  1. Go to Settings > Startup > Tasks
  2. Select the {Bash::Git bash} option
  3. Set the Hotkey to Ctrl+T
  4. Modify the command to start with -new_console:d:"%CD%"
  5. Save settings
The d: option sets the startup directory and the "%CD%" option uses the current directory.




In order for it to read the current directory into environment variable %CD%, you have to enable it in your .bash_profile or .bashrc startup script. In ~/.bash_profile add this:

if [[ -n "${ConEmuPID}" ]]; then
  export PROMPT_COMMAND='ConEmuC -StoreCWD'
fi


See also:

Cmder documetation on GitHub
Cmder wiki
ConEmu documentation

Monday, December 9, 2019

Set zsh (zshell) colors for ls command

Catalina uses zsh (zshell) instead of the old bash or (even older) sh. To set colorized display of files and directories when using the ls command, modify ~/.zprofile or ~/.zshrc with something like:

export CLICOLOR=1
export LSCOLORS=CxFxExDxBxegedabagaced

When you run the ls command, it will display the files colorized according to their type like this:












Setting CLICOLOR to 1 enables colorization. Setting LSCOLORS to the string shown sets the colors for the different file types.

For a detailed explanation of the attributes and colors and how they are set, see:

How to enable colorized output for ls command in MacOS X Terminal



Set zsh (zshell) prompt in Mac OS Catalina terminal

Catalina uses zsh (zshell) instead of the old bash or (even older) sh. To set the command prompt, modify ~/.zprofile or ~/.zshrc with something like:


#--------------------ZSH script commands--------------------#
#  %B  Bold on
#  %b  bold off
#  %F  color on, %F{green} or %F{2}
#  %f  color off
#  %D  date with strftime options in {}
#      %a  weekday 3-letter abbreviation (Mon)
#      %x  locale date (09/30/13)
#      %X  locale time (07:06:05)
#  %n  user
#  %m  machine
#  %/  directory path
#  %#  show % unless elevated privileges (sudo), then show #
#  $'\n'  newline
#
#-----------------------------------------------------------#

PROMPT="%B%F{green}%D{%a %x %X} %F{red}%n%F{white}@%F{cyan}%m %F{yellow}%/%f %#"$'\n'"> "

This will generate a prompt that looks like this, with the command prompt on the next line down:





You can use either PS1 or PROMPT. PS1 may be set in /etc/zshrc and it will override your setting. To disable it, edit /etc/zshrc and comment out the PS1 line. You may have to use sudo vim and write your changes with w! (and exit with q!) because the permissions may be set to read-only for everyone.

For a detailed explanation of setting the prompt in zsh, see:

zsh Prompt Expansion
Customizing the zsh prompt

For a list of 256 colors whose numeric values you can use in place of red, green, yellow, blue, magenta, cyan, and white, see:

256 Colors Cheat Sheet

Here's a strftime reference for options to include with %D for date and time formatting:

Python's strftime directives


Monday, May 6, 2019

Key event handlers in Vue

What I learned about setting event handling for keys in Vue is:
  1. Add the v-on directive (shorthand is @) to the element (for example; @keyup, @keydown).

  2. Set focus on the element (add the property tabindex="0").

  3. To set focus programmatically with .focus(), if the action or event that initiated the change in focus causes the DOM to change (it usually does) you must set focus using $nextTick to wait for the DOM to update first.

<div class="notify-item-list" v-for="(entry, index) in category.entries" :key="entry.id">
    <a href="#" @click="selectItem(category.entries, index)" class="text-black" :class="{ 'text-bold': isUnread(entry) }">{{ entry.title }}</a>
    <div id="notification-modal" tabindex="0" ref="notifyModal" @keyup="navKeys" class="item-detail modal" :class="{ 'is-active': showItemDetail(entry) }">

methods: {
    selectItem: function ( entries, index ) {
        this.selectedItemIndex = index;
        this.$nextTick( () => {
            let input = this.$refs.notifyModal[index];
            input.focus();
        }),
    navKeys: function ( e ) {
        switch( e.keyCode ) {
            case 27: // esc
                this.hideItemDetail();
                break;
            case 37: // left
                this.prevNotificationDetail(this.category.entries);
                break;
            case 39: // right
                this.nextNotificationDetail(this.category.entries);
                break;
        }
    }
}


It’s a little more involved when multiple similar elements are created with the v-for directive, but you can simplify it by adding the ref="whatever" attribute, then use the index of the array to find the right object and its $refs.whatever, for example this.$refs.whatever[index]. Here’s a discussion of how to do this with v-for:

https://laracasts.com/discuss/channels/vue/vue-set-focus-to-input-created-by-v-for?page=1

See the 4th, 5th, and 6th replies by Kazuya.Gosho, MacPrawn and lukas.pierce. The last one was the most helpful. Anyway, it works like a charm. Feels a little kludgy, but considering how the user is interacting with the DOM it makes sense.

Wednesday, July 25, 2018

Mimic PC NumLock on Mac with 101/102 Key PC Keyboard

I use a MacBook Pro with a leftover Dell 102-key PC keyboard. For almost everything it works great. Even the volume keys work. However, the NumLock doesn't behave the way it does on a PC.

I mostly use the number pad on the right to move the cursor around for editing. It makes editing really fast because the cursor keys are easily reached; just like using the A,S,D,W keys for navigating in a video game. I rarely use the number pad for entering numbers; just when I have a long series of number I want to rapidly input. If it's only one or two numbers, I use the number keys at the top of the keyboard. Using the NumLock key to switch back and forth between cursor control and number entry is extremely handy, but the Apple keyboard doesn't have this feature.

Karabiner to the rescue


I found a popular keyboard-mapping utility for Mac called Karabiner. It allows me to remap the keyboard for specific keyboards, so I can map the keypad 0-9 keys to cursor movement for just the Dell keyboard; however I can't quickly switch back to the default functions.

Map NumLock to toggle between keyboard profiles


The solution is to create 2 keyboard profiles. I modified the "Default profile" to map the keypad keys for cursor movement and created another profile, "NumLock On" that reverts to the original function of the keypad keys for number entry. Then I mapped the NumLock key to run a shell_command calling Karabiner from the command line and loading the other profile. You can see the way it's set up in ~/.config/karabiner/karabiner.json. Here is the relevant code:
    {   
        "from": {
            "key_code": "keypad_9"
        },
        "to": {
            "key_code": "page_up"
        }
    },
    {
        "from": {
            "key_code": "keypad_num_lock"
        },
        "to": {
            "shell_command": "'/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli' --select-profile 'NumLock On'"
        }
    },
    {
        "from": {
            "key_code": "keypad_period"
        },
        "to": {
            "key_code": "delete_forward"
        }
    }
The key_code, "keypad_num_lock", in the profile, "Default profile", is mapped to a "shell_command" which runs the Karabiner command-line interface (cli) and selects the "NumLock On" profile.

In the "NumLock On" profile, keypad_num_lock also runs the Karabiner cli but selects the "Default profile", like this:
     {
         "from": {
             "key_code": "f12"
         },
         "to": {
             "consumer_key_code": "volume_increment"
         }
     },
     {
         "from": {
             "key_code": "keypad_num_lock"
         },
         "to": {
             "shell_command": "'/Library/Application Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli' --select-profile 'Default profile'"
         }
     }
For more on Karabiner, see:

Karabiner Manual

Karabiner JSON Reference Manual

Wednesday, September 27, 2017

View or Suppress Logback Status

Logback always shows status statements if there are configuration errors


Logback will log its own status statements to the console if you have any configuration problems resulting in WARN or ERROR messages, which will also show INFO messages. The Logback levels are, from lowest level to highest level:

TRACE < DEBUG < INFO < WARN < ERROR

(See Logback Architecture: error levels for details.)

See Logback status statements


To see Logback's status statements in the console (standard out) regardless of whether or not there are any configuration errors, set the debug attribute to true in the configuration element.
  <configuration debug="true">
    ...
  <configuration>

Suppress Logback status statements


To suppress display of Logback's status statements to the console, omit the debug attribute in the configuration element or set it to false. This will not suppress status statements if there are configuration problems with Logback.
  <configuration>
    ...
  </configuration>
If there is no debug attribute or it's set to false and you see Logback status statements, fix the problems causing the WARN or ERROR statements and the statements will no longer display.

If you can't fix the configuration problem but want to suppress the status statements, you can configure an alternate StatusListener like NopStatusListener to completely remove status statements.
  <configuration>
    <statusListener class="ch.qos.logback.core.status.NopStatusListener" />
    ...
  </configuration>
See also:

Logback Configuration: Automatic printing of status messages in case of warning or errors
Logback Configuration: Show status data
Logback Configuration

Wednesday, March 1, 2017

Use swagger-codegen to generate Java code from Swagger Spec

Swagger is the most popular standard for describing RESTful APIs. The Swagger Specification (formerly known as the OpenAPI Specification) is a JSON or YAML document that describes an API's endpoints, HTTP methods (GET, PUT, POST, etc.), possible responses and fields, possible errors, etc.

Swagger has code generators that will read a Swagger Specification and generate code in a variety of programming languages to consume the API. This saves a lot of time. The command line code generator is a Java Jar file. You need Java 7 or higher installed to run it. There is also a Maven plugin for Java projects that can generate the code for you as part of your project build process.


You can get help from the command line utility by running:
java -jar swagger-codegen-cli.jar help

which shows:
The most commonly used swagger-codegen-cli commands are:
    config-help   Config help for chosen lang
    generate      Generate code with chosen lang
    help          Display help information
    langs         Shows available langs
    meta          MetaGenerator. Generator for creating a new template set...
    version       Show version information

See 'swagger-codegen-cli help <command>' for more information on a specific command.

If you want detailed help about the generate command:
java -jar swagger-codegen-cli.jar help generate

The code generator can use a local Swagger doc or one hosted on a website. There is a quirk about how it handles URLs.

If the Swagger doc path is a URL and the URL has query parameters in it separated by an ampersand (&), you have to modify the URL slightly depending on whether you are using the command-line utility or the Maven plugin.

Command Line Utility (CLI)


When using swagger-codegen-cli.jar, enclose the -i (or --input-spec) parameter in double quotes if the URL has query parameters, like this:
-i "https://my.api.com/store/api-docs?provider=USER/me&name=MyNewService&version=v1"

For example:
java -jar swagger-codegen-cli.jar generate -l java --library jersey1 -o my/dir --model-package my.model.svc -i "https://my.api.com/store/api-docs?provider=USER/me&name=MyNewService&version=v1"

Maven swagger-codegen-maven-plugin


When using the Maven plugin, substitute &amp; for the & character if the URL has query parameters, like this:
https://mysite.com?color=red&flavor=sweet

Right: ?color=red&amp;flavor=sweet
<configuration>
  <inputSpec>https://mysite.com/api?provider=USER/me&amp;name=MyGreatService&amp;version=v1</inputSpec>
</configuration>

Wrong: ?color=red&flavor=sweet
<configuration>
  <inputSpec>https://mysite.com/api?provider=USER/me&name=MyGreatService&version=v1</inputSpec>
</configuration>

pom.xml

<build>
  <plugins>
    <plugin>
      <groupId>io.swagger</groupId>
      <artifactId>swagger-codegen-maven-plugin</artifactId>
      <version>2.2.1</version>
      <executions>
        <execution>
          <goals>
            <goal>generate</goal>
          </goals>
          <configuration>
            <inputSpec>https://my.api.com/store/api-docs?provider=USER/me&name=MyGreatService&version=v1</inputSpec>
            <language>java</language>
            <configOptions>
              <dateLibrary>joda</dateLibrary>
            </configOptions>
            <library>jersey1</library>
            <modelPackage>my.model.svc</modelPackage>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Set Cmder (ConEmu) console emulator to open new tab in current directory with Bash shell

Windows is a truly bad operating system for almost everything except games. Unfortunately sometimes we have to use it for web development. I...