User:Andrew Nikitin/Literate

From J Wiki
Jump to navigation Jump to search

Open source software

Open source software is good.

The code originally posted here has been revised to reflect the most current version of the J GUI tools. This newer version is less literate than the example here but it works in contemporary J.

Literate programming

Literate programming is especially good for open source software.

Literate comments are not a substitution for user manual. Literate comments explain choices made by the programmer, rather than explain how to use the program.

Example: program that generates random passwords

In the following text comments not related to program itself, but rather to illustrate certain feature of literate are typeset with italic.

Motivation for the program

There are just too many web sites that require registration and password. One way is to use same password for all of them. This has obvious security problem -- once somebody knows one of your passwords, he knows all of your passwords. Even if you do not care about your online identity, it still seems like a bad habit. Better way is to treat them all equally and give them all different password.

This simple program does just that.

It consists of a single script file as described below. File:Passw.ijs


Licence and disclaimer

It is a good idea to start open source program with license and disclaimer. License tells user what he can do with the software (best if it is "everything") and under what conditions (best if under any conditions).

Disclaimer should disclose potential dangers of the software to disclaim author's liability so user is notified that he uses it at his own risk. For example, if program may delete files or create files in unobvious places or start some other programs, this is good place to mention it.

Good place for license and disclaimer is in the beginning of the file where user will immediately see it. But they do not help to understand the program, so there is no need to place them first in the technical documentation. [{{#file: "main"}} Download script: main ]

«License and disclaimer»


Another things that belong to the first few lines of open source software is configuration and tweaks.

More elaborate programs would probably need some kind of configuration file, for a simple program like this it is sufficient to place configuration in the beginning of executable script. [{{#file: "main"}} Download script: main ]


Configuration nouns are all bundled together in the beginning of the file, but code with their actual definitions is located in this document close to the pieces of code that use them.


This is GUI program and it uses form to communicate with user. The form looks like this:


and is defined as [{{#file: "main"}} Download script: main ]

GPSW=: 0 : 0
pc gpsw;pn "Generate password";
xywh 3 3 124 11;cc pwd edit ws_border es_autohscroll;
xywh 3 15 64 9;cc al checkbox;cn "allow &lowercase";
xywh 3 25 64 9;cc au checkbox;cn "allow &uppercase";
xywh 3 35 64 9;cc ad checkbox;cn "allow &digits (0-9)";
xywh 3 45 64 9;cc ah checkbox;cn "allow &hex digits (a-h)";
xywh 3 55 64 9;cc es checkbox;cn "exclude &similar";
xywh 72 15 43 9;cc static static ss_center;cn "Password l&ength";
xywh 115 15 12 9;cc len static ss_center;cn "8";
xywh 72 25 52 9;cc size scrollbar;
xywh 72 35 52 9;cc strength static;cn "";
xywh 72 45 52 14;cc runvim button;cn "Open password list";
xywh 24 65 40 14;cc gp button bs_defpushbutton;cn "&Generate";
xywh 69 65 40 14;cc save button;cn "&Save";
pas 3 3;pcenter;
rem form end;
gpsw_cancel_button=:wd bind 'pclose;'

Form Initializtion

Render form [{{#file: "main"}} Download script: main ]

gpsw_run=: 3 : 0
wd 'pshow;'

Initialize random seed. This is not the best way to initialize random seed because it is not very random, but is good for example purpose. [{{#file: "main"}} Download script: main ]

9!:1 [ 60 60 24 #. |. _3 {. <. (6!:0 '')

Define and set initial (default) values for controls. [{{#file: "config"}} Download script: config ]

NB. Inital alphabet and password size
INIT=:'al 1';'au 1';'ad 1';'ah 0';'es 0';'len 12';'size 12'

[{{#file: "main"}} Download script: main ]

([: wd 'set ' , ])&> INIT

Finally, assign values to globals and generate password. Normally window driver assigns values to control names, but since we are calling event handler directly, the burden of assigning is on us. [{{#file: "main"}} Download script: main ]

4 : '(x)=:y'/|:;:&> INIT
gpsw_gp_button ''

exclude similar

SIMILAR noun lists characters that look similar and can be easily confused with each other. Definition of "look similar" depends on one's handwriting and is therefore user configurable. If exclude similar is checked, then password will not contain any of those characters, so there cannot be mistake in transcription.

Note, how SIMILAR is explained here, where it belongs, but inserted in the code in the beginning of the file, so it can be tweaked by the user. [{{#file: "config"}} Download script: config ]


[{{#file: "main"}} Download script: main ]

rsel=: ;@:(({~ ?@#)&.>)@(-.&a:)
flt=: ;@[ -. ;@[ -. ]
rrsame =: 3 : 0
(y -. ;x) , rsel x

Generate password

[{{#file: "config"}} Download script: config ]

ALPH_LOW=:a.{~ (a.i.'a')+i.26
ALPH_UP=:a.{~ (a.i.'A')+i.26
ALPH_DIG=:a.{~ (a.i.'0')+i.10
ALPH_HEX=:a.{~ (a.i.'a')+i.6

Generate button generates new password. [{{#file: "main"}} Download script: main ]

gpsw_gp_button=: 3 : 0

To do this it selects set of characters that are allowed in the password and weeds out similar characters if requested. [{{#file: "main"}} Download script: main ]

alph=.;("."0 al,au,ad,ah)#(ALPH_LOW;ALPH_UP;ALPH_DIG;ALPH_HEX)
NB. alph=.rrsame^:(es-:,'1') alph
NB. alph=.alph -.~^:(es-:,'1')~ ;SIMILAR
alph=.alph -.~^:(es-:,'1')~ ; (#~ (1 < +/@e.&alph)&>) SIMILAR

Entropy is calculated as It can be used to estimate password "strength" in bits. Here "strength" is the negative logarithm of the probability to guess the password first time. [{{#file: "main"}} Download script: main ]

wd 'set strength *entropy ',(":<.(".size)*2^.#alph),' bits'

Please note that formula is included in its natural form. This removes limitation of including formulas and diagrams into in-source comment only in the form of ascii art.

Finally, generate random string of given length in given alphabet, show it in editbox and place it on clipboard. In certain cases using built in random number generator may be unacceptable. [{{#file: "main"}} Download script: main ]

p=.alph {~ ? (". size)##alph
wd 'set pwd *',p
wdclipwrite p

Any click on any of the checkboxes that changes allowed character set generates new password. [{{#file: "main"}} Download script: main ]

gpsw_au_button=: gpsw_gp_button
gpsw_al_button=: gpsw_gp_button
gpsw_ah_button=: gpsw_gp_button
gpsw_ad_button=: gpsw_gp_button
gpsw_es_button=: gpsw_gp_button

Change size

Length or number of characters in the password. Limits set for scrollbar size implicitly define limits on allowed password sizes. Length id displayed in static len. [{{#file: "main"}} Download script: main ]

gpsw_size_button=: 3 : 0
  wd 'set len *',size
  gpsw_gp_button ''


Originally I wanted to keep track of generated passwords by means of this same program, hence this button. I ended up with alternative approach (see below), but button stayed. It can be removed if needed. [{{#file: "main"}} Download script: main ]

gpsw_save_button=: 3 : 0
 wdinfo 'Save password to password list';'Not implemented yet'

Password file

Open password file button starts predefined external program that decrypts and opens a text file or database or anything else where user keeps his passwords together with site names, account names and other related information.

This keeps all this information together and instead of remembering many passwords user needs only to remember single password for his master password file. [{{#file: "main"}} Download script: main ]

gpsw_runvim_button=: 3 : 0
wd 'winexec "',OPENFILECMD,'"'

Please, change next line, do not keep your password.txt in root directory, keep it in secure storage if your system supports it. If not, use one of the numerous password managers. [{{#file: "config"}} Download script: config ]

NB. please, CHANGE NEXT LINE, but no double quotes (")
OPENFILECMD=:'notepad c:\password.txt'

Including in-source comments is generally not needed since literate comments serve same purpose better. However, parts of the program intended to be modified by the user can bear comments. Another example where in-source comments are useful is NB.*verb v description in library scripts for easy scriptdoc/Ctrl+F1 access [{{#file: "Disclaimer"}} Download script: Disclaimer ]

NB. May start external program (originally, notepad).

Notes on potentially dangerous actions can be created where these actions are defined and then assembled into single disclaimer block for their better visibility

Run, form, run

[{{#file: "main"}} Download script: main ]

gpsw_run ''

Loose ends

[{{#file: "License and disclaimer"}} Download script: License and disclaimer ]

NB. (C) 1997 Andrew Nikitin
NB. This is free software. You may use, copy, modify and distribute it at your
NB. own risk.
NB. May contain toxic waste. Do not eat.

Contributed by Andrew Nikitin