Skip to content

Instantly share code, notes, and snippets.

@daurnimator
Last active December 10, 2015 19:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save daurnimator/4484437 to your computer and use it in GitHub Desktop.
Save daurnimator/4484437 to your computer and use it in GitHub Desktop.
My bash prompt
local ret_code , n_jobs = ...
ret_code = tonumber ( ret_code )
n_jobs = tonumber ( n_jobs ) or 0
local ffi = require "ffi"
ffi.cdef [[
typedef uint32_t uid_t;
uid_t geteuid(void);
int gethostname(char *name, size_t namelen);
char *getcwd(char *buf, size_t size);
void free(void *ptr);
]]
local HOST_NAME_MAX = 64
local function gethostname ( )
local buff = ffi.new ( "char[?]" , HOST_NAME_MAX )
assert ( ffi.C.gethostname ( buff , HOST_NAME_MAX ) == 0 )
return ffi.string ( buff )
end
local function getcwd ( )
local cwd = ffi.C.getcwd ( nil , 0 )
local str = ffi.string ( cwd )
ffi.C.free ( cwd )
return str
end
local getenv = os.getenv
local function cmd ( c )
local fd = io.popen ( c .. " 2> /dev/null" )
local ret = fd:read "*l"
fd:close ( )
return ret
end
local uid = ffi.C.geteuid()
local hostname = getenv "HOSTNAME" or gethostname()
local username = getenv "USER" or getenv "USERNAME" or ""
local home = getenv "HOME" or getenv "HOMEPATH"
local pwd = (getenv "PWD" or getcwd()):gsub("^"..home,"~")
local escapes = {
reset = 0 ;
bold = 1 ;
blink = 5 ;
fraktur = 20 ;
-- Colours
black = 30 ;
red = 31 ;
green = 32 ;
yellow = 33 ;
blue = 34 ;
magenta = 35 ;
cyan = 36 ;
white = 37 ;
}
-- \1 and \2 are undocumented features that cause bash to not count the characters inbetween as printable
-- (and hence will place the prompt at the correct location)
local function esc ( ... )
return "\1\27["..table.concat({...},";").."m\2"
end
local function set_title ( str )
io.write ( "\1\27]0;" , str , "\7\2" )
end
--set_title ( string.format ( "%s@%s %s" , username , hostname , pwd ) )
io.write (
esc(escapes.yellow),os.date("%m-%d %H:%M:%S "),
esc(escapes.reset,escapes.bold),username,
esc(escapes.reset),"@",
esc(escapes.green),hostname," ",
esc(escapes.bold,escapes.blue),pwd,
esc(escapes.reset)," "
)
local is_git = select(3, os.execute ( "git rev-parse --git-dir > /dev/null 2> /dev/null" )) == 0
if is_git then
local hash = cmd "git show --format=%h"
if hash then -- Hash is nil if currently not on a commit (e.g. new repo)
local status = io.popen "git status -sb"
local branch = status:read"*l":match("^## (.*)") -- First line is ## BRANCH NAME
local dirty = status:read"*l" -- If there are any uncommited changes they will follow
status:close()
local col = escapes.green
if dirty then
col = escapes.red
end
io.write(esc(col),"git:{",branch,":",hash,"} ")
else
io.write(esc(escapes.green),"git ")
end
end
local is_hg = select(3, os.execute ( "hg root > /dev/null 2> /dev/null" )) == 0
if is_hg then
local t = { }
local summary = io.popen "hg summary"
for line in summary:lines() do
local name , value = line:match("([^:]+): (.*)")
if name then
t [ name ] = value
end
end
summary:close()
local col = escapes.green
local hg_status = cmd ( "hg status -q" )
if hg_status then
col = escapes.red
elseif not t.update:match("(current)") then
col = escapes.yellow
end
io.write(esc(col),"hg:{",t.branch,":",t.parent:match(":(%x*)"),"} ")
end
if n_jobs ~= 0 then
io.write(esc(escapes.bold,escapes.cyan),n_jobs," jobs ")
end
io.write (esc(escapes.reset))
if ret_code and ret_code ~= 0 then
io.write(esc(escapes.bold,escapes.red),"exit=",ret_code," ")
end
io.write ( uid==0 and "#" or "$" , " ", esc(escapes.reset) ) -- Reset
PS1="\$(luajit ~/.bash_prompt.lua \$? \j)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment