Thursday, 24 November 2016

How to convert from kebab-case to camelCase in Clojure

Here are six functions that do that. Pick your favourite. It won't be the best performing one. Can you guess which that is? Scroll down for answer.
(defn kebab->camel1 [^String kebab]
  (->> kebab
       (reduce
        (fn [[buf ucase] c]
          (let [dash (= \- c)]
            [(if dash
               buf
               (conj buf (if ucase
                           (Character/toUpperCase c)
                           c)))
             dash]))
        [[] false])
       first
       (apply str)))

(defn kebab->camel2 [^String kebab]
  (->> (map
        (fn [cur prev] (if (= \- prev)
                         (Character/toUpperCase cur)
                         cur)) kebab (cons nil kebab))
       (filter #(not= \- %))
       (apply str)))

(defn kebab->camel3 [^String kebab]
  (loop [buf []
         ucase false
         rst kebab]
    (if (seq rst)
      (let [c (first rst)
            dash (= \- c)]
        (recur (if dash
                 buf
                 (conj buf (if ucase
                             (Character/toUpperCase c)
                             c)))
               dash
               (rest rst)))
      (apply str buf))))

(defn kebab->camel4 [^String kebab]
  (->> (map
        (fn [[prev cur]] (if (= \- prev)
                           (Character/toUpperCase cur)
                           cur)) (partition 2 1 (cons nil kebab)))

       (filter #(not= \- %))
       (apply str)))

(defn kebab->camel5 [^String kebab]
  (let [pv (volatile! nil)
        sb (StringBuilder. (count kebab))]
    (doseq [c kebab]
      (let [prior @pv
            dash (= \- c)]
        (vreset! pv dash)
        (when-not dash (.append
                        sb
                        (if prior
                          (Character/toUpperCase c) c)))))
    (.toString sb)))

(defn kebab->camel6 [^String kebab]
  (let [buf (.toCharArray kebab)
        len (count buf)]
    (loop [src 0 dst 0 ucase nil]
      (if (< src len)
        (let [c (aget buf src)
              dash (= \- c)]
          (when-not dash (aset buf dst (if ucase (Character/toUpperCase c) c)))
          (recur (inc src) (if dash dst (inc dst)) dash))
        (String. buf 0 dst)))))

To see which is best we do this

(let [kebab (->> (.ints (java.util.Random. 17)  0 31)
                 .iterator
                 iterator-seq
                 dedupe
                 (map #(nth "abcdefghijklmnopqrstuvwxyz-----" %))
                 (take 10000)
                 (apply str))
      time-fn (fn [f]
                (let [start (System/nanoTime)]
                  (f)
                  (/ (double (- (System/nanoTime) start)) 1000000.0)))]
  (for [f [kebab->camel1
           kebab->camel2
           kebab->camel3
           kebab->camel4
           kebab->camel5
           kebab->camel6]]
    [f (time-fn #(dotimes [_ 1000] (f kebab)))]))

and get results like these

([#function[user/kebab->camel1] 9064.630932]
 [#function[user/kebab->camel2] 11520.793361]
 [#function[user/kebab->camel3] 8440.000948]
 [#function[user/kebab->camel4] 20740.882337]
 [#function[user/kebab->camel5] 8455.671506]
 [#function[user/kebab->camel6] 99.724767])

Wednesday, 23 November 2016

How to get Structure and Interpretation of Computer Programs as an Info file on your system

sudo dnf install texi2html texinfo 
git clone https://github.com/webframp/sicp-info.git
cd sicp-info/
makeinfo --no-split sicp.texi -o sicp.info
gzip sicp.info
sudo install-info sicp.info.gz /usr/share/info/dir
sudo mv sicp.info.gz /usr/share/info

Monday, 14 November 2016

My crazy keyboard configuration

I have this in my .Xmodmap file.
  clear mod5
  clear mod4
  clear lock
  clear control
  keycode 49 = ISO_Level3_Shift
  keycode 66 = Menu NoSymbol Menu
  keycode 37 = Super_L NoSymbol Super_L
  keycode 133 = Control_L NoSymbol Control_L
  keycode 108 = Alt_L
  keycode 134 = Control_R NoSymbol Control_R
  add mod5 = ISO_Level3_Shift
  add mod4 = Super_L Hyper_R
  add control = Control_L Control_R
  keycode  10 = 1 exclam 1 exclam grave onesuperior exclamdown
  keycode  11 = 2 quotedbl 2 quotedbl notsign twosuperior trademark
  keycode  12 = 3 sterling 3 sterling brokenbar threesuperior copyright

It turns my Windows keys into Ctrl keys, my left Ctrl key into a Windows key, my Caps Lock key into a menu (▤) key, my AltGr key into a regular Alt key and it turns the key directly below Esc (I call it backtick) into an AltGr. To access the characters that were on that key I type my new AltGr + 1 or 2 or 3.

Why these changes?

  • I need a symmetrical ctrl key arrangement (on both my desktop and laptop).
  • I need a symmetrical alt key arrangement. (I'm an Emacs user.)
  • But I still need an AltGr key
  • I have customized Emacs to make the menu key very useful (following Xah Lee's advice), that's why I've moved it to the easy-to-reach Caps Lock position.

Thursday, 3 November 2016

How to create a Java (/Clojure/Scala) service on Linux

This is a sort of a continuation of an earlier post. In that post I said that you have to create a shell file called test-service or whatever in /etc/init.d/.

You will need Apache Jsvc. Your Java (or whatever JVM language) code will include a class that implements org.apache.commons.daemon.Daemon.

Here is what you should put in that shell file to make you JVM thing into a Linux service called test-service (test.daemon.Daemon is the class you wrote which implements org.apache.commons.daemon.Daemon).

#! /bin/sh                                                                                                                                                                                     
### BEGIN INIT INFO                                                                                                                                                                            
# Provides:     test-service                                                                                                                                                                   
# Required-Start:                                                                                                                                                                              
# Required-Stop:                                                                                                                                                                               
# Default-Start:     S                                                                                                                                                                         
# Default-Stop:                                                                                                                                                                                
# X-Start-Before:                                                                                                                                                                              
# Short-Description:                                                                                                                                                                           
# Description: test-service                                                                                                                                                                    
### END INIT INFO                                                                                                                                                                              
                                                                                                                                                                                               
                                                                                                                                                                                               
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64                                                                                                                                             
SVC_DIR=/home/mikey/test-service                                                                                                                                                               
                                                                                                                                                                                               
                                                                                                                                                                                               
case "$1" in                                                                                                                                                                                   
    start|"")                                                                                                                                                                                  
        /usr/bin/jsvc -wait 20 -cwd $SVC_DIR -pidfile $SVC_DIR/test-service.pid -outfile $SVC_DIR/out.log -errfile $SVC_DIR/err.log -cp $SVC_DIR/target/test-service-0.1-standalone.jar test.daemon.Daemon                                                                                                                                                                                   
        exit $?                                                                                                                                                                                
        ;;                                                                                                                                                                                     
    restart|reload|force-reload)                                                                                                                                                               
        echo "Error: argument '$1' not supported" >&2                                                                                                                                          
        exit 3                                                                                                                                                                                 
        ;;                                                                                                                                                                                     
    stop)                                                                                                                                                                                      
        /usr/bin/jsvc -wait 20 -stop -cwd $SVC_DIR -pidfile $SVC_DIR/test-service.pid -outfile $SVC_DIR/out.log -errfile $SVC_DIR/err.log -cp $SVC_DIR/target/test-service-0.1-standalone.jar test.daemon.Daemon                                                                                                                                                                             
        exit $?                                                                                                                                                                                
        ;;                                                                                                                                                                                     
    status)                                                                                                                                                                                    
        # No-op                                                                                                                                                                                
        ;;                                                                                                                                                                                     
    *)                                                                                                                                                                                         
        echo "Usage: test-service.sh [start|stop]" >&2                                                                                                                                         
        exit 3                                                                                                                                                                                 
        ;;                                                                                                                                                                                     
esac                                                                                                                                                                                           
                                                                                                                                                                                               
:    

Friday, 7 October 2016

Make Caps Lock an additional Menu key

Use the localectl command.

localectl [--no-convert] set-x11-keymap layout [model [variant [options]]]

To make caps lock an additional menu key, the options parameter should be caps:menu

To figure out what the other parameters should be, enter this command:

setxkbmap -print -verbose 10

The command I ended up with was

localectl --no-convert set-x11-keymap gb pc105 mac caps:menu

See Keyboard configuration in Xorg for more details.

Friday, 23 September 2016

How to mount a Windows share on Linux

sudo mount.cifs \\\\windows-host\\share-name /mnt -o user=mikey,pass="bestpasswordever",uid=mikey,gid=mikey

Wednesday, 24 August 2016

Simple-ish Arch setup for VirtualBox

This is a work in progress. There's probably a simple command for making Arch remember that I only ever want to use a UK keyboard, but I've been tinkering with this for too long now.

If you want to use SSH to access the guest from the host, add a Host-Only Ethernet Adapter in your VirtualBox settings.

loadkeys uk
parted /dev/sda
# When in parted
mklabel  msdos
mkpart  primary  ext4  0%  100%
set 1 boot on
quit
# Then
mkfs.ext4 /dev/sda1
mount  /dev/sda1  /mnt
# Edit /etc/pacman.d/mirrorlist to select mirror.
pacstrap /mnt base
genfstab -p /mnt >> /mnt/etc/fstab
arch-chroot /mnt
passwd
ln -s /usr/share/zoneinfo/Europe/Dublin/ /etc/localtime

printf “arch1\n” > /etc/hostname

pacman -S grub

grub-install --target=i386-pc /dev/sda
grub-mkconfig -o /boot/grub/grub.cfg

exit
reboot
# Then enable networking
systemctl enable dhcpcd.service
systemctl start dhcpcd.service

# Install stuff

pacman -S --noconfirm linux-headers xorg xorg-server mate mate-extra lxdm pkgfile base-devel virtualbox-guest-iso wget openssh

# Enable display manager and ssh daemon
systemctl enable lxdm.service
systemctl enable sshd.socket
reboot

# I know there must be a way of reducing the number of reboots
mkdir -p /media/iso
mount -o loop /usr/lib/virtualbox/additions/VBoxGuestAdditions.iso /media/iso
/media/iso/autorun.sh 
# Now add a user and log in as them...
useradd -m -G wheel -s /bin/bash mikey
passwd mikey

# ... so we can install yaourt (not allowed do this as su) ...
mkdir yaourt
cd yaourt
wget https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=package-query
mv PKGBUILD?h=package-query PKGBUILD
makepkg -s
sudo pacman -U package-query-1.8-2-x86_64.pkg.tar.xz 
ls
rm -rf *
ls
wget https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=yaourt
mv PKGBUILD\?h\=yaourt PKGBUILD
ls
makepkg
sudo pacman -U yaourt-1.8.1-1-any.pkg.tar.xz 
cd ..
rm -rf yaourt/
# ... so we can install Google Chrome
echo 1|yaourt --noconfirm google-chrome

Tuesday, 23 August 2016

Install Chrome on CentOS 7

Put this in a .sh file and run it

cat <<EOF >/etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/x86_64
enabled=1
gpgcheck=1
gpgkey=https://dl.google.com/linux/linux_signing_key.pub
EOF
yum install -y google-chrome-stable

Install MATE on CentOS 7

These commands will install MATE and make it launch on boot.

yum -y install epel-release
yum -y groupinstall "X Window system"
yum -y groupinstall "MATE Desktop"
systemctl set-default graphical.target

This command will start it up now

systemctl isolate graphical.target

Simple CentOS 7 VM configuration

This setup allows you to ssh into your VM easily (without port forwarding)

  1. Create a new VirtualBox VM with name vm-name of type Linux, Version Linux 2.6 / 3.xd /4.x (64-bit)
  2. Start the VM, select the install iso, follow dialog boxes to complete installation then shutdown the vm
  3. run these commands on the host
    VBoxManage modifyvm "vm-name" --nictype1 82543GC
    VBoxManage modifyvm "vm-name" --nic2 hostonly
    VBoxManage modifyvm "vm-name" --nictype2 82543GC
    VBoxManage modifyvm "vm-name" --hostonlyadapter2 "VirtualBox Host-Only Ethernet Adapter"
    
  4. run these command on the guest
    sed -ie "s/ONBOOT=no/ONBOOT=yes/" /etc/sysconfig/network-scripts/ifcfg-enp0s3
    sed -ie "s/ONBOOT=no/ONBOOT=yes/" /etc/sysconfig/network-scripts/ifcfg-enp0s8
    systemctl stop NetworkManager.service
    systemctl start NetworkManager.service
    

Monday, 22 August 2016

Install Latest Stable git from source on CentOS

Put these commands in a shell script and run it.
yum install -y wget curl-devel expat-devel gettext-devel \
      openssl-devel zlib-devel gcc perl-ExtUtils perl-devel
cd /usr/local/src
wget https://www.kernel.org/pub/software/scm/git/git-2.9.3.tar.gz
tar xzf git-2.9.3.tar.gz
cd git-2.9.3
./configure
make
make install

Install Latest Stable Emacs from source on CentOS

Put these commands in a shell script and run it.

yum install -y gtk3-devel libXpm-devel gcc giflib-devel libX11-devel libXft-devel \
       libjpeg-turbo-devel libtiff-devel make ncurses-devel -y
cd /usr/local/src
wget http://ftp.gnu.org/pub/gnu/emacs/emacs-24.5.tar.gz
tar xzvf emacs-24.5.tar.gz
cd emacs-24.5
./configure
make && make install

Wednesday, 10 August 2016

How to create a service on Linux

It took me a while to figure this out so I post it here in case I need to refer to it in the future.
These instructions apply to linux distros which have systemd. To find out if this applies to your distro run this command:
ps -q 1 -o comm=
If the output is systemd then your distro is one with systemd, so you can continue with these instructions.
  1. Create a shell file called test-service or whatever in /etc/init.d/. The shell file has to follow a pattern. Have a look at /etc/init.d/mountall-bootclean.sh for a concise example which conforms to this pattern.
  2. Enter this command to have your service start every time the host starts.
    sudo systemctl enable test-service
    
  3. Enter this command to have your service start now.
    sudo systemctl start test-service