Table of Contents


Raspberry Pi

Debugging Tips

Common Programs

Git and GitHub


A repository, often called a repo, is a directory of files. Every directry under source conntrol is a complete independant repository, and can function even without network access.

The basic structures are:

When sharing work with other users, there is no special "central" repository. All repositories are equal in the eyes of git. Instead of checking an updated file into a source control central server, with Git you push or pull commits from one repository to another. In practice, one repository may be treated specially, like a central master, but that is outside of git. Different organizations may use different policies for identifying or protecting different special repositories.

GitHub is a web-based server where people can exchange and share a source tree. You can push your local repository to the server, and can pull repositories from the server to your local repository. It also lets people chat and read each other's source code. You do not need GitHub to use Git, but you do use git to interact with GitHub. Git does everything on the local computer, and GitHub is a web service that allows sharing between different git users. Git can also work with other similar services.

Login to GitHub at and create a Free account.
WARNING! Use the same email you used for the local repository!

The git cheat sheet (in English)

Some handy tutorials


Creating repositories

Each directory of source code requires a separate repository.

Modifying and Committing Files

The states of a file are: Tracked ---> Modified ---> Staged ---> Committed/Tracked
A key idea in git is that changes are not stored as diffs, but rather as stand-alone snapshots.

If you are only working on a local storage (no GitHub or BitBucket or other remote store) then you are done. Your changes are saved. If you delete the working copy of the file, then do a "git reset --hard HEAD" the file will be restored.

If you want to use GitHub, then you ALSO need to do the next steps.

Next make a branch. In git, a branch is a reference to a commit. This becomes important when you have several commits in a directory, each with different set of snapshots of files. You use branch names to reference each commit. In practice, this means you specify a branch name to the command that changes the current working environment to reference a particlar commit.

Now, push a branch to Github git push origin my-new-branch Here, "origin" is just a special keyword that means the remote URL associated with this repository Or, you can try this, but I have to enter SSH public key passcodes which takes extra configuration. git push yourbranchname

Now you can log into GitHub and create a pull request, examine the diff, and merge it into the main branch.

Getting Updates

In a directory that is a clone of a repository on GitHub git pull origin master

To dischard all local changes and replace the directory with the remote repository git reset --hard HEAD git pull

To restore the state of a file from your local repository git checkout However, if you deleted a file, then you will have to name it to restore it from the local repository. git checkout myFileName

Status Commands

To see what has changed but not been committed in the working directory git status

To see which branch you are currently working on git branch

To see what remote repository git remote -v

To see what has been changed and committed in the past: git log

To see what changes are changed but not yet staged. Shows the differences between the working directory and the index. Note, if all changes are staged but not yet committed then "git diff" will show nothing. git diff git diff [fileName] git diff [tag name]

The changes are in the current staged commit. These files have been added to the index and staged for a commit. These are the changes between the index and the HEAD (which is the last commit on this branch). git diff --staged

Shows the changes between the index and the HEAD (which is the last commit on this branch). git diff --cached

Shows all the changes between the working directory and HEAD (which includes changes in the index). This shows all the changes since the last commit, whether or not they have been staged for commit or not. git diff HEAD

Delete/Undo Changes


GDB in Emacs

A good tutorial is
  • Control-x 2 - Split the screen
  • Esc-X gdb - Start gdb
  • Esc-X gud-gdb - Start GUD gdb
  • {program name} - type this at the "Run gdb" prompt in the mini-buffer
  • Optionally, type "set args xxxx" to the prompt, which will set the command line arguments to xxxx.

GDB Commands

See the manual for more information.
  • file - Load a new program
  • r - Run the current program
  • k - Kill the current debugged process
  • s - Step Into
  • n - Step Over
  • c - Continue
  • jump lineNum - Jump to lineNum in the current file
  • fin - Run until the current function finishes
  • bt - Print the call stack
  • f n - Set the current stack frame to frame #n
  • p {var name} - Print the value of the named variable
  • b {proc name or lineNum} - Set a breakpoint at the entry to the named procedure. If this is a lineNum then it assumes the current file being debugged.
  • d {num} - Delete breakpoint number
  • info break - List breakpoints

gprof (GNU Profiler)

Using gprof

  • Compile with -pg flag
  • run the program as you normally would. This creates a gmon.out file
  • gprof {programName} gmon.out > prof.txt

Microsoft Excel

Making a Cell whose value is defined by an expression

Select the cell, and type the expression in the fx (function) text box. Start the string with "=" to tell Excel that this is a formula and not a string value.

=(L2 / (K2 + L2)) * 100

The parameters refer to cells. These take the form of where is a letter and is a number. A "$" symbol in front of either the column or letter means it is absolute address, which is independent of the location of the cell making the reference. No "$" means that this address is relative to the cell making the reference. This can have several combinations:

Type Description Example
Absolute A specific cell independent of location of the referencing cell $A$1
Absolute Column, Relative Row A cell in a specific column, and in a row relative to the referencing cell $A1
Absolute Row, Relative Column A cell in a specific row, and in a column relative to the referencing cell A$1
Relative A cell in a relative row and column to the referencing cell A1

Once you have a cell with a formula, you can select it and drag the outline to fill a column or row. This will put that expression in every cell in the region. Assuming that hte formula uses relative cell references, this means every cell will have a value dependent on relative cells in its own row or column.

NOTE: The first cell uses relative addresses with specific constant names, like "A3" and so on. When you copy this to other cells, Excel will first convert the specific names (like "A3") to relative positions (like, one column to the left and two rows up) and then put the appropriate relative positions in each new cell. So, you define the pattern with a specific example and then Excel generalizes this and makes new specific constants for each new cell.

Besides algebraic expressions, there are a few built-in functions that are handy.

  • SUM(A1:A3)
  • AVERAGE(A1:A3)
  • MAX(A1:A3)
  • MIN(A1:A3)

Creating a series of auto-fill data in rows or columns
  1. Click a cell, which should show a dark frame around the cell, with a box in the lower right corner. Select the box, and drag it to expand the region to a row or column or block of cells.
  2. Select the "Home" tab, then click the "Fill" combo box, then select the "Series..." item. This lets you control how data is filled in the selected region.

Counting the Number of rows that Meet a Condition

=CountIf(range, criteria)

  • Range is a range of cells, like "A2:A7"
  • Criteria is a quoted algebraic relation, like ">=2001"

Some examples

  • =CountIf(A2:A7, ">=2001")

Some extensions

  • Combine several COUNTIF expressions in a SUM expression

A few personal things for installing and configuring Linux

This is just my personal To-Do list for installine a new Fedora machine. This will probably not be useful to anyone else. This is also Fedora-specific, which uses yum. Debian and Ubuntu systems will use an alternate system, apt-get. Yum
yum is a wrapper for the RedHat package manager (rpm) which works on Fedora or Red Hat systems. It runs as root. Here are the common yum commands:

  • yum update
  • yum list <package name>
  • yum list updates
  • yum list recent
  • yum list installed
  • yum search <name> - looks for a string in package names and descriptions
  • yum info <package name>
  • yum install <package name>
  • yum remove <package name>

  • After installing from the DVD, I add additional accounts (fsuser, root2, etc).

  • Use the Software Package tool to get the latest system updates

  • Use the Software Package tool to install "Gnome Tweak"

  • Go through Tweak and Settings tools

  • Use the Software Package tool to install Emacs

  • Copy working directories and files
    • Copy ddRoot and dLargeData directories from a recent backup

    • Copy .emacs and .bashrc from ddRoot/tools to the home directory

  • Bash tweaks
    • sudo dnf install bash-completion

  • Configure Firefox

  • Install and Configure Chrome

  • Install gcc and friends
    yum install gcc
    yum install gcc-c++
    yum install glibc-static
    yum install libstdc++-static

  • Install Extra Fedora Packages

    These contain extra packages that are not in default Fedora’s repositories, including proprietary and partially open source libs in the non-free. These are used by VLC and NVIDIA.

    • dnf install$(rpm -E %fedora).noarch.rpm

    • dnf install$(rpm -E %fedora).noarch.rpm

  • Install VLC
    See This requires Fedora 22 and later.
    This uses rpmfusion, and installs from rpmfusion-free-release-stable.noarch.rpm

  • Installing PrivateInternetAccess VPN

    I use privateinternetaccess, so this is specific to their software. Different VPN's will have different installation steps. Moreover, PrivateInternetAccess has changed their installer, from dnf-based to an app you download from their web site.

    • Open a browser and go to
    • Download the app. This creates a file
    • chmod ugo+rwx ./
    • Launch the PIA application
    • Select options, and check to turn on PIA on system startup

  • Install Password Manager

    Once I started using a password manager I wondered how I lived without one. But, I prefer to keep a local file that is password protected rather than a cloud-based service. A local file has a big inconvenience that I can't use it from a laptop while working or travelling. But, really, I don't want to be accessing financial or similar web sites from a coffee shop wifi. Keeping a local file means you first have to break into my house and then break into my computer and then break the file encryption to get my passwords. Sure, that's possible, but it adds another level of security which I prefer. I just fear that web-based password managers are too tempting a target and may some day be broken, particularly by a state agency.

    There are lot of password managers, and I used to use PasswordSafe because of its association with Bruce Schneier. However, that is not supported in the latest Fedora, so I changed to KeePass and am happy with it as well.

    I installed KeePass XC" through Fedora Software manager. There is also

  • Install NVIDIA drivers and CUDA

    I use the rpmfusion method. rpmfusion is already required for VLan and I also do not want to customize my NVIDIA driver install - I just want something that works.

    • Install rpmfusion packages as described above

    • Disable secure boot, by booting with F2 and turning off the option

    • sudo -i

    • Find out what card you have installed:
      /sbin/lspci | grep -e VGA
      For example, I have an RTX A2000 Mobile (rev a1)

    • dnf update -y

    • dnf install akmod-nvidia

    • dnf install xorg-x11-drv-nvidia-cuda

    • Reboot

    • To test the install:
      modinfo -F version nvidia

  • Install numpy and pytorch
    This assumes you have installed NVIDIA drivers and CUDA.
    • sudo -i
    • python3 -m pip install numpy
    • python3 -m pip install tables
    • python3 -m pip install opencv-python
    • python3 -m pip install matplotlib
    • python3 -m pip install sklearn
    • python3 -m pip install pylint
    • python3 -m pip install flake8
    • python3 -m pip install xgboost
    • python3 -m pip install python-gnupg
    • python3 -m pip install psutil
    • python3 -m pip install boto3
    • dnf install python3-tkinter

    • Find out which version of CUDA is running: nvidia-smi

    • To install Pytorch itself, go to the
      Select the proper options in the table and it will give you an install line for Pytorch.
      Copy and paste this into the command line

  • Installing Google Drive for Python on Fedora

  • Fixing Sound Issues
    I have not been able to make this work. I have NVIDIA drivers, which is the audio output. I ended up just using a USB audio card, but there seems to be a way to make this work.
    • Getting the audio module in use:
      lspci -v | grep -iA10 audio | grep modules (below, I assume this returns snd-hda-intel)
      cat /proc/asound/card*/codec* | grep Codec (below, I assume this returns Codec: Nvidia GPU a0 HDMI/DP)
      sudo -i
      echo "options snd-hda-intel model=auto" > /etc/modprobe.d/alsa.conf
  • Misc
    • yum install ftp
    • yum install dvd+rw-tools
    • dnf install -y gvfs-mtp

  • Evolution Email
    • Install Evolution from Software Manager tool
    • Go through View menu options (Preview=Vertical, Uncheck group by threads)
    • Go through menu Edit>Preferences
    • Setup gmail
      • Select the menu "Edit>Accounts" and then expand the list item for your email account, then expand the list item for "Mail Accounts" and then select the list item for your email account and click the "Edit" button.
      • In the edit dialog, select "Receiving Email" and change the to
      • In the edit dialog, select "Sending Email" and change the to
    • Create an account for Local Archived files
      • Select the menu item File>New>Mail Account
      • For the General Dialog, FillName=Local Archive
      • For the Receiving Email Dialog, accountType="Standard Unix mbox spool directory" spoolDirectory=[local archive dir]
      • For the Receiving Options Dialog, deselect all options, these messages have already been filtered and saved.
      • For the Sending Email Dialog, serverType=None
      • For the Account Summary Dialog, name="Local Archive"

  • Installing Git and Github gh command-line tool on Fedora
    • sudo -i
    • dnf install git-all
    • On non-Linux systems, download Git -
    • dnf config-manager --add-repo
    • dnf install gh

    Create a user

    • git config --global "xxxx xxxx"
    • git config --global
    • git config --global core.editor emacs
    • git config --list

    Install GitHub Desktop

    • Download the rpm from github
    • sudo -i
    • rpm -i GitHubDesktop-linux-2.9.6-linux1.rpm

  • Installing Zoom on Fedora

  • Prusa Slicer
    The instructions are here

  • Microsoft Teams
    Microsoft Download Page
    • cd ~/Downloads
    • sudo -i
    • dnf localinstall teams[tab key]

  • Disable Bell in shell windows

    Edit the "/etc/inputrc" to add the line:

        set bell-style none

  • Automate backups and other tasks with cron
    • sudo -i
    • dnf install cronie cronie-anacron
    • python3 -m pip install boto3
    • If cron is not running, use this to configure it to run at boot:
      systemctl enable crond.service
    • Add this line to /etc/crontab
      0 2 * * * ddean /home/ddean/ddRoot/tools/offsiteBackup
      0 1 * * * ddean /home/ddean/ddRoot/tools/offsiteTasks
    • Make sure the files offsiteBackup and offsiteTasks are executable
      chmod ugo+x offsiteBackup
      chmod ugo+x offsiteTasks

  • Install user logon scripts
    • cp ~/ddRoot/tools/ddean.desktop ~/.config/autostart/ddean.desktop
    • chmod ugo+x ~/.config/autostart/ddean.desktop

  • Brother Printer Install the drivers Install the scanner utilities
    • Look on the printer/scanner to determine its IP address. This assumes it is 192.168.1.xxxx
    • vi /etc/sane.d/saned.conf
    • Add to the config
    • brsaneconfig4 -a name=Brother model=MFCL2750DW ip=192.168.1.xxxx
    • gscan2pdf

  • OBS (Open Broadcaster Software) Studio The installation instructions on the official project site are at
    • Download some prereqs
      dnf install$(rpm -E %fedora).noarch.rpm$(rpm -E %fedora).noarch.rpm
    • dnf install obs-studio
  • Closure
  • Apache
    • sudo -i
    • dnf install httpd
    • To have the server start at each boot: systemctl enable httpd.service
    • To start the server now: systemctl start httpd.service

Installing and configuring Linux Disks and Samba File Server

A few common steps that I follow when managing disks and Samba on Fedora. Note - this is Fedora specific but may be close to what you would do on another distro.

    Format and mount a new disk

    • GParted to determine the drive label
      • sudo -1
      • dnf install gparted
      • gparted
      Run gparted to find the device for the new disk. All examples below assume /dev/sda but this will be different for each disk.

    • Partition the disk
      This will make a numeric partition, like /dev/sda1 is the first partition of /dev/sda. Refer to that partition now.
      • fdisk /dev/sda
      • n
      • w
      You can use lsblk to confirm the new partition is created.

    • Make the file system.
      You can use "mkfs -v -t ext4 /dev/sda1" However, I just used gparted.

    • Mount the FS
      • mkdir -v /fsDisk
      • mount --source /dev/sda --target /fsDisk

    • Some useful links:

    Set a Static IP Address for your Server

    This uses a local IP address behind your router, so it is *only* visible on the local network.

    • Get the local network device names
      • sudo -i
      • dnf install lshw
      • lshw -class network

    • Or you can simply do this:
      • ifconfig

      So, why is this an odd name, like enp0s31f6 and now "eth0" or something? These are the new "Predictable network interface device names", which remain the same despite different physical and virtual network cards being added and removed. enp0s31f6 refers to ethernet (en), prefix 0 (p0), slot 31 (s31), function 6 (f6)

    • See what the IP address of the local machine is
      • ip addr show

    • Configure an interface with static network settings using ifcfg files For an interface with the name enp0s31f6, create a file with name ifcfg-enp0s31f6 in the /etc/sysconfig/network-scripts/ directory with content similar to this:
      See Fedora Docs

    • Reboot and confirm the change
      • ip addr show dev enp0s31f6

    Install and enable Samba

    This also sets the firewall to allow access to Samba from other computers. See Fedora Docs for more. There is also a useful article in Fedora magazine.

    • Install the Samba software and open access to it through the local machine firewall so other machines (even those on your local network) can access it.
      • sudo -i
      • dnf install samba
      • sudo systemctl enable smb --now
      • firewall-cmd --get-active-zones
      • sudo firewall-cmd --permanent --zone=FedoraWorkstation --add-service=samba
      • sudo firewall-cmd --reload

    • Do user and group setup. See the private instructions.

    • Tell Samba that this is a share
      • semanage fcontext --add --type "samba_share_t" /fsDisk
      • restorecon -R /fsDisk

    • Configure Samba
      There is no longer a GUI tool for configuring Samba. There was one in the past but it is no longer supported for a variety of reasons (lack of developer support, known bugs, etc). So, you have to manually edit the /etc/samba/smb.conf file. Below is a very simple smb.conf file that will make one share with NO security (everyone can read/write it). I am using this for my private file share that is behind my router.
      # Run 'testparm' to verify the config is correct after
      # you modified it.
      # The name of the share is in square brackets [],
      #   this will be shared as //hostname/sharename
      # There are a three exceptions:
      #   the [global] section;
      #   the [homes] section, that is dynamically set to the username;
      #   the [printers] section, same as [homes], but for printers.
      # path: the physical filesystem path (or device)
      # comment: a label on the share, seen on the network.
      # read only: disable writing, defaults to true.
      # Note:
      # SMB1 is disabled by default. This means clients without support for SMB2 or
      # SMB3 are no longer able to connect to smbd (by default).
      # BUG!
      #	workgroup = SAMBA
      #	workgroup = FEDORA
      #	security = user
      #	passdb backend = tdbsam
      #	valid users = %S, %D%w%S
      	server role = standalone server
      	workgroup = SAMBA
      	log file = /var/log/samba/%m
              log level = 1
              comment = File System Share
              path = /fsDisk
      	guest ok = yes
              guest only = yes
      	read only = no
      	writeable = yes
              browseable = yes
              public = yes
              create mask = 0770
              directory mask = 0770

      By default, Samba uses tdbsam for user information. This is based on “TDB” (trivial database). Also by default the workgroup is "SAMBA".

    • Make sure SMBv1 is disabled
      You can add the following to the [global] section of /etc/samba/smb.conf client min protocol = SMB2_02 server min protocol = SMB2_02 However, I leave this out if the config file includes the comment that SMBv1 is disabled.

    • Some useful links:

    Mount the Samba Share on a Linux Client

    • Now look for IP addresses of other machines to see what is in use. This should confirm that the static IP we set up above is visible.
      • dnf install nmap
      • nmap -sn
      • nmap -sT -O

    • Install the CIFS client software
      • sudo -i
      • dnf install cifs-utils
    • Make a place to mount the remove server
      • sudo -i
      • mkdir /fileServer
      • chmod ugo+rwx /fileServer

    • Modify your /etc/fstab file.
      WARNING!!!!! Do NOT change any other line in the /etc/fstab file. This can make your system unusable and require a complete new OS install!!!! Only APPEND a new line. You have been warned.
      // /fileServer cifs guest,vers=3.0,noperm 0 0
      The option noperm in fstab tells the client to not do permission checks. This can expose files on this mount to access by other users on the local client system

    • Reload the modified /etc/fstab file to remount all file systems
      • mount -a

    Mount the Samba Share on a Windows Client

    I do not have a good fix here. The big problem seems to be the client cannot authenticate to a Samba server that has no password. I have tried changing the registry keys.

    I have read Microsoft KB notes that say to use "the Local Group Policy Editor (gpedit.msc)". I have also read posts and seen notes saying to use Regedit to add a DWORD named "AllowInsecureGuestAuth" and set its value to 1 under the following keys:

    • HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\LanmanWorkstation\
    • HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters
    See the KB Then they say to use File Explorer to right-click "This PC" and in the context menu select "Add a network location". But this doesn't work for me.

    So, instead I do this:

    • Mount the server to a local drive through the command line
      • net use x: \\\fileroot /user:"" ""

    • Or mount the server to a local drive through the GUI
      • Right click "This PC" and select the "Map Network Drive..."

    However, this does NOT survive across reboots. After rebooting, it fails to mount the server again because the user name and password are blank. So, I got a bit frustrated (and I don't use Windows daily) and made a shell script which is on the desktop which I have to run to mount the server.

    net use x: /delete
    net use x: \\\fileroot /user:""  ""
    Yes, there is a better way, and yes I am obviously missing something above. But for now, this will get me through.

Block Access to the SMB Ports from outside the router

See This will block Internet access to the device but it will be accessible on the LAN to others.
  • Launch an internet browser from a computer or wireless device that is connected to the network. This will be usually one of these:
  • Click "Advanced" tab
  • Select the "Security > Block Services" section from the pane on the left
  • Under Service Table, click "Add"
  • US-CERT recommends that users and administrators consider:
    • UDP/137 - used by nmbd - incoming UDP datagrams from the local network
    • UDP/138 - used by nmbd - incoming UDP datagrams from the local network
    • TCP/139 - used by smbd - incoming TCP connections
    • TCP/445 - used by smbd - incoming TCP connections

Installing and configuring Emacs

A few common shortcuts that I personally prefer. The blessing/curse of emacs is that it is so customizable, everyone ends up with a slightly different solution. These are what I have come up with so far, but I am also still trying to tweak it to make it more to my liking. Still, you may not like these design choices.

When testing a .emacs file, you can always use "M-x load-file" and then enter the file name. This will reload the config file without quitting and restarting the program.

;; Emacs Customization
;; Tips and tricks from many sources, collected by Dawson Dean

;; Font Size and Type
;; The height is 1/100th of a point, so 100 is a 10pt font.
(set-default-font "DejaVu Sans Mono")
(set-face-attribute 'default nil :height 100)

;; Text Colors
(set-face-foreground 'font-lock-string-face "black")
(set-face-foreground 'font-lock-comment-face "dark green")
(set-face-foreground 'font-lock-comment-delimiter-face "dark green")
(set-face-foreground 'font-lock-function-name-face "black")
(set-face-foreground 'font-lock-variable-name-face "black")
(set-face-foreground 'font-lock-keyword-face "dark blue")
(set-face-foreground 'font-lock-type-face "black")
(set-face-foreground 'font-lock-constant-face "black")
(set-face-foreground 'font-lock-builtin-face "black")
(set-face-foreground 'font-lock-preprocessor-face "black")

;; The color of the mark region
(set-face-attribute 'region nil :background "#BFEFFF")
;; Blue:    0000FF
;; Orange:  FFA000

;; Custom Key Bindings

;; Ctrl-Z is undo.
(global-set-key (kbd "C-z") 'undo)
(global-set-key (kbd "C-Z") 'undo)

;; Ctrl-/ will goto-line
;; This is totally unique to me, nobody else agrees on this. Lots of people
;; seem to like "Esc-g g" but that's still too many keystrokes for me.
(define-key global-map (kbd "C-/") 'goto-line)

;; I sometimes have the Control key held down while doing other things.
(define-key global-map (kbd "") (kbd ""))
(define-key global-map (kbd "") [Double-Mouse-1])

;; Basic Editing

;; Shift-click will extend the mark region
(define-key global-map (kbd "") 'mouse-save-then-kill)

;; Typing will replace the currently selected text.
(delete-selection-mode 1)

;; Syntax Table Hacking
;; Word operations will not treat "_" as a word-break in C++. This puts
;; the character "_" (which is quoted with ? so it is ?_) in the "word"
;; class of characters (which is identified by "w").
;; Really, we just want to evaluate this:  (modify-syntax-entry ?_ "w")
;; But we add a hook so our customization is not clobbered every time
;; the symbol table is edited.
(add-hook 'text-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'c-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'c++-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'html-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'xml-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'java-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'js-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'js2-mode-hook (lambda () (modify-syntax-entry ?_ "w")))
(add-hook 'abbrev-mode-hook (lambda () (modify-syntax-entry ?_ "w")))

;; Select the entire buffer
;; This was copied (with some small changes) from:
(defun mark-whole-buffer()
       "Select the entire buffer"
       (message "mark-whole-buffer!")
        ;; Put point at beginning 
       (push-mark (point))
        ;; Put the mark at end of buffer.
       (push-mark (point-max) nil t)
       (goto-char (point-min))
) ;; defun
(global-set-key (kbd "C-S-A") 'mark-whole-buffer)

;; CUA Mode
;; This makes Ctl-x cut, Ctl-v paste, and Ctl-C copy.
;; This is what you use in Web browsers, so it makes sense for all applications to
;; share a common convention.
(cua-mode t)
(transient-mark-mode 1) ;; Default in Emacs 23 and later. Selected region is only active when highlighted
;;(setq cua-auto-tabify-rectangles nil) ;; Don't tabify after rectangle commands
;;(setq cua-keep-region-after-copy t) ;; Standard Windows behaviour

;; Searching: Find, Find-And-Replace, Grep 
;; As I switched back to emacs after years on Microsoft's Visual Studio, I realized
;; that I use search to navigate around a buffer more than Ctl-V and Esc-V or similar
;; things. Here are some functions to find the next and previous instance of the
;; currently selected text.

;; Find the next instance of the selected text
(defun forward-search-selection (beg end)
    "Search for the current selection"
    ;; This tells elisp to call this command with the point and mark
    ;; as arguments parameters bound to beg and end
    (interactive "r")

    ;; Save the current selection to a local variable.
    ;; We want to deactivate the mark, so save a private copy first.
    (let (
          (selection (buffer-substring-no-properties beg end))
        ;;(message "selection:%s" selection)
        ;; De-activate the current mark region. We will change the mark later

        ;; Find the next instance of the string.
        ;; search-forward takes 4 arguments:
        ;;      The search pattern
        ;;      Optional - limit of search. nil means end of buffer
        ;;      Optional - how to handle failed search. nil means print a message.
        ;;                   t means return a result
        ;;      Optional - How many instances to find
        (when (search-forward selection nil t)
            ;; If search-forward returned true, then it found a match.
            ;; Select the match. This is nice for user feedback but it also
            ;; lets another search-forward find the next occurrence.
                (mark) (match-beginning 0)
                (point) (match-end 0))
        ) ;; when
    ) ;; let
) ;; forward-search-selection
(define-key global-map (kbd "") 'forward-search-selection)

;; Find the previous instance of the selected text
(defun reverse-search-selection (beg end)
    "Search for the current selection"
    ;; This tells elisp to call this command with the point and mark
    ;; as arguments parameters bound to beg and end
    (interactive "r")

    ;; Save the current selection to a local variable.
    ;; We want to deactivate the mark, so save a private copy first.
    (let (
          (selection (buffer-substring-no-properties beg end))
        ;; De-activate the current mark region. We will change the mark later

        ;; Find the prev instance of the string.
        ;; This works like search-forward except it runs in reverse
        ;; search-backward takes 4 arguments:
        ;;      The search pattern
        ;;      Optional - limit of search. nil means end of buffer
        ;;      Optional - how to handle failed search. nil means print a message.
        ;;                   t means return a result
        ;;      Optional - How many instances to find
        (when (search-backward selection nil t)
            ;; If search-forward returned true, then it found a match.
            ;; Select the match. This is nice for user feedback but it also
            ;; lets another search-forward find the next occurrence.
                (mark) (match-end 0)
                (point) (match-beginning 0))
        ) ;; when
    ) ;; let
) ;; reverse-search-selection
(define-key global-map (kbd "") 'reverse-search-selection)

;; Replace Text

;; Replace the next instance of the selected text
(defun forward-replace-selection (beg end)
    "Search for the current selection"
    ;; This tells elisp to call this command with the point and mark
    ;; as arguments parameters bound to beg and end
    (interactive "r")

    ;; Save the current selection to a local variable.
    ;; We want to deactivate the mark, so save a private copy first.
    (let (
          (selection (buffer-substring-no-properties beg end))
        ;; (message "forward-replace-selection:%s" selection)
        ;; De-activate the current mark region. We will change the mark later

        (let (
            (replaceStr (read-from-minibuffer "Replacement: "))
            ;;(message "replaceStr:%s" replaceStr)

            ;; Go to the start of the buffer.
            ;; search-forward will only start at the current position.
            (goto-char (point-min))

            (while (search-forward selection nil t)
                ;; replace-match replacement &optional fixedcase literal string subexp
                ;; fixedcase says to not change the case of the replacement text
                ;; to match the text being replaced.
                (replace-match replaceStr t))
        ) ;; let

    ) ;; let
) ;; forward-replace-selection
(define-key global-map (kbd "C-r") 'forward-replace-selection)

;; Grep

;; Find the next instance of the selected text
(defun grep-selection (beg end)
    "Grep for the current selection"
    ;; This tells elisp to call this command with the point and mark
    ;; as arguments parameters bound to beg and end
    (interactive "r")

    ;; Save the current selection to a local variable.
    ;; We want to deactivate the mark, so save a private copy first.
    (let (
          (pattern (buffer-substring-no-properties beg end))
        (message "ddGrep:%s" pattern)
        ;; De-activate the current mark region. We will change the mark later

        ;; grep-find is a built-in emacs elisp function.
        ;; See:
        ;; See:

        ;; The options are the normal command line grep options.
        ;; Here, I use:
        ;;  -e, --regexp=PATTERN      use PATTERN for matching
        ;;  -i, --ignore-case         ignore case distinctions
        ;;  -n, --line-number         print line number with output lines
        ;;  -H, --with-filename       print file name with output lines
        ;;  -R, --recursive           like --directories=recurse, and also follow all symlinks
        ;; Some useful topns which are not used now, but may be used later
        ;;  -w, --word-regexp         force PATTERN to match only whole words
        ;;  -x, --line-regexp         force PATTERN to match only whole lines
        ;;  -m, --max-count=NUM       stop after NUM selected lines
        ;;  -h, --no-filename         suppress the file name prefix on output
        ;;  -o, --only-matching       show only the part of a line matching PATTERN
        ;;  --include=FILE_PATTERN    search only files that match FILE_PATTERN
        ;;  -L, --files-without-match print only names of FILEs with no selected lines
        ;;  -l, --files-with-matches  print only names of FILEs with selected lines
        ;;  -T, --initial-tab         make tabs line up (if needed)
        ;;  -B, --before-context=NUM  print NUM lines of leading context
        ;;  -A, --after-context=NUM   print NUM lines of trailing context
        ;;  -C, --context=NUM         print NUM lines of output context
        (grep (concat "grep -i -n -H -R -e \"" (shell-quote-argument pattern) "\" /home/ddean/ddRoot/code"))
    ) ;; let
) ;; grep-selection
(define-key global-map (kbd "") 'grep-selection)

;; Parens and Braces

;; Find the matching (open or close) paren
;; This was copied (with some small changes) from:
(defun find-match-paren (arg)
    "Go to the matching paren if on a paren; otherwise insert %."
    (interactive "p")
            ((looking-at "\\s(") (forward-list 1) (backward-char 1))
            ((looking-at "\\s)") (forward-char 1) (backward-list 1))

            ((looking-at "\\s[") (forward-list 1) (backward-char 1))
            ((looking-at "\\s]") (forward-char 1) (backward-list 1))
    ) ;; cond
) ;; defun
(define-key global-map (kbd "C-]") 'find-match-paren)

;; Make braces act like parens, and match opens and closes
(modify-syntax-entry ?{ "(}")
(modify-syntax-entry ?} "){")

;; Tabs and Indentation

;; Tabs are space characters, not a tab character.
(setq-default indent-tabs-mode nil)

(global-set-key (kbd "TAB") 'tab-to-tab-stop)
(setq default-tab-width 4)
(setq tab-width 4)

;; tab-width is used when DISPLAYING tabs, while tab-stop-list 
;; is needed to determine tab stops when you ADD tabs.
;; From emacs documentation, "The variable tab-stop-list controls these positions. The default value is nil, which means a tab stop every 8 columns."
;;;(setq-default c-basic-offset 4)
(setq tab-stop-list (number-sequence 4 200 4))

;; Be careful. If you set this to newline-and-indent, then emacs
;; will autoindent no matter what you set the autoindent options to.
;;(global-set-key (kbd "RET") 'newline-and-indent)
(global-set-key (kbd "RET") 'newline)

;; Don't use tabs to indent code.
;;;(setq-default indent-tabs-mode nil)

;; Stop emacs from trying to second-guess what it thinks I want.
(when (fboundp 'electric-indent-mode) (electric-indent-mode -1))
;;(setq-default electric-indent-inhibit t)

;; Pasting a newline does not cause an indent.
(global-set-key "\C-j" 'newline)

;; Indenting and Un-Indenting

(defun shift-region (distance)
  (let ((mark (mark)))
      (indent-rigidly (region-beginning) (region-end) distance)
      (push-mark mark t t)
      ;; Tell the command loop not to deactivate the mark
      ;; for transient mark mode
      (setq deactivate-mark nil))))

(defun shift-right ()
  (shift-region 4))

(defun shift-left ()
  (shift-region -4))

;; C-[ is equivalent to the escape key on US English keyboards
;; Changing  C-[ will break things like Esc-x
(global-set-key (kbd "C-]") 'shift-right)
(global-set-key (kbd "C-.") 'shift-right)
(global-set-key (kbd "C-,") 'shift-left)

;; Backup Files
(setq backup-directory-alist `(("." . "~/emacsBackupFiles")))

(setq delete-old-versions t
  kept-new-versions 1
  kept-old-versions 1
  version-control t)

;; This will turn off all backup files.
;; (setq make-backup-files nil)

vi editor

I used emacs until I went into IDE's. Now that I am back to some linux programming, here are some tips for those times when I do a bit of VI (like when you are running as root and need an editor for a config file).

  • Run vi - "vi fileName"

  • Enter insert mode - Type "i <RET>". Now any further text you type is entered into the file as data. You can use the arrow keys to move around the file. This command leaves command mode.

  • Leave insert mode - Type the <ESC> key. Now you are back in command mode.

  • Save changes and exit vi - ":wq <RET>" Type this in command mode

  • Exit vi withOUT saving changes - ":q! <RET>" Type this in command mode

  • Search for the next occurrence after the cursor of some pattern - "/pattern <RET>" Type this in command mode

  • Search for the previous occurrence after the cursor of some pattern - "?pattern <RET>" Type this in command mode

  • Find the next occurrence of the pattern - "n <RET>" Type this in command mode

  • Save the current file - ":w <RET>" Type this in command mode

  • Save the current file to a new file - ":w fileName <RET>" Type this in command mode

Emacs Common Things

For some reason, I always forget these things.

  • Conditional-Search-Replace M-% string RET newstring RET
    Then, <Space> to replace the current instance, <DEL> to skip the current instance, <RET> to stop search without any more replacements

Burning DVDs on Linux

I use an online backup service, but I still like to burn my home directory to a DVD every few days. It lets me make my own offsite backups, as well as shuttle my home directory between machines and between Linux and Windows. I know I might be able to use some online service for that, but with more complexity, with a monthly subscription fee, with challenges in portability across operating systems, with a dependency on a third party company that may change their UI or features or costs, and with my data sitting on somebody else's computer which may be secure but is also an inviting target for hackers. On Windows, I just used Roxio, but on Linux, here is a quick and dirty solution. I wrote scripts to do this, so I just run the script to burn an image:

This uses growisofs, which requires you install

    yum install dvd+rw-tools
Burning a data DVD with a tree of files
    mkisofs -J -R -o /your-temp-directory-name/foo.iso -root your-top-level-dir-name  /your-home-dir
    growisofs -dvd-compat -Z /dev/cdrom=/your-temp-directory-name/foo.iso 
    rm -rf /your-temp-directory-name/foo.iso
Restoring a Directory from a DVD
    umount /dev/cdrom
    mount -t iso9660   /dev/cdrom   your-temp-directory-name
    rm -r -I   your-home-dir
    cp -r your-temp-directory-name   your-home-dir
    chown -R   your-user:your-group   your-home-dir
    chmod -R   u+rwx  your-home-dir
    umount /dev/cdrom
Note, these must run as root.
Burning VOB files to a Video DVD
There are several alternatives.
  • mkisofs -dvd-video -o mydvd.iso -udf /path/to/filedir/
    This will not skrink, so the .iso file will be 8gb
  • genisoimage -dvd-video -v -o DVD.iso DVD

Compiling Linux programs with static libraries

Linux has adopted the philosophy that programs should be dynamic linked. There are both legal reasons for this (the libraries are built under GPL) and practical. However, suppose you want to compile a program, and then run your program on servers provided by web hosting companies. Your program must be compiled with exactly the same version of the runtime libc as is available on the hosting servers. Do hosting companies guarantee that? Of course not. So, instead your program must be compiled with static libraries. That is the problem I am trying to solve, and here are some notes.

  • Compile your programs with static linking. The compiler uses the flag -static. There are some other flags that I have seen discussed, but in practice I don't need them. These include the flags -Wl -Bstatic, where -Wl sends a flag to the linker and -Bstatic is the static link flag

  • Install the static libraries
    • yum install glibc-static
    • yum install libstdc++-static

  • Key networking system calls do not seem to work for a statically linked program. Specifically, you cannot lookup a network address if you are statically linked because getaddrinfo and even gethostname do not work. It seems that the name resolution library runs different code depending on host-specific preferences, like whether to use DNS or other network infrastructure. So, rather than writing 1 program that can call out to different local name resolver services (like, via a local pipe or system call), the C library is hard-compiled with the diffreent sources. This means that libc cannot call gethostbyname in a portable way. Instead, you must dynamically link with the local glibc on each different machine. If you really need to run the static glibc, then you cannot use this call.

Installing and configuring mySQL


I use Fedora, which uses dnf and yum, and the best guide I found (granted after only a cursory look) is at

Installing and configuring Apache
  • Install Apache
    • su
    • dnf install httpd
    • To have the server start at each boot: systemctl enable httpd.service
    • To start the server now: systemctl start httpd.service
  • Configuration
    • GUI Configuration tool: /usr/bin/system-config-httpd
    • Manual edit config files. emacs /etc/httpd/conf/httpd.conf

Using CSS "position" attributes for HTML Layout

Many HTML elements may use CSS to control where they are positioned on a page. This is done with a "position" attribute, that may have two values: "absolute" or "relative". For example:

  • style="position:absolute; left:0px; top:0px;"
  • style="position:relative; left:0px; top:0px;"

These can be confusing, because they use the terms "absolute" and "relative" to place an element in a position in relation to the "normal position of that element in the HTML layout", and NOT necessarily in relation to another element. So, the browser first lays out an HTML document, which assigns every element in the document to a position on the page. This initial position is referred to as the element's position in the "document flow". Once the browser has completed this initial layout step, then the CSS position attributes may override each element's position and place the element in a different place.

"Relative" means place the element at some offset in relation to where it would normally go in the HTML laytout. So, for example, if a typical HTML page would place an element at x=100,y=200, and the element had an attribute

  • style="position:relative; left:50px; top:75px;"
then the element would be placed at x=150,y=275.

"Absolute" means place the element at some "absolute" position, and just ignore where it would normally go in the HTML laytout. So, for example, if a typical HTML page would place an element at x=100,y=200, and the element had an attribute

  • style="position:absolute; left:50px; top:75px;"
then the element would be placed at x=50,y=75.

However, the confusing part is that an "absolute" coordinate is still in relation to somethng. It may be in relation to the bottom-left corner of the HTML page, but it may also be in relation to a containing element, like a div element. So, "position:absolute" means an absolute position compared to the flow of the document but still relative to the position of the parent HTML element that contains the element being moved.

Installing Raspberry Pi

Installation with Linux

  • Run lsblk to see which devices are NOT the SD card. This will print a list of devices.
  • Plug an SD card into the linux box - I use a USB-SD-reader.
  • Run "lsblk" again. The USB HDMI is cometimes sdb, but beware. That can differ with different devices.
  • sudo -i
  • parted /dev/sdb - or whatever the device name of the SD card is.
    • (parted) mklabel msdos
    • (parted) mkpart primary fat32 1MiB 100%
    • (parted) set 1 boot on
  • mkfs.vfat /dev/sdb1
  • Ctrl-D
  • Download the latest noobs OS software from
  • Mount the device. One way to do this is to open Files, which will automount the new device.
  • cd ~/Downloads
  • unzip -d /run/media/userName/xxxxxx - where userName is your name and XXXX is the volume name of the SD drive
  • Plug in the SD card, a USB mouse, a USB Keyboard, a HDMI monitor into the Pi and connect a powersupply.
  • Plug the power supply in, and the Pi should boot. It will install an OS from your SD card
Some handy references:

Copying Files from Linux to a Pi

  • Configure the Pi to accept SSH connections.
    • sudo systemctl enable ssh
    • sudo systemctl start ssh
    Or, try this:
    • On desktop, select menu "Preferences>Raspberry Pi Configuration"
    • Select the Interfaces tab
    • Select "Enabled" next to SSH
    • Select the "OK" button, and the Pi will reboot
  • On the Pi, open a terminal window and run "ifconfig". Next to the wlan0 entry, get the IP address
  • To copy from Linux to Pi: scp file.txt
  • To copy from Pi to Linux: scp file.txt
Some handy references:

Cross-compiling on Linux and Running on Pi

I am not doing this yet. Currently, I am just maintaining source code on my dev box and copying it to a Pi and compiling it there.
  • yum install apt-get install git rsync cmake
    Note that ia32-libs is no longer supported.
Some handy references: