EMACS Report Design

I won’t say much about report design since manipulating text in an EMACS buffer is a pretty standard activity for EMACS users, with plenty of web resources available as tutorials. A couple of suggestions – with your results as a list of rows, you can iterate over the rows and print directly into a new buffer prepared with a header. Alternatively you can extract fields from each row using:

1
2
3
4
5
6
(while results-rows   
(setq line (split-string (car results-rows)"\t" nil ))
.
.
.
(setq results-rows (cdr results-rows)))

Now fields can individually be manipulated. Note that tab is being used as the field delimiter. This was specified previously when we started up the database.

Share

EMACS Sqlite Mode

For a good discussion of the details of creating a major mode refer to Writing GNU EMACS Extensions by Bob Glickstein. The advantage of utilizing SQLITE within a major mode is that while you are in the SQLITE specific buffer, you can have SQLITE specific menu items and key chords that are in effect only while in that buffer. A mode also allows you a single point in your code to open and close the database and deal with any database housekeeping that is required. Our effort to abstract away the details of database interaction are also facilitated by a mode, as any database specific functions can be included in the mode. The commands for creating the mode along with helper functions and load statements can go into a file called sqlite-mode.el. My file also includes code for working with the widget library:

1
2
3
4
(require 'widget)
(require 'derived)
(eval-when-compile
(require 'wid-edit))

Define a hook variable and menu map. Add elements to the menu map. Note that each menu item is defined by a dotted pair, the car being the text in the menu and the cdr being an associated function. Often that function will launch a form to be used to enter data. A single example of form design is given below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(defvar sqlite-mode-hook nil
"*List of functions to call when entering sqlite mode*")

(defvar sqlite-menu-map nil
"Menu for sqlite mode.")


(if sqlite-menu-map
nil
(setq sqlite-menu-map (make-sparse-keymap "sqlite"))
(define-key sqlite-menu-map [sqlite-reports]
'("Sqlite reports" . sqlite-reports))
(define-key sqlite-menu-map [add-antibody]
'("Add Antibody" . add-antibody))
(define-key sqlite-menu-map [add-gene]
'("Add Gene" . add-gene))
(define-key sqlite-menu-map [add-abresult]
'("Add Antibody Results" . add-abresult)))

(define-key sqlite-mode-map [menu-bar sqlite]
(cons "sqlite" sqlite-menu-map))

Define keybindings specific for SQLITE mode. I don’t define any unique SQLITE specific bindings because I need to use the widget keymap for my forms to be functional, so I copy-keymap the widget keymap.

1
2
3
4
5
6
7
8
9
10
11
(defvar sqlite-mode-map nil
"Keybindings for sqlite mode")

(if sqlite-mode-map
nil
(setq sqlite-mode-map (copy-keymap widget-keymap)))

(define-derived-mode sqlite-mode text-mode "sqlite"
"Major mode using sqlite for tau antibodies.
Special commands:
\\{sqlite-mode-map}")

Load any libraries that need to be accessed during database manipulation. Here I load various forms and the report interface. provide allows me to require in my .emacs file.

1
2
3
4
5
6
(load "c:/temp/lisp-code/sqlite/add-antibody")
(load "c:/temp/lisp-code/sqlite/add-gene")
(load "c:/temp/lisp-code/sqlite/add-abresult")
(load "c:/temp/lisp-code/sqlite/tau-reports")

(provide 'sqlite)

Also in this file I would include any helper functions, such as sqlite-query and chomp described in an earlier post. Once the mode is defined, the command (sqlite-mode) can be used to invoke the mode, for example in a form buffer.

Share

EMACS and SQLITE as a rapid application development environment

Scientists in their quest for truth often need to catalog and parse large amounts of data. Desktop databases are ideal for this purpose. A reputable package will contain a form and report designer, scripting language, database back end, and a method for interfacing with other software and equipment. Over the years I have experimented with many systems, including the RAD (Rapid Application Development) environment Superbase ( late 1980s early 90s), JAVA and a variety of object oriented databases (POET, ObjectStore and the JDO from Sun; late 90s early 2000s) and more recently Lisp and ObjectPrevalence. Though I quickly gained an appreciation of the LISP language working with Common Lisp, the limited number of libraries, poor documentation, small user base, and lack of a GUI did not meet all my requirements. Clojure promises to address many of these issues, but is still a work in progress. My experience with the JDEE (Java Development Environment for EMACS) familiarized me with EMACS Lisp. The only shortcoming of EMACS is the lack of a database. Enter SQLITE.

SQLITE is a a software library that implements a self-contained, serverless, zero-configuration, transactional SQL relational database engine. Installation and configuration are simple, and an included executable allows SQLITE to run as a process within EMACS. With the widget interface of EMACS, you have all you need to create, query and report data. Setup is as follows:

  1. Install SQLITE
  2. Connect to EMACS
  3. SQLITE mode
  4. Form design
  5. Report design

 


Installing SQLITE

Download and unzip SQLITE into a directory. I used c:\program files\sqlite3. This path will need to be referred to as c:\progra~1\sqlite3 in your lisp code and any batch files. Be sure to also download the associated executable file, which provides about 27 “dot” utility commands. Test that the systems works by creating a table and populating with data. To get started, create a batch file that starts SQLITE with the database name of interest, which is passed to the executable as a parameter. To create the database named “mydb”, the contents of sqlite.bat would be:

1
c:\progra~1\sqlite\sqlite3.exe mydb

At the sqlite prompt both dot and SQL commands can be submitted. To retain a record of the commands used to create your database, place them in a plain text file and then use the .read command to read that file into SQLITE. Here are the contents of my “create-tables.txt” file:

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE ab ( 
ab_id INTEGER PRIMARY KEY AUTOINCREMENT,
names varchar(20),
antigen_species char(20),
host char(20),
supplier varchar(20),
catnum varchar(20),
isotype char(20),
specificity varchar(20),
application varchar(20),
epitope varchar(20));

To execute, read in create-tables.txt at the sqlite prompt:

1
sqlite> .read "create-tables.txt"

You can check that the table was created with the .schema command. Next insert a value. Either type it directly at the sqlite prompt, or read it from a file.

1
INSERT INTO ab VALUES ( NULL,'Tau 46', 'human', 'mouse', 'Santa Cruz', 'sc-32274', 'IgG1', 'hu;mu;rat', 'western;ip;if','unknown');

And query it out:

1
sqlite> SELECT * FROM ab;

If you retrieve your row, you are all set to move on. Note that the assigned value of ab_id is NULL. Let the database assign the autoincrement field.


Connect SQLITE to EMACS

Interaction between SQLITE and EMACS is accomplished through comint. Use describe-function “comint-” to browse the various comint commands. We are interested in comint-redirect-send-command-to-process. Some of the comments in comint.el are also useful to read. Before examining comint directly, let’s consider how to abstract away the process of interacting with the database. Ultimately what I want is a single command that will send my SQL statement to SQLITE and return my result set. I would like the result set returned as a list of tuples (rows). Each tuple can then be processed into a list of fields. This is very convenient as Lisp works well with lists. My command will be sqlite-query, and its only argument will be sql-command. It will return a list of tuples.

First, lets set up a few variables

1
2
3
4
5
6
7
(defvar sqlite-program "c:/progra~1/sqlite/sqlite3.exe" "Full path name of the SQLITE executable.")

(defvar sqlite-db "c:/temp/lisp-code/tutorial/mydb" "Full path name of the SQLITE database.")

(defvar sqlite-process-buffer "*sqlite-process*" "*Name of the SQLITE process buffer. This is where SQL commands are sent.")

(defvar sqlite-output-buffer "*sqlite-output-buffer*" "Name of the buffer to which all SQLITE output is redirected.")

Next start up the SQLITE process. Send the SQLITE dot command “.mode tabs” so that fields are always tab delimitted. This is important later when fields must be extracted. Our database abstraction will return a list of rows, each row being a string with tab delimited fields. This string then needs to be parsed using split-string to extract fields as a list. More on that later.

1
2
3
(apply 'make-comint "sqlite-process"  sqlite-program  nil `(,sqlite-db ))
(comint-redirect-send-command-to-process ".mode tabs" sqlite-output-buffer (get-buffer-process sqlite-process-buffer) nil)
(get-buffer-create sqlite-output-buffer)

Next we need to write our sqlite-query function. The function should perform the following activities:

  1. Navigate to the output buffer.
  2. Erase the contents of the output buffer, if any.
  3. Send the sql-statement to SQLITE using the sqlite-process buffer
  4. Switch back to the sqlite-output buffer and retrieve the results. One result row per line of the buffer. Extract each line as an element of the result list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(defun sqlite-query( sql-command )
(set-buffer sqlite-output-buffer) ;1
(erase-buffer) ;2
(comint-redirect-send-command-to-process sql-command sqlite-output-buffer (get-buffer-process sqlite-process-buffer) nil) ;3
(accept-process-output (get-buffer-process sqlite-process-buffer) 1) ;need to wait to obtain results

(let* ((begin (goto-char (point-min))) ;4
(end (goto-char (point-max)))
(num-lines (count-lines begin end))
(counter 0)
(results-rows ()))
(goto-char (point-min))
(while ( < counter num-lines)
(setq results-rows (cons (chomp (thing-at-point 'line)) results-rows))
(forward-line)
(setq counter (+ 1 counter)))
(car `(,results-rows))))

chomp is a utility that will remove whitespace from the results:

1
2
3
4
5
6
7
8
9
10
11
12
13
(defun chomp (str)
"Trim whitespace from string"
(let ((s (if (symbolp str)(symbol-name str) str)))
(save-excursion
(while (and
(not (null (string-match "^\\( \\|\f\\|\t\\|\n\\)" s)))
(> (length s) (string-match "^\\( \\|\f\\|\t\\|\n\\)" s)))
(setq s (replace-match "" t nil s)))
(while (and
(not (null (string-match "\\( \\|\f\\|\t\\|\n\\)$" s)))
(> (length s) (string-match "\\( \\|\f\\|\t\\|\n\\)$" s)))
(setq s (replace-match "" t nil s))))
s))
Share

Scientist/programmer dichotomy

Bioinformatics and data analysis are mission critical activities at both large pharmaceutical and small biotech companies. Access to bioinformatic resources can vary, depending on project priority and financial resources. Even when forthcoming, bioinformatic resources can be difficult to take advantage of for many reasons. The impedance mismatch between programmer and scientist vocabulary can result in costly misunderstandings during software design. The lengthy requirements gathering, document writing, prototype roll out, evaluation, rewrite cycle adds cost and extends project time lines. The perceived need by programmers to work with the latest and greatest language and programming technology can add unnecessary complexity, expense, and time to a project.

Way back in the 1980s there was a competitive market for desktop database systems such as dBASE, FoxPro, Quattro Pro, FileMaker, and my favorite - Superbase. Self taught programmers using such packages could make short work of many data storage needs in a laboratory environment. Though much maligned by the professional programmers for their sometimes sloppy, undocumented spaghetti code, scientists were focused on getting the job done in the fastest most efficient manner possible. Desktop systems were efficient, incorporating table and form design as well as scripting in a single package. A scientist could focus on mastering the details of his discipline rather than memorizing commands and protocols for different languages and systems.

Microsoft effectively ended innovation in the desktop database market with its Access database monopoly. Though capable, Access is expensive and forces a commitment to a closed Windows based system. Although there are numerous open source desktop databases available, few integrate a form designer, report generator, and scripting language. These elements do exist separately, and a close approximation of a semi-integrated system would be the EMACS/ELISP/SQLITE system I review in this tutorial. Familiarity with such a system would allow the user to perform rapid application development. Efficiency and rapidity are important, as many programs will have a short half life in a rapidly changing research and development environment.

Donald Eastlake describes my software development attitude succinctly as he discusses a piece of software called the ITS system:

The ITS system is not the result of a human wave or crash effort. The system has been incrementally developed almost continuously since its inception. It is indeed true that large systems are never “finished”….

In general, the ITS system can be said to have been designer implemented and user designed. The problem of unrealistic software design is greatly diminished when the designer is the implementor. The implementors’ ease in programming and pride in the result is increased when he, in an essential sense, is the designer. Features are less likely to turn out to be of low utility if users are their designers and they are less likely to be difficult to use if their designers are their users.

Donald EastlakeHackers 1972 page 127

User designed software eliminates the communication barrier between scientist and programmer, and puts control of time lines in the hands of the scientist.

Share

.emacs configuration notes

Below are some configuration notes for your .emacs file.
By default .emacs is found in your “c:/documents and settings/<*your-login-id*>/Application Data” folder.
If you set a HOME system variable, .emacs will be found in the HOME directory.

Below are settings I have used over the years, not necessarily all at the same time. Pick and choose what you need.


Global settings

; For all buffers
(global-font-lock-mode 1) 
(show-paren-mode t);show matching parentheses
(cua-enable-cua-keys t);allows me to use Windows shortcut keys. Must install cua-mode.el
(cua-mode t nil (cua-base))
(tool-bar-mode nil);I don't like tool bars
(transient-mark-mode t);highlight marked regions when selecting code
(global-set-key (kbd "<f12>") 'other-window)
(global-set-key (kbd "<f2>") 'switch-to-buffer)
(global-set-key (kbd "<f1>") 'find-file)

;Define a key to load and run your current project of interest file
(defun load-and-run-fave-file()
  (interactive)
  (load "my-favorite-file.el"))

(global-set-key (kbd "<f6>") 'load-and-run-fave-file)

EMACS Lisp

;;;;    Programming - Elisp

(add-hook 'emacs-lisp-mode-hook
      '(lambda ()
         (interactive)
         (require 'eldoc)
         (turn-on-eldoc-mode)
         (define-key emacs-lisp-mode-map [f5] 'eval-region)
         (define-key emacs-lisp-mode-map [f4] 'eval-buffer)))

Note that below I use F5 in R mode to evaluate a region. Whichever mode I am in, R or Lisp, F5 evaluates a region.


R

;;;; R  Setup
 (require 'ess-site)

(defun my-ess-mode ()
  (interactive)
  (cond ((string= "R" ess-dialect)
     (message "my-r-mode")
     ;; customization for ESS[R] here
     (define-key ess-mode-map '[f5] 'ess-eval-region-and-go))))

;and then hook this into the appropriate place:

(add-hook 'ess-mode-hook 'my-ess-mode)    

SLIME

;; 1. Start the CL first with "M-x clisp-start" (or equivalent) from Emacs 
;; 2. Start the SLIME connection with "M-x slime-connect RET RET RET" from Emacs

;for Common Lisp
;(defun clisp-start ()
;  (interactive)
; (shell-command (concat "c:/clisp-2.43/full/lisp.exe" ;
;			 "-B c:/clisp-2.43/full/ "
;			 "-M c:/clisp-2.43/full/lispinit.mem "
;			 "-i c:/emacs-22.1/site-lisp/.slime.lisp "
;			 "-ansi -q&")))

;(defun sbcl-start ()
;	 (interactive) 
;	(shell-command (concat "c:/sbcl-1.0.13/sbcl.exe" 
                    " --dynamic-space-size 64" 
                    " --noinform"))) 
(defun sbcl-start () 
    (interactive) 
    (shell-command "c:/sbcl-1.0.13/sbcl.exe --core c:/sbcl-1.0.13/sbcl.core --load c:/emacs-22.1/site-lisp/.slime.lisp &")) 

(setq load-path (append (list "c:/emacs-22.1/site/slime-2.0")
                        load-path))

(require 'slime)
(add-hook 'lisp-mode-hook (lambda () (slime-mode t)))
(add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t)))
;; If you don't want eldoc-like behavior, comment out the following line
(slime-autodoc-mode)

;M-x run-lisp;  M-x slime

(setq inferior-lisp-program "c:/sbcl-1.0.13/sbcl.exe --core c:/sbcl-1.0.13/sbcl.core --userinit c:/sbcl-1.0.13/sbcl-init2.lisp")
(require 'slime)
(slime-setup) 

Clojure

(setq load-path (append (list "c:/emacs-22.3/site-lisp/slime-2009-06-28")
                        load-path))
(require 'slime)
(slime-setup) 

(setq inferior-lisp-program
                                        ; Path to java implementation
      (let* ((java-path "java")
                                        ; Extra command-line options
                                        ; to java.
             (java-options "")
                                        ; Base directory to Clojure.
                                        ; Change this accordingly.
             (clojure-path "c:/myclasses/classes/clojure/")
                                        ; The character between
                                        ; elements of your classpath.
             (class-path-delimiter ";")
             (class-path (mapconcat (lambda (s) s)
                                        ; Add other paths to this list
                                        ; if you want to have other
                                        ; things in your classpath.
                                    (list (concat clojure-path "clojure.jar"))
                                    class-path-delimiter)))
        (concat java-path
                " " java-options
                " -cp " class-path
                " clojure.lang.Repl")))

(require 'clojure-mode)

(setq auto-mode-alist
      (cons '("\\.clj$" . clojure-mode)
            auto-mode-alist))

JDEE

(setq defer-loading-jde t) 
;; 

(if defer-loading-jde 
    (progn 
      (autoload 'jde-mode "jde" "JDE mode." t) 
      (setq auto-mode-alist 
        (append 
         '(("\\.java\\'" . jde-mode)) 
         auto-mode-alist))) 
  (require 'jde)
  (load "jde-ant")) 

;; Sets the basic indentation for Java source files 
;; to two spaces. 

(defun my-jde-mode-hook () 
    (setq c-basic-offset 2)
        ( define-key jde-mode-map '[f5] 'jde-build) ) 

(add-hook 'jde-mode-hook 'my-jde-mode-hook) 

(cond ((fboundp 'global-font-lock-mode)
       ;;Turn on font-lock in all modes that support it
      (global-font-lock-mode t)
       ;;Maximum colors
      (setq font-lock-maximum-decoration t)))

(jde-ant-args "-emacs")
(jde-ant-buildfile "c:\\classes\\prs500mngr\\bin\\build.xml")
(jde-ant-complete-target t)
(jde-ant-enable-find nil)
(jde-ant-home "c:\\classes\\org\\apache-ant-1.7.1")
(jde-ant-program "c:\\classes\\prs500mngr\\bin\\ant")
(jde-ant-read-buildfile t)
(jde-ant-read-target nil)
(jde-ant-working-directory "c:\\classes\\prs500mngr\\bin\\")
(setenv "ANT_HOME" "c:\\classes\\org\\apache-ant-1.7.1")

ORG mode

(add-to-list 'auto-mode-alist '("\\.org\\'" . org-mode))
     (global-set-key "\C-cl" 'org-store-link)
     (global-set-key "\C-ca" 'org-agenda)

(require 'org)

(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))

(define-key mode-specific-map [?a] 'org-agenda)

(eval-after-load "org"
  '(progn
     (define-prefix-command 'org-todo-state-map)

     (define-key org-mode-map "\C-cx" 'org-todo-state-map)

     (define-key org-todo-state-map "x"
       #'(lambda nil (interactive) (org-todo "CANCELLED")))
     (define-key org-todo-state-map "d"
       #'(lambda nil (interactive) (org-todo "DONE")))
     (define-key org-todo-state-map "f"
       #'(lambda nil (interactive) (org-todo "DEFERRED")))
     (define-key org-todo-state-map "l"
       #'(lambda nil (interactive) (org-todo "DELEGATED")))
     (define-key org-todo-state-map "s"
       #'(lambda nil (interactive) (org-todo "STARTED")))
     (define-key org-todo-state-map "w"
       #'(lambda nil (interactive) (org-todo "WAITING")))

     (define-key org-agenda-mode-map "\C-n" 'next-line)
     (define-key org-agenda-keymap "\C-n" 'next-line)
     (define-key org-agenda-mode-map "\C-p" 'previous-line)
     (define-key org-agenda-keymap "\C-p" 'previous-line)))

(require 'remember)

(add-hook 'remember-mode-hook 'org-remember-apply-template)

(define-key global-map [(control meta ?r)] 'remember)
'(org-agenda-custom-commands (quote (("d" todo #("DELEGATED" 0 9 (face org-warning)) nil) ("c" todo #("DONE|DEFERRED|CANCELLED" 0 23 (face org-warning)) nil) ("w" todo #("WAITING" 0 7 (face org-warning)) nil) ("W" agenda "" ((org-agenda-ndays 21))) ("A" agenda "" ((org-agenda-skip-function (lambda nil (org-agenda-skip-entry-if (quote notregexp) "\\=.*\\[#A\\]"))) (org-agenda-ndays 1) (org-agenda-overriding-header "Today's Priority #A tasks: "))) ("u" alltodo "" ((org-agenda-skip-function (lambda nil (org-agenda-skip-entry-if (quote scheduled) (quote deadline) (quote regexp) "<[^>
]+>"))) (org-agenda-overriding-header "Unscheduled TODO entries: "))))))
(org-agenda-files (quote ("~/todo.org" "b:/private/2008/recur.org")))
(org-agenda-ndays 7)
(org-agenda-show-all-dates t)
(org-agenda-skip-deadline-if-done t)
(org-agenda-skip-scheduled-if-done t)
(org-agenda-start-on-weekday nil)
(org-deadline-warning-days 14)
(org-default-notes-file "~/notes.org")
(org-fast-tag-selection-single-key (quote expert))
(org-remember-store-without-prompt t)
(org-remember-templates (quote ((116 "* TODO %?
  %u" "~/todo.org" "Tasks") (110 "* %u %?" "~/notes.org" "Notes"))))
(org-reverse-note-order t)
(remember-annotation-functions (quote (org-remember-annotation)))
(remember-handler-functions (quote (org-remember-handler)))

Share

EMACS setup notes

Installation instructions for the various programs I use with EMACS


WindowsXP

R

Download and install R from Cran. I am using version 2.11.1. Sequence manipulation algorithms require the seqinr package v2.0-9 to be installed in R. Launch the gui and select Packages/Install Packages… Select a Cran mirror, then select the package “seqinr”. Packages can also be installed from the command line, once you have R running in EMACS. Use the comand:

1
install.packages("seqinr")

EMACS

Install EMACS. I am using version 23.2

Set up some speed keys:

1
2
3
4
5
6
7
8

(defun load-and-run-fave-file()
(interactive)
(find-file "~/owncloud/markov-elear/src/markov_elear/generator.clj"))


(global-set-key (kbd "<f6>") 'load-and-run-fave-file)
(global-set-key (kbd "<f10>") 'primer-db-main)

ESS

Install ESS. I am using version 5.8. Unzip the files as a subdirectory to c:/emacs-23.2/site-lisp. You must include in your .emacs file:

1
(require 'ess-site)

Start EMACS. If ESS and R have been properly installed and configured, you should see:

“Finding all versions of R on your system…”

in the minibuffer during startup. Launch R with the command “M-x R”. You should be able to enter R commands at the > prompt and see the output.

To make working with R more convenient, I include the following in my .emacs file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
;;__________________________________________________________________________
;;;; R Setup
(require 'ess-site)

(defun my-ess-mode ()
(interactive)
(cond ((string= "R" ess-dialect)
(message "my-r-mode")
;; customization for ESS[R] here
(define-key ess-mode-map '[f5] 'ess-eval-region-and-go))))

;and then hook this into the appropriate place:

(add-hook 'ess-mode-hook 'my-ess-mode)

;;__________________________________________________________________________
;;;; Programming - Elisp

(add-hook 'emacs-lisp-mode-hook
'(lambda ()
(interactive)
(require 'eldoc)
(turn-on-eldoc-mode)
(define-key emacs-lisp-mode-map [f5] 'eval-region)
(define-key emacs-lisp-mode-map [f4] 'eval-buffer)))

This allows me to use F5 to evaluate a region whether I am in R or Lisp. I also define the following function key shortcuts to streamline the loading of different files of interest. If you decide not to define these keys, you will need to load the files manually using the command “M-x my-favorite-file”.

1
2
3
4
5
6
7
(global-set-key (kbd "&lt;F6>") 'load-and-run-fave-file)
(global-set-key (kbd "&lt;F10>") 'exe-my-fave-method)

(defun load-and-run-fave-file()
(interactive)
(load "my-favorite-file.el"))

If ess is not finding R, check your PATH variable and make sure the R executable is listed.

Clustalw2

Install clustalw2 which performs the sequence alignments. Download the clustalw-2.0.11-win.msi file and allow it to install in c:\Program Files.

Package.el

Try to use Melpa stable only. At least for Clojure compatibility, MELPA unstable introduces bugs.

update MELPA packages (note capital U)

1
M-x package-list-packages U x  
1
M-x package-refresh-contents

Init.el

I switched from ~/.emacs to ~/.emacs.d/init.el
Furthermore I want all of .emacs.d to be in my ~/syncd directory for easy cloud backup.
I need to change the properties of the launch icon to redirect to ~/syncd/.emacs.d/init.el and set the user-emacs-directory variable early in init.el

Properties of the launch icon can only be modified by root so sudo edit /usr/share/applications/GNU Emacs 25 (GUI)

#nautilus
navigate to /usr/share/applications/GNU Emacs 25 (GUI) and chage properties to: /usr/bin/emacs25 %F -q –load “/home/mbc/syncd/.emacs.d/init.el”

%F allows multiple files as arguments.

The first line in init.el is (setq user-emacs-directory “/home/mbc/syncd/.emacs.d/“)

11/01/2019

Working with emacs26

#nautilus
navigate to /usr/share/applications/emacs.desktop and change the line to:
Exec=/usr/bin/emacs %F -q -load /home/mbc/syncd/.emacs.d/init.el

Useful Packages

eldoc: provides method documentation

company: auto completes

ido: provides selection lists e.g. for navigating directories

Share

Principles of Population Genetics

Principles of Population Genetics, first edition, was the text for Genetics 705 / Plant Science 705 graduate course at State U. I took this course back in 1983 to satisfy requirements for the Master of Science degree in Genetics. Being an early version of the book, there are few of the molecular biology and genomics distractions present in the more recent versions.



I work out many of the problem sets using R.


Course syllabus:


Recommended texts:



Share

Guile

Installation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>pacman -S guile  ;;installs Guile 2.0.9
>wget https://aur.archlinux.org/packages/gu/guile-ncurses/guile-ncurses.tar.gz
>mv ./guile-ncurses.tar.gz ~/builds
>cd builds
>tar -xzvf ./guile-ncurses.tar.gz
>cd guile-ncurses
>makepkg
>pacman -U guile-ncurses-1.4-1-any.pkg.tar.xz
>pkg-config guile-2.0 --variable=extensiondir
/usr/lib/guile/2.0/extensions
>mv /usr/local/lib/* /usr/lib/guile/2.0/extensions ;;move libraries to expected location
>cat ~/.bash_profile
#
# ~/.bash_profile
#

[[ -f ~/.bashrc ]] && . ~/.bashrc

export GUILE_LOAD_PATH=${GUILE_LOAD_PATH}:/usr/share/guile-ncurses:/usr/share/guile/site/2.0/ncurses


sudo apt-get install guile-2.0-dev libunistring0 libunistring-dev

Configuration

pkg-config guile-2.0 –variable=extensiondir

Guile-ncurses

download into ./Downloads

1
2
3
4
5
6
7
cd Downloads
tar -xzvf ./guile-ncurses.tar.gz
cd guile-ncurses
./configure --with-guilesitedir=/usr/share/guile/site/2.0

make
make install

init.el

install geiser

;__________________________________________________________________________
;;;; Guile/Lisp Setup
;;(load-file “~/.emacs.d/elpa/geiser-20170325.1956/geiser.el”)

Share

ftpbox

Owncloud will not back up certain files, such as those beginning with underscores. Ftpbox is a hack that allows me to back up all files manually, using batch files. A better option is rsync. Osync for bidirectional sync.

Installation

1
2
#apt-get update
#apt-get install lftp

Batch files

ftpbox-download.sh
1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
HOST='mysite.net'
USER='ftpbox@mysite.net'
TARGETFOLDER='/home/mbc/ftpbox'
SOURCEFOLDER='/'

lftp -f "
open $USER@$HOST
lcd $SOURCEFOLDER
mirror --verbose --delete --only-newer $SOURCEFOLDER $TARGETFOLDER bye"

ftpbox-upload.sh
1
2
3
4
5
6
7
8
9
10
11
12

#!/bin/bash
HOST='mysite.net'
USER='ftpbox@mysite.net'
TARGETFOLDER='/'
SOURCEFOLDER='/home/mbc/ftpbox'

lftp -f "
open $USER@$HOST
lcd $SOURCEFOLDER
mirror --reverse --delete --verbose --only-newer $SOURCEFOLDER $TARGETFOLDER bye"

put in ~/.profiles for execution on login

for execution at shutdown:

sudo cp ./ftpbox-upload.sh /etc/init.d/
sudo update-rc.d ftpbox-upload.sh start 03 0 6

0 is for shutdown
6 is for reboot
03 puts it in the middle of the scripts run
update-rc.d creates a symlink

Run on login, logout, cron

~/.bash_profile or ~/.bash_login do not exist on Ubuntu

Use ~/.profile for login scripts and append:

~/ftpbox-download.sh

Use ~/.bash_logout for logout scripts

~/ftpbox-upload.sh

crontab -e to edit crontab
add 1 line per command

*/10 * * * * /home/dad/ftpbox-upload.sh

chmod 600 ~/.netrc ;read and write by user only

**~/.netrc **
machine www..net login ftpbox@mysite.net password

Share

Owncloud

Software installation

echo ‘deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_7.0/ /‘ >> /etc/apt/sources.list.d/owncloud-client.list

apt-get update
apt-get install owncloud-client

Local folder: /home/mbc/owncloud
must modify network folder to use ~/owncloud/documents
When asked for network folder type “/“

server: https://www.mysite.net/owncloud

Server configuration

Database: mbc_owncloud
user: mbc_owncloud
password: mypassword

owncloud server user: mbc
password: mypassword

database host:localhost

create an admin user: mbc

I am only using the MySQL method
copy setup-owncloud.php to /public_html then go to

www.mysite.net/setup-owncloud.php

To use WebDav with Zotero

www.mysite.net/owncloud/remote.php/webdav ( /zotero is automatically appended)
you will be prompted to create directory

Client configuration

Zotero

do not export, backup the database directory to retain metadata

~/.zotero/zotero/3xdb…./zotero…
the “pipes” subdir will not copy, be sure to compensate

www.mysite.net/owncloud/remote.php/webdav

Share