priority -50

extends c

# We want to overwrite everything in parent ft.
priority -49

################################################################################
#                           Documentation Functions                            #
################################################################################

global !p

class Arg(object):
	def __init__(self, arg):
		self.arg = arg
		tmp = arg.split('=')[0].split()
		self.name = tmp[-1].strip()
		self.type = ' '.join(tmp[:len(tmp)-1])

	def __str__(self):
		return self.name

	def __unicode__(self):
		return self.name

	def get_type(self):
		return self.type

	def is_kwarg(self):
		return '=' in self.arg


def get_args(arglist):
	args = [Arg(arg) for arg in arglist.split(',') if len(arg.split()) >= 2]
	return args


def format_arg(arg):
		return " * \param %s [%s] TODO" % (arg, arg.get_type())


def write_docstring_args(args, snip):
	for arg in args:
		snip += format_arg(arg)


def write_method_docstring(t, snip, argi, reti):
	"""
	Writes a function docstring with the current style.

	:param t: The values of the placeholders
	:param snip: UltiSnips.TextObjects.SnippetUtil object instance
	"""
	snip.rv = ""
	args = get_args(t[argi])
	if args:
		write_docstring_args(args, snip)
	snip += r" * \return " + t[reti] +" TODO"


def write_constructor_docstring(t, snip):
	"""
	Writes a function docstring with the current style.

	:param t: The values of the placeholders
	:param snip: UltiSnips.TextObjects.SnippetUtil object instance
	"""
	snip.rv = ""
	snip >> 1
	args = get_args(t[2])
	if args:
		snip += '/**'
		write_docstring_args(args, snip)
		snip += ' */'


endglobal

################################################################################
#                              Helper Expressions                              #
################################################################################

## Input/Output
snippet cout "std::cout (cout)" b
std::cout << ${1} << std::endl;
endsnippet

snippet cin "std::cin (cin)" b
std::cin >> ${1};
endsnippet

snippet readfile "read file (readF)"
std::vector<char> v;
if (FILE *fp = fopen(${1:"filename"}, "r"))
{
	char buf[1024];
	while(size_t len = fread(buf, 1, sizeof(buf), fp))
		v.insert(v.end(), buf, buf + len);
	fclose(fp);
}
endsnippet

## Iteration
snippet beginend "$1.begin(), $1.end() (beginend)" i
${1:v}${1/^.*?(-)?(>)?$/(?2::(?1:>:.))/}begin(), $1${1/^.*?(-)?(>)?$/(?2::(?1:>:.))/}end()
endsnippet
snippet fore "foreach ... (fore)"
for (${1:auto} ${2:i} : ${3:container}) {
	${VISUAL}${4}
}
endsnippet
snippet iter "iteration ... (iter)"
for (${1:typename}::${2:const_iterator} ${3:iter} = ${4:container}.begin(); $3 != $4.end(); ++$3) {
	${VISUAL}${5}
}
endsnippet
snippet itera "auto-iteration ... (itera)"
for (auto ${1:i} = ${2:container}.begin(); $1 != $2.end(); ++$1) {
	${3:std::cout << *$1 << std::endl;}
}
endsnippet

## Lambdas
snippet ld "lambda (one-line) ... (ld)"
[${1}](${2}){${3}}
endsnippet
snippet lld "lambda (multi-line) ... (lld)"
[${1}](${2}){
	${3}
}
endsnippet

################################################################################
#                             Classes and Members                              #
################################################################################

snippet tp "template <typename ..> (template)"
template <typename ${1:_InputIter}>
endsnippet

snippet cl "class with documentation (class)" b
/**
 * \class ${1/(\w+).*/$1/} ${5:TODO}
 */
class ${1:`!p
snip.rv = ''.join(map(lambda x: x.capitalize(), snip.basename.split('_'))) or "classname"`}
{
 public:`!p write_constructor_docstring(t, snip)`
	${1/(\w+).*/$1/}(${2:/*arguments*/});
	virtual ~${1/(\w+).*/$1/}();

	${3:/* public methods */}

 private:
	${4:/* private methods */}

 private:
	${0:/* data */}
};
endsnippet

snippet clp "class with documentation and pointer defs (class)" b
/**
 * \class ${1/(\w+).*/$1/} ${5:TODO}
 */
class ${1:`!p
snip.rv = ''.join(map(lambda x: x.capitalize(), snip.basename.split('_'))) or "classname"`}
{
 public:
	typedef boost::shared_ptr<$1> Ptr;
	typedef boost::shared_ptr<$1 const> ConstPtr;

 public:`!p write_constructor_docstring(t, snip)`
	${1/(\w+).*/$1/}(${2:/*arguments*/});
	virtual ~${1/(\w+).*/$1/}();

	${3:/* public methods */}

 private:
	${4:/* private methods */}

 private:
	${0:/* data */}
};

typedef $1::Ptr $1Ptr;
typedef $1::ConstPtr $1ConstPtr;
endsnippet

snippet funh "method declaration with documentation" b
/**
 * \brief ${7:TODO}`!p write_method_docstring(t, snip, 4, 3)`
 */
