#!/usr/bin/python
"""%prog [options]

Looks at /proc/meminfo and retrieves swap and memory information; 
* total, used and free swap;
* total, used, cached+buffers and free memory;

Please note that running the program without arguments will return nothing. 
You should specify one or more flags to output something."""

__author__="Pedro Venda (pjvenda at pjvenda org)"
__version__="1.0"
__date__="2006/08/25"
__copyright__ = "Copyright (c) 2006 Pedro Venda"
__license__="GPL"

import re

# file location
MEMINFO="/proc/meminfo"

def parse_file(filename):
	"""
Takes a file and looks for some regular expressions like MemFree, SwapUsed, etc.

Parses its values and returns a dictionary with them
"""

	# some regular expressions for searching and matching
	EXPR={	'free_swap':re.compile('^SwapFree.*'), \
		'total_swap':re.compile('^SwapTotal.*'), \
		'free_mem':re.compile('MemFree.*'), \
		'total_mem':re.compile('MemTotal.*'), \
		'cache_mem':re.compile('Cached.*'), \
		'buffer_mem':re.compile('Buffers.*'), \
		'number':re.compile('[0-9]+'), \
		}

	# open file
	fd=file(filename)
	# iterate through it
	for line in fd:
		# look for free swap
		if EXPR['free_swap'].match(line):
			free_swap=int(EXPR['number'].findall(line)[0])
		# look for total swap
		elif EXPR['total_swap'].match(line):
			total_swap=int(EXPR['number'].findall(line)[0])
		# look for free mem
		elif EXPR['free_mem'].match(line):
			free_mem=int(EXPR['number'].findall(line)[0])
		# look for total mem
		elif EXPR['total_mem'].match(line):
			total_mem=int(EXPR['number'].findall(line)[0])
		# look for buffer mem
		elif EXPR['cache_mem'].match(line):
			cache_mem=int(EXPR['number'].findall(line)[0])
		# look for cache mem
		elif EXPR['buffer_mem'].match(line):
			buffer_mem=int(EXPR['number'].findall(line)[0])
	# close file
	fd.close()
	return {'free_swap':free_swap, \
		'total_swap':total_swap, \
		'free_mem':free_mem, \
		'total_mem':total_mem, \
		'cache_mem':cache_mem, \
		'buffer_mem':buffer_mem, \
		}
		
# calculate some extra numbers
def compute_extra_values(meminfo):
	"""Calculates some values not explicitly in /proc/meminfo"""

	meminfo['used_swap']=meminfo['total_swap']-meminfo['free_swap']
	meminfo['cache_mem']=meminfo['cache_mem']+meminfo['buffer_mem']
	meminfo['used_mem']=meminfo['total_mem']-meminfo['free_mem']-meminfo['cache_mem']
	meminfo['free_mem']=meminfo['free_mem']+meminfo['cache_mem']

	return

# produce output
def produce_output(options,meminfo):
	"""Produces program output"""
	if options.swap_free:
		if not options.quiet:
			print "Swap Free:",meminfo['free_swap'],"Kb"
		else:
			print meminfo['free_swap']

	if options.swap_used:
		if not options.quiet:
			print "Swap Used:",meminfo['used_swap'],"Kb"
		else:
			print meminfo['used_swap']

	if options.swap_total:
		if not options.quiet:
			print "Swap Total:",meminfo['total_swap'],"Kb"
		else:
			print meminfo['total_swap']

	if options.mem_free:
		if not options.quiet:
			print "Memory Free:",meminfo['free_mem'],"Kb"
		else:
			print meminfo['free_mem']
	if options.mem_used:
		if not options.quiet:
			print "Memory Used:",meminfo['used_mem'],"Kb"
		else:
			print meminfo['used_mem']

	if options.mem_total:
		if not options.quiet:
			print "Memory Total:",meminfo['total_mem'],"Kb"
		else:
			print meminfo['total_mem']

	if options.mem_cache:
		if not options.quiet:
			print "Memory Cache+buffer:",meminfo['cache_mem'],"Kb"
		else:
			print meminfo['cache_mem']
	return

# prevent action if inadvertedly included
if __name__ == '__main__':
	# parse file and retrieve relevant info
	meminfo=parse_file(MEMINFO)
	
	# compute some values not directly in /proc/meminfo
	compute_extra_values(meminfo)

	from optparse import OptionParser

	# setup command line parser
	parser=OptionParser(usage=__doc__,version="%prog "+__version__)

	parser.add_option("--sf",action="store_true",dest="swap_free",help="show free swap space")
	parser.add_option("--su",action="store_true",dest="swap_used",help="show used swap space")
	parser.add_option("--st",action="store_true",dest="swap_total",help="show total swap space")

	parser.add_option("--mf",action="store_true",dest="mem_free",help="show free ram space")
	parser.add_option("--mu",action="store_true",dest="mem_used",help="show used ram space")
	parser.add_option("--mt",action="store_true",dest="mem_total",help="show total ram space")
	parser.add_option("--mc",action="store_true",dest="mem_cache",help="show cache+buffer ram space")

	parser.add_option("-q",action="store_true",dest="quiet",help="be quiet! show only output size")

	# parse command line arguments
	(options,args)=parser.parse_args()

	# display output according to command line flags
	produce_output(options,meminfo)

