From c22d87f6dede9f55dfc5ebc8a1db8283fb078d95 Mon Sep 17 00:00:00 2001 From: Alex Tarkovsky Date: Sat, 13 Oct 2007 11:02:51 +0200 Subject: New features for generate-configs.sh; renamed to generate-configs darcs-hash:20071013090251-bd4fb-cbc2dbc80107aa545c665fe552c19a9bbde2b04f.gz --- scripts/generate-configs | 302 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100755 scripts/generate-configs (limited to 'scripts/generate-configs') diff --git a/scripts/generate-configs b/scripts/generate-configs new file mode 100755 index 0000000..e2880f6 --- /dev/null +++ b/scripts/generate-configs @@ -0,0 +1,302 @@ +#!/bin/bash + +# generate-configs - Docstring parser for generating xmonad build configs with +# default settings for extensions +# Author: Alex Tarkovsky +# Released into the public domain + +# This script parses custom docstrings specifying build-time configuration data +# from xmonad extension source files, then inserts the data into copies of +# xmonad's Config.hs and xmonad.cabal files accordingly. +# +# Usage: generate-configs [ OPTIONS ] --main MAIN_DIR --contrib CONTRIB_DIR +# +# OPTIONS: +# --active, -a Insert data in active mode (default: passive) +# --contrib, -c CONTRIB_DIR Path to contrib repository base directory +# --help, -h Show help +# --main, -m MAIN_DIR Path to main repository base directory +# --output, -o OUTPUT_DIR Output directory (default: CONTRIB_DIR) +# +# Data parsed from the extension source files is inserted into Config.hs in +# either active or passive mode. The default is passive mode, in which the +# inserted data is commented out. The --active option inserts the data +# uncommented. Data inserted into xmonad.cabal is always inserted in active +# mode regardless of specified options. +# +# The docstring markup can be extended as needed. Currently the following tags +# are defined, shown with some examples: +# +# ~~~~~ +# +# %cabalbuilddep +# +# Cabal build dependency. Value is appended to the "build-depends" line in +# xmonad.cabal and automatically prefixed with ", ". NB: Don't embed +# comments in this tag! +# +# -- %cabalbuilddep readline>=1.0 +# +# %def +# +# General definition. Value is appended to the end of Config.sh. +# +# -- %def commands :: [(String, X ())] +# -- %def commands = defaultCommands +# +# %import +# +# Module needed by Config.sh to build the extension. Value is appended to +# the end of the default import list in Config.sh and automatically +# prefixed with "import ". +# +# -- %import XMonadContrib.Accordion +# -- %import qualified XMonadContrib.FlexibleManipulate as Flex +# +# %keybind +# +# Tuple defining a key binding. Must be prefixed with ", ". Value is +# inserted at the end of the "keys" list in Config.sh. +# +# -- %keybind , ((modMask, xK_d), date) +# +# %keybindlist +# +# Same as %keybind, but instead of a key binding tuple the definition is a +# list of key binding tuples (or a list comprehension producing them). This +# list is concatenated to the "keys" list must begin with the "++" operator +# rather than ", ". +# +# -- %keybindlist ++ +# -- %keybindlist -- mod-[1..9] @@ Switch to workspace N +# -- %keybindlist -- mod-shift-[1..9] @@ Move client to workspace N +# -- %keybindlist -- mod-control-shift-[1..9] @@ Copy client to workspace N +# -- %keybindlist [((m .|. modMask, k), f i) +# -- %keybindlist | (i, k) <- zip [0..fromIntegral (workspaces-1)] [xK_1 ..] +# -- %keybindlist , (f, m) <- [(view, 0), (shift, shiftMask), (copy, shiftMask .|. controlMask)]] +# +# %layout +# +# A layout. Must be prefixed with ", ". Value is inserted at the end of the +# "defaultLayouts" list in Config.sh. +# +# -- %layout , accordion +# +# %mousebind +# +# Tuple defining a mouse binding. Must be prefixed with ", ". Value is +# inserted at the end of the "mouseBindings" list in Config.sh. +# +# -- %mousebind , ((modMask, button3), (\\w -> focus w >> Flex.mouseResizeWindow w)) +# +# ~~~~~ +# +# NB: '/' and '\' characters must be escaped with a '\' character! +# +# Tags may also contain comments, as illustrated in the %keybindlist examples +# above. Comments are a good place for special user instructions: +# +# -- %def -- comment out default logHook definition above if you uncomment this: +# -- %def logHook = dynamicLog + +# Markup tag to search for in source files. +TAG_CABALBUILDDEP="%cabalbuilddep" +TAG_DEF="%def" +TAG_IMPORT="%import" +TAG_KEYBIND="%keybind" +TAG_KEYBINDLIST="%keybindlist" +TAG_LAYOUT="%layout" +TAG_MOUSEBIND="%mousebind" + +# Insert markers to search for in Config.sh and xmonad.cabal. Values are +# extended sed regular expressions. +INS_MARKER_CABALBUILDDEP='^build-depends:.*' +INS_MARKER_IMPORT='-- % Extension-provided imports$' +INS_MARKER_LAYOUT='-- % Extension-provided layouts$' +INS_MARKER_KEYBIND='-- % Extension-provided key bindings$' +INS_MARKER_KEYBINDLIST='-- % Extension-provided key bindings lists$' +INS_MARKER_MOUSEBIND='-- % Extension-provided mouse bindings$' +INS_MARKER_DEF='-- % Extension-provided definitions$' + +# Literal indentation strings. Values may contain escaped chars such as \t. +INS_INDENT_CABALBUILDDEP="" +INS_INDENT_DEF="" +INS_INDENT_IMPORT="" +INS_INDENT_KEYBIND=" " +INS_INDENT_KEYBINDLIST=" " +INS_INDENT_LAYOUT=" " +INS_INDENT_MOUSEBIND=" " + +# Prefix applied to inserted passive data after indent strings have been applied. +INS_PREFIX_DEF="-- " +INS_PREFIX_IMPORT="--import " +INS_PREFIX_KEYBIND="-- " +INS_PREFIX_KEYBINDLIST="-- " +INS_PREFIX_LAYOUT="-- " +INS_PREFIX_MOUSEBIND="-- " + +# Prefix applied to inserted active data after indent strings have been applied. +ACTIVE_INS_PREFIX_CABALBUILDDEP=", " +ACTIVE_INS_PREFIX_DEF="" +ACTIVE_INS_PREFIX_IMPORT="import " +ACTIVE_INS_PREFIX_KEYBIND="" +ACTIVE_INS_PREFIX_KEYBINDLIST="" +ACTIVE_INS_PREFIX_LAYOUT="" +ACTIVE_INS_PREFIX_MOUSEBIND="" + +# Don't touch these +opt_active=0 +opt_contrib="" +opt_main="" +opt_output="" + +generate_configs() { + for extension_srcfile in $(ls --color=never -1 "${opt_contrib}"/*.hs | head -n -1 | sort -r) ; do + for tag in $TAG_CABALBUILDDEP \ + $TAG_DEF \ + $TAG_IMPORT \ + $TAG_KEYBIND \ + $TAG_KEYBINDLIST \ + $TAG_LAYOUT \ + $TAG_MOUSEBIND ; do + + ifs="$IFS" + IFS=$'\n' + tags=( $(sed -n -r -e "s/^.*--\s*${tag}\s//p" "${extension_srcfile}") ) + IFS="${ifs}" + + case $tag in + $TAG_CABALBUILDDEP) ins_indent=$INS_INDENT_CABALBUILDDEP + ins_marker=$INS_MARKER_CABALBUILDDEP + ins_prefix=$ACTIVE_INS_PREFIX_CABALBUILDDEP + ;; + $TAG_DEF) ins_indent=$INS_INDENT_DEF + ins_marker=$INS_MARKER_DEF + ins_prefix=$INS_PREFIX_DEF + ;; + $TAG_IMPORT) ins_indent=$INS_INDENT_IMPORT + ins_marker=$INS_MARKER_IMPORT + ins_prefix=$INS_PREFIX_IMPORT + ;; + $TAG_KEYBIND) ins_indent=$INS_INDENT_KEYBIND + ins_marker=$INS_MARKER_KEYBIND + ins_prefix=$INS_PREFIX_KEYBIND + ;; + $TAG_KEYBINDLIST) ins_indent=$INS_INDENT_KEYBINDLIST + ins_marker=$INS_MARKER_KEYBINDLIST + ins_prefix=$INS_PREFIX_KEYBINDLIST + ;; + $TAG_LAYOUT) ins_indent=$INS_INDENT_LAYOUT + ins_marker=$INS_MARKER_LAYOUT + ins_prefix=$INS_PREFIX_LAYOUT + ;; + $TAG_MOUSEBIND) ins_indent=$INS_INDENT_MOUSEBIND + ins_marker=$INS_MARKER_MOUSEBIND + ins_prefix=$INS_PREFIX_MOUSEBIND + ;; + esac + + # Insert in reverse so values will ultimately appear in correct order. + for i in $( seq $(( ${#tags[*]} - 1 )) -1 0 ) ; do + [ -z "${tags[i]}" ] && continue + if [[ $tag == $TAG_CABALBUILDDEP ]] ; then + sed -i -r -e "s/${ins_marker}/\\0${ins_prefix}${tags[i]}/" "${CABAL_FILE}" + else + sed -i -r -e "/${ins_marker}/{G;s/$/${ins_indent}${ins_prefix}${tags[i]}/;}" "${CONFIG_FILE}" + fi + done + + if [[ $tag != $TAG_CABALBUILDDEP && -n "${tags}" ]] ; then + ins_group_comment="${ins_indent}-- For extension $(basename $extension_srcfile .hs):" + sed -i -r -e "/${ins_marker}/{G;s/$/${ins_group_comment}/;}" "${CONFIG_FILE}" + fi + done + done +} + +parse_opts() { + [[ -z "$1" ]] && show_usage 1 + + while [[ $# > 0 ]] ; do + case "$1" in + --active|-a) opt_active=1 + shift ;; + + --contrib|-c) shift + if [[ -z "$1" || ! -d "$1" ]] ; then + echo "Error: Option --contrib requires a directory as argument. See: generate-configs -h" + exit 1 + fi + opt_contrib="$1" + shift ;; + + --help|-h) show_usage ;; + + --main|-m) shift + if [[ -z "$1" || ! -d "$1" ]] ; then + echo "Error: Option --main requires a directory as argument. See: generate-configs -h" + exit 1 + fi + opt_main="$1" + shift ;; + + --output|-o) shift + if [[ -z "$1" || ! -d "$1" ]] ; then + echo "Error: Option --output requires a directory as argument. See: generate-configs -h" + exit 1 + fi + opt_output="$1" + shift ;; + + -*) echo "Error: Unknown option ${1}. See: generate-configs -h" + exit 1 ;; + + *) show_usage 1 ;; + esac + done + + if [[ -z "$opt_main" ]] ; then + echo "Error: Missing required option --main. See: generate-configs -h" + exit 1 + fi + + if [[ -z "$opt_contrib" ]] ; then + echo "Error: Missing required option --contrib. See: generate-configs -h" + exit 1 + fi +} + +show_usage() { +cat << EOF +Usage: generate-configs [ OPTIONS ] --main MAIN_DIR --contrib CONTRIB_DIR + +OPTIONS: + --active, -a Insert data in active mode (default: passive) + --contrib, -c CONTRIB_DIR Path to contrib repository base directory + --help, -h Show help + --main, -m MAIN_DIR Path to main repository base directory + --output, -o OUTPUT_DIR Output directory (default: CONTRIB_DIR) +EOF + exit ${1:-0} +} + +parse_opts $* + +[[ -z "$opt_output" ]] && opt_output="$opt_contrib" + +CABAL_FILE="${opt_output}/xmonad.cabal" +CONFIG_FILE="${opt_output}/Config.hs" + +cp -f "${opt_main}/xmonad.cabal" "${CABAL_FILE}" +cp -f "${opt_main}/Config.hs" "${CONFIG_FILE}" + +if [[ $opt_active == 1 ]] ; then + INS_PREFIX_DEF=$ACTIVE_INS_PREFIX_DEF + INS_PREFIX_IMPORT=$ACTIVE_INS_PREFIX_IMPORT + INS_PREFIX_KEYBIND=$ACTIVE_INS_PREFIX_KEYBIND + INS_PREFIX_KEYBINDLIST=$ACTIVE_INS_PREFIX_KEYBINDLIST + INS_PREFIX_LAYOUT=$ACTIVE_INS_PREFIX_LAYOUT + INS_PREFIX_MOUSEBIND=$ACTIVE_INS_PREFIX_MOUSEBIND +fi + +generate_configs -- cgit v1.2.3