${2:virtual }${3:void}
${1:memberFunction}(${4:/*arguments*/})${5: const}${6};
$0
endsnippet

snippet funm "method implementation with documentation" b
/**
 * \details TODO
 */
${3:void}
${1:`!p snip.rv = ''.join(map(lambda x: x.capitalize(), snip.basename.split('_'))) or "classname"`}::
${2:memberFunction}(${4:/*arguments*/})
{
	${VISUAL}${5}
}
$0
endsnippet

snippet ns "namespace .. (namespace)"
namespace${1/.+/ /m}${1:`!p snip.rv = snip.basename or "name"`}
{
	${VISUAL}${0}
}  // namespace $1
endsnippet

################################################################################
#                                   Pointers                                   #
################################################################################

snippet ptr "boost::shared_ptr (ptr)" i
boost::shared_ptr<${1:Type}> ${2}
endsnippet

snippet new "new boost:shared_ptr (new)"
boost::shared_ptr<$1> ${2:ptr}( new ${1:Type}(${3:/* arguments */}) );
endsnippet

################################################################################
#                       Type Abbreviations and Typedefs                        #
################################################################################

snippet td "typedef"
typedef ${1:Type} ${2:CustomType};
endsnippet

snippet str "std::string (str)" i
std::string ${1}
endsnippet

## STL Collections
snippet vec "std::vector (vec)" i
std::vector<${1:int}> ${2}
endsnippet
snippet ar "std::array (arr)" i
std::array<${1:int}, ${2:N}> ${3}
endsnippet
snippet deq "std::deque (deq)" i
std::deque<${1:int}> ${2}
endsnippet
snippet fli "std::forward_list (fli)" i
std::forward_list<${1:T}> ${2}
endsnippet
snippet li "std::list (li)" i
std::list<${1:T}> ${2}
endsnippet
snippet set "std::set (set)" i
std::set<${1:int}> ${2}
endsnippet
snippet map "std::map (map)" i
std::map<${1:Key}, ${2:T}> ${3}
endsnippet
snippet mset "std::multiset (mset)" i
std::multiset<${1:T}> ${2}
endsnippet
snippet dict "std::multimap (dict)" i
std::multimap<${1:Key}, ${2:T}> ${3}
endsnippet
snippet uset "std::unordered_set (uset)" i
std::unordered_set<${1:T}> ${2}
endsnippet
snippet umap "std::unordered_map (umap)" i
std::unordered_map<${1:Key}, ${2:T}> ${3}
endsnippet
snippet umset "std::unordered_multiset (umset)" i
std::unordered_multiset<${1:T}> ${2}
endsnippet
snippet ummap "std::unordered_multimap (ummap)" i
std::unordered_multimap<${1:Key}, ${2:T}> ${3}
endsnippet
snippet st "std::stack (sta)" i
std::stack<${1:T}> ${2}
endsnippet
snippet qu "std::queue (qu)" i
std::queue<${1:T}> ${2}
endsnippet
snippet pqu "std::priority_queue (pqu)" i
std::priority_queue<${1:T}> ${2}
endsnippet

snippet V "Vector (V)" i
${1:Type}Vector
endsnippet
snippet CV "ConstVector (CV)" i
${1:Type}ConstVector
endsnippet
snippet L "List (L)" i
${1:Type}List
endsnippet
snippet CL "ConstList (CL)" i
${1:Type}ConstList
endsnippet
snippet PV "PtrVector (PV)" i
${1:Type}PtrVector
endsnippet
snippet CPV "ConstPtrVector (CPV)" i
${1:Type}ConstPtrVector
endsnippet
snippet PL "PtrList (PL)" i
${1:Type}PtrList
endsnippet
snippet CPL "ConstPtrList (CPL)" i
${1:Type}ConstPtrList
endsnippet

snippet VP "VectorPtr (VP)" i
${1:Type}VectorPtr
endsnippet
snippet CVP "ConstVectorPtr (CVP)" i
${1:Type}ConstVectorPtr
endsnippet
snippet LP "ListPtr (LP)" i
${1:Type}ListPtr
endsnippet
snippet CLP "ConstListPtr (CLP)" i
${1:Type}ConstListPtr
endsnippet
snippet PVP "PtrVectorPtr (PVP)" i
${1:Type}PtrVectorPtr
endsnippet
snippet CPVP "ConstPtrVectorPtr (CPVP)" i
${1:Type}ConstPtrVectorPtr
endsnippet
snippet PLP "PtrListPtr (PLP)" i
${1:Type}PtrListPtr
endsnippet
snippet CPLP "ConstPtrListPtr (CPLP)" i
${1:Type}ConstPtrListPtr
endsnippet

snippet VCP "VectorConstPtr (VP)" i
${1:Type}VectorConstPtr
endsnippet
snippet CVCP "ConstVectorConstPtr (CVP)" i
${1:Type}ConstVectorConstPtr
endsnippet
snippet LCP "ListConstPtr (LP)" i
${1:Type}ListConstPtr
endsnippet
snippet CLCP "ConstListConstPtr (CLP)" i
${1:Type}ConstListConstPtr
endsnippet
snippet PVCP "PtrVectorConstPtr (PVP)" i
${1:Type}PtrVectorConstPtr
endsnippet
snippet CPVCP "ConstPtrVectorConstPtr (CPVP)" i
${1:Type}ConstPtrVectorConstPtr
endsnippet
snippet PLCP "PtrListConstPtr (PLCP)" i
${1:Type}PtrListConstPtr
endsnippet
snippet CPLCP "ConstPtrListConstPtr (CPLCP)" i
${1:Type}ConstPtrListConstPtr
endsnippet

snippet Vt "typedef Vector (tV)" b
typedef std::vector<$1> ${1:Type}Vector;
endsnippet
snippet CVt "typedef ConstVector (tCV)" b
typedef std::vector<$1 const> ${1:Type}ConstVector;
endsnippet
snippet Lt "typedef List (tL)" b
typedef std::list<$1> ${1:Type}List;
endsnippet
snippet CLt "typedef ConstList (tCL)" b
typedef std::list<$1 const> ${1:Type}ConstList;
endsnippet
snippet PVt "typedef PtrVector (tPV)" b
typedef std::vector<$1Ptr> ${1:Type}PtrVector;
endsnippet
snippet CPVt "typedef ConstPtrVector (tCPV)" b
typedef std::vector<$1ConstPtr> ${1:Type}ConstPtrVector;
endsnippet
snippet PLt "typedef PtrList (tPL)" b
typedef std::list<$1Ptr> ${1:Type}PtrList;
endsnippet
snippet CPLt "typedef ConstPtrList (tCPL)" b
typedef std::list<$1ConstPtr> ${1:Type}ConstPtrList;
endsnippet

snippet VPt "typedef VectorPtr (tVP)" b
typedef boost::shared_ptr<$1Vector> ${1:Type}VectorPtr;
endsnippet
snippet CVPt "typedef ConstVectorPtr (tCVP)" b
typedef boost::shared_ptr<$1ConstVector> ${1:Type}ConstVectorPtr;
endsnippet
snippet LPt "typedef ListPtr (tLP)" b
typedef boost::shared_ptr<$1List> ${1:Type}ListPtr;
endsnippet
snippet CLPt "typedef ConstListPtr (tCLP)" b
typedef boost::shared_ptr<$1ConstList> ${1:Type}ConstListPtr;
endsnippet
snippet PVPt "typedef PtrVectorPtr (tPVP)" b
typedef boost::shared_ptr<$1PtrVector> ${1:Type}PtrVectorPtr;
endsnippet
snippet CPVPt "typedef ConstPtrVectorPtr (tCPVP)" b
typedef boost::shared_ptr<$1ConstPtrVector> ${1:Type}ConstPtrVectorPtr;
endsnippet
snippet PLPt "typedef PtrListPtr (tPLP)" b
typedef boost::shared_ptr<$1PtrList> ${1:Type}PtrListPtr;
endsnippet
snippet CPLPt "typedef ConstPtrListPtr (tCPLP)" b
typedef boost::shared_ptr<$1ConstPtrList> ${1:Type}ConstPtrListPtr;
endsnippet

snippet VCPt "typedef VectorConstPtr (tVCP)" b
typedef boost::shared_ptr<$1Vector const> ${1:Type}VectorConstPtr;
endsnippet
snippet CVCPt "typedef ConstVectorConstPtr (tCVCP)" b
typedef boost::shared_ptr<$1ConstVector const> ${1:Type}ConstVectorConstPtr;
endsnippet
snippet LCPt "typedef ListConstPtr (tLCP)" b
typedef boost::shared_ptr<$1List const> ${1:Type}ListConstPtr;
endsnippet
snippet CLCPt "typedef ConstListConstPtr (tCLCP)" b
typedef boost::shared_ptr<$1ConstList const> ${1:Type}ConstListConstPtr;
endsnippet
snippet PVCPt "typedef PtrVectorConstPtr (tPVCP)" b
typedef boost::shared_ptr<$1PtrVector const> ${1:Type}PtrVectorConstPtr;
endsnippet
snippet CPVCPt "typedef ConstPtrVectorConstPtr (tCPVCP)" b
typedef boost::shared_ptr<$1ConstPtrVector const> ${1:Type}ConstPtrVectorConstPtr;
endsnippet
snippet PLCPt "typedef PtrListConstPtr (tPLCP)" b
typedef boost::shared_ptr<$1PtrList const> ${1:Type}PtrListConstPtr;
endsnippet
snippet CPLCPt "typedef ConstPtrListConstPtr (tCPLCP)" b
typedef boost::shared_ptr<$1ConstPtrList const> ${1:Type}ConstPtrListConstPtr;
endsnippet


snippet cla "An entire .h generator" b
#ifndef ${2:`!v substitute(vim_snippets#Filename('$1_H','ClassName'),'.*','\U&\E','')`}
#define $2

class ${1:`!v substitute(substitute(vim_snippets#Filename('$1','ClassName'),'^.','\u&',''), '_\(\w\)', '\u\1', 'g')`}
{
private:
	${3}

public:
	$1();
	virtual ~$1();
};

#endif /* $2 */
endsnippet
# vim:ft=snippets:
