about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--config.arg.h5
1 files changed, 3 insertions, 2 deletions
diff --git a/config.arg.h b/config.arg.h
index 41ae9b1..7a03460 100644
--- a/config.arg.h
+++ b/config.arg.h
@@ -27,8 +27,9 @@ static Key key[] = { \
 	{ MODKEY|ShiftMask,		XK_Return,	spawn, \
 		{ .cmd = "exec uxterm -bg '#111111' -fg '#eeeeee' -cr '#eeeeee' +sb -fn '"FONT"'" } }, \
 	{ MODKEY,			XK_p,		spawn, \
-		{ .cmd = "exec `ls -lL /usr/bin /usr/X11R6/bin /usr/local/bin 2>/dev/null | " \
-			"awk 'NF>2 && $1 ~ /^[^d].*x/ {print $NF}' | sort -u | dmenu`" } }, \
+		{ .cmd = "exec \"$(IFS=:; for dir in $PATH; do " \
+			"for file in \"$dir\"/*; do [ -x \"$file\" ] && echo \"${file##*/}\"; done; " \
+			"done | sort -u | dmenu)\"" } }, \
 	{ MODKEY,			XK_j,		focusnext,	{ 0 } }, \
 	{ MODKEY,			XK_k,		focusprev,	{ 0 } }, \
 	{ MODKEY,			XK_Return,	zoom,		{ 0 } }, \
/a> 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
#
#
#            Nimrod's Runtime Library
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## A higher level `mySQL`:idx: database wrapper. The same interface is 
## implemented for other databases too.

import strutils, mysql

type
  TDbConn* = PMySQL    ## encapsulates a database connection
  TRow* = seq[string]  ## a row of a dataset
  EDb* = object of EIO ## exception that is raised if a database error occurs

  TSqlQuery* = distinct string ## an SQL query string

  FDb* = object of FIO ## effect that denotes a database operation
  FReadDb* = object of FReadIO   ## effect that denotes a read operation
  FWriteDb* = object of FWriteIO ## effect that denotes a write operation

proc dbError(db: TDbConn) {.noreturn.} = 
  ## raises an EDb exception.
  var e: ref EDb
  new(e)
  e.msg = $mysql.error(db)
  raise e

proc dbError*(msg: string) {.noreturn.} = 
  ## raises an EDb exception with message `msg`.
  var e: ref EDb
  new(e)
  e.msg = msg
  raise e

when false:
  proc dbQueryOpt*(db: TDbConn, query: string, args: varargs[string, `$`]) =
    var stmt = mysql_stmt_init(db)
    if stmt == nil: dbError(db)
    if mysql_stmt_prepare(stmt, query, len(query)) != 0: 
      dbError(db)
    var 
      binding: seq[MYSQL_BIND]
    discard mysql_stmt_close(stmt)

proc dbQuote(s: string): string =
  result = "'"
  for c in items(s):
    if c == '\'': add(result, "''")
    else: add(result, c)
  add(result, '\'')

proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
  result = ""
  var a = 0
  for c in items(string(formatstr)):
    if c == '?':
      add(result, dbQuote(args[a]))
      inc(a)
    else: 
      add(result, c)
  
proc TryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
  tags: [FReadDB, FWriteDb].} =
  ## tries to execute the query and returns true if successful, false otherwise.
  var q = dbFormat(query, args)
  return mysql.RealQuery(db, q, q.len) == 0'i32

proc rawExec(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
  var q = dbFormat(query, args)
  if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)

proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
  tags: [FReadDB, FWriteDb].} =
  ## executes the query and raises EDB if not successful.
  var q = dbFormat(query, args)
  if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)
    
proc newRow(L: int): TRow = 
  newSeq(result, L)
  for i in 0..L-1: result[i] = ""
  
proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =  
  if row != nil:
    while mysql.FetchRow(sqlres) != nil: nil
  mysql.FreeResult(sqlres)
  
iterator FastRows*(db: TDbConn, query: TSqlQuery,
                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
  ## executes the query and iterates over the result dataset. This is very 
  ## fast, but potenially dangerous: If the for-loop-body executes another
  ## query, the results can be undefined. For MySQL this is the case!.
  rawExec(db, query, args)
  var sqlres = mysql.UseResult(db)
  if sqlres != nil:
    var L = int(mysql.NumFields(sqlres))
    var result = newRow(L)
    var row: cstringArray
    while true:
      row = mysql.FetchRow(sqlres)
      if row == nil: break
      for i in 0..L-1: 
        setLen(result[i], 0)
        add(result[i], row[i])
      yield result
    properFreeResult(sqlres, row)

proc getRow*(db: TDbConn, query: TSqlQuery,
             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
  ## retrieves a single row.
  rawExec(db, query, args)
  var sqlres = mysql.UseResult(db)
  if sqlres != nil:
    var L = int(mysql.NumFields(sqlres))
    result = newRow(L)
    var row = mysql.FetchRow(sqlres)
    if row != nil: 
      for i in 0..L-1: 
        setLen(result[i], 0)
        add(result[i], row[i])
    properFreeResult(sqlres, row)

proc GetAllRows*(db: TDbConn, query: TSqlQuery, 
                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
  ## executes the query and returns the whole result dataset.
  result = @[]
  rawExec(db, query, args)
  var sqlres = mysql.UseResult(db)
  if sqlres != nil:
    var L = int(mysql.NumFields(sqlres))
    var row: cstringArray
    var j = 0
    while true:
      row = mysql.FetchRow(sqlres)
      if row == nil: break
      setLen(result, j+1)
      newSeq(result[j], L)
      for i in 0..L-1: result[j][i] = $row[i]
      inc(j)
    mysql.FreeResult(sqlres)

iterator Rows*(db: TDbConn, query: TSqlQuery, 
               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
  ## same as `FastRows`, but slower and safe.
  for r in items(GetAllRows(db, query, args)): yield r

proc GetValue*(db: TDbConn, query: TSqlQuery, 
               args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
  ## executes the query and returns the result dataset's the first column 
  ## of the first row. Returns "" if the dataset contains no rows. This uses
  ## `FastRows`, so it inherits its fragile behaviour.
  result = ""
  for row in FastRows(db, query, args): 
    result = row[0]
    break

proc TryInsertID*(db: TDbConn, query: TSqlQuery, 
                  args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
  ## executes the query (typically "INSERT") and returns the 
  ## generated ID for the row or -1 in case of an error.
  var q = dbFormat(query, args)
  if mysql.RealQuery(db, q, q.len) != 0'i32: 
    result = -1'i64
  else:
    result = mysql.InsertId(db)
  
proc InsertID*(db: TDbConn, query: TSqlQuery, 
               args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
  ## executes the query (typically "INSERT") and returns the 
  ## generated ID for the row.
  result = TryInsertID(db, query, args)
  if result < 0: dbError(db)

proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, 
                       args: varargs[string, `$`]): int64 {.
                       tags: [FReadDB, FWriteDb].} = 
  ## runs the query (typically "UPDATE") and returns the
  ## number of affected rows
  rawExec(db, query, args)
  result = mysql.AffectedRows(db)

proc Close*(db: TDbConn) {.tags: [FDb].} = 
  ## closes the database connection.
  if db != nil: mysql.Close(db)

proc Open*(connection, user, password, database: string): TDbConn {.
  tags: [FDb].} =
  ## opens a database connection. Raises `EDb` if the connection could not
  ## be established.
  result = mysql.Init(nil)
  if result == nil: dbError("could not open database connection") 
  if mysql.RealConnect(result, "", user, password, database, 
                       0'i32, nil, 0) == nil:
    var errmsg = $mysql.error(result)
    db_mysql.Close(result)
    dbError(errmsg)