Friday 3 November 2017

How to generate a not totally crap password in Javascript

I keep writing versions of this in various languages and then losing them. I'm posting it here so I'll have a version I can run in my browser whenever I need a new password for something. The password generated will often be harder to guess than one I would just make up, but that's the only guarantee I'm giving.
function password(n){
    if (n < 3) n = 3;
    let randomIndex=0;
    const randomArray = new Uint32Array((n << 1) - 1);
    window.crypto.getRandomValues(randomArray);
    const random = n => randomArray[randomIndex++] % n;
    const randOf = s => s.charAt(random(s.length));
    const shuffle = (s) => {
        let c = [...s];
        let n = c.length;
        for(let i = n - 1; i > 0; i--){
            let j = random(i + 1);
            let tmp = c[i];
            c[i]  = c[j];
            c[j]  = tmp;
        }
        return c;
    };
    
    let a=[];
    for(let i=0;i<n-3;i++){
        a.push(randOf("abcdefghijklmnopqrstuvwxyz"));
    }
    a.push(randOf("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
    a.push(randOf("01234567890"));
    a.push(randOf("!\"£$%^&*()-_+=[]{}:;@'~#<>,./?"));
    return shuffle(a).join("");
}

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