<commit_before>"""
Copyright (c) 2008 Marian Tietz
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
"""

import time
from dbus import UInt64

config = None
gui = None
com = None

commands = {}

def parseInput(text):
	"""
		TODO: document
	"""
	if not text:
		return

	serverTab,channelTab = gui.tabs.getCurrentTabs()

	if text[0] != "/":
		if not channelTab:
			return
		com.sendMessage(serverTab.name, channelTab.name, text)
	elif text[:2] == "//":
		if not channelTab:
			return
		com.sendMessage(serverTab.name, channelTab.name, text[1:])
	else:
		list = text[1:].split(" ")
		cmd = list[0]

		if not cmd:
			return gui.myPrint("No command given.")
		elif not commands.has_key(cmd):
			if not serverTab:
				return gui.myPrint("No server active.")
			gui.myPrint("Unknown command '%s'; Forwarding raw." % (cmd))
			com.raw(serverTab.name, cmd.upper() + " ".join(list[1:]))

		else:
			commands[cmd](serverTab, channelTab, list[1:])

def makiConnect(currentServer, currentChannel, args):
	"""
		Connect to the given server.

		Usage: /connect <server>
	"""
	if not args:
		return gui.myPrint("Usage: /connect <servername>")

	com.connectServer(args[0])

def makiQuit(currentServer, currentChannel, args):
	"""
		Quit the given server with an optional reason.
		If no server is given, the current server is quit.

		Usage: /quit <server> [<reason>]
		       /quit [<reason>]
	"""
	if args:
		# /quit <server> [<reason>]
		if gui.tabs.searchTab(None, args[0]):
			com.quitServer(args[0], " ".join(args[1:]))
		else:
			# /quit [<reason>]
			if not currentServer:
				return gui.myPrint("Could not determine server.")
			com.quitServer(currentServer.name, " ".join(args))
	else:
		# /quit
		if not currentServer:
			return gui.myPrint("Could not determine server.")
		com.quitServer(currentServer.name,"")

def makiNick(currentServer, currentChannel, args):
	"""
		Change your current nick to the given nick.

		Usage: /nick <new nick>
	"""
	if not args:
		return gui.myPrint("Usage: /nick <new nick>")

	if not currentServer:
		return gui.myPrint("Can't determine my server.")

	com.nick(currentServer.name, args[0])

def makiPart(currentServer, currentChannel, args):
	"""
		Part the given channel with an optional reason.
		If no channel is given, the current channel is parted.

		Usage: /part <channel> [<reason>]
		       /part [<reason>]
	"""
	if args and currentServer:
		# /part <channel> [<reason>]
		if gui.tabs.searchTab(currentServer.name, args[0]):
			com.part(args[0], " ".join(args[1:]))
		else:
			# /part [<reason>]
			if not currentChannel:
				return gui.myPrint("Could not determine channel.")
			com.part(currentServer.name, currentChannel.name, " ".join(args))
	else:
		# /part
		if not currentChannel:
			return gui.myPrint("Could not determine channel.")
		com.part(currentServer.name, currentChannel.name,"")

def makiJoin(currentServer, currentChannel, args):
	"""
		Joins the given channel with the optional key.

		Usage: /join <channel> [<key>]
	"""
	if not currentServer:
		return gui.myPrint("Can't determine server.")

	if not args:
		return gui.myPrint("Usage: /join <channel> [<key>]")

	com.join(currentServer.name, args[0], " ".join(args[1:]))

def makiAction(currentServer, currentChannel, args):
	"""
		Sends an action in third person view.

		Usage: /me <text>

		Example: nemo types: /me giggles.
		Results in: nemo giggles.
	"""
	if not args:
		return gui.myPrint("Usage: /me <text>")

	if not currentChannel:
		return gui.myPrint("Can't find active channel.")

	com.action(currentServer.name, currentChannel.name, " ".join(args))

def makiKick(currentServer, currentTab, args):
	"""
		Kick the given user with an optional reason from the
		current channel.

		Usage: /kick <user> [<reason>]
	"""
	if not args:
		return gui.myPrint("Usage: /kick <user> [<reason>]")

	if not currentTab or not currentTab.is_channel():
		return gui.myPrint("You're not on a channel")

	com.kick(currentServer.name, currentTab.name, args[0], " ".join(args[1:]))

def makiMode(currentServer, currentChannel, args):
	"""
		Sets a mode on the target.

		Usage: /mode <target> (+|-)<mode> [<param>]

		Example: /mode #xesio +o nemo
		OR:      /mode nemo +x
		OR:      /mode #xesio +m
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /mode <target> (+|-)<mode> [<param>]")

	if not currentServer:
		return gui.myPrint("Could not determine server.")

	if len(args) > 2:
		# a parameter is given
		param = " ".join(args[2:])

	com.mode(currentServer.name, args[0], "%s %s" % (args[1],param))

def makiTopic(serverTab, channelTab, args):
	"""
		Sets the topic in the current channel.

		Usage: /topic <text>
	"""
	if not args:
		return gui.myPrint("Usage: /topic <text>")
	else:
		topic = " ".join(args)

	if not channelTab or not channelTab.is_channel():
		return gui.myPrint("No channel active.")

	com.setTopic(serverTab.name, channelTab.name, topic)

def makiAway(serverTab, channelTab, args):
	"""
		Sets you away with an optional reason.

		Usage: /away [<reason>]
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")

	com.setAway(serverTab.name, " ".join(args))

def makiBack(serverTab, channelTab, args):
	"""
		Sets you back from being away.

		Usage: /back
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")
	com.setBack(serverTab.name)

def makiNickserv(serverTab, channelTab, args):
	"""
		Authenticates you at NickServ with
		the data stored in maki.

		Usage: /nickserv
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")

	com.nickserv(server)

def makiCTCP(serverTab, channelTab, args):
	"""
		Sends a CTCP message to the given target.

		Usage: /ctcp <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /ctcp <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.ctcp(serverTab.name, args[0], args[1])

def makiNotice(serverTab, channelTab, args):
	"""
		Sends a notice to the given target.
		The difference between /ctcp and /notice
		is, that /ctcp sends directly to the user
		while /notice sends the message over the
		server.

		Usage: /notice <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /notice <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.notice(serverTab.name, args[0], " ".join(args[1:]))

def makiMessage(serverTab, channelTab, args):
	"""
		Sends a message (PRIVMSG) to the target.
		The target can be a channel or a user.

		Usage: /msg <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /msg <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.sendMessage(serverTab.name, args[0], " ".join(args[1]))

def makiOper(serverTab, channelTab, args):
	"""
		Authentificate as IRC operator.

		Usage: /oper <user> <pass>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /oper <user> <pass>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.oper(serverTab.name, args[0], " ".join(args[1:]))

def makiKill(serverTab, channelTab, args):
	"""
		Kill a user on the network with an optional reason.

		Usage: /kill <user> [<reason>]
	"""
	if not args or len(args) < 1:
		return gui.myPrint("Usage: /kill <user> [<reason>]")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.kill(serverTab.name, args[0], " ".join(args[1:]))

def makiList(serverTab, channelTab, args):
	"""
		Start a channel listing.
		If channel is given, only the channel
		is listed.

		Usage: /list [<channel>]
	"""
	if not serverTab:
		return gui.myPrint("Could not determine server.")

	try:
		# channel specific listing?
		channel = args[0]
	except IndexError:
		# start a complete list..
		channel = ""

	gui.serverPrint(time.time(), serverTab.name, "Start of list.")
	com.list(serverTab.name, channel)

def makiRaw(serverTab, channelTab, args):
	"""
		Sends a command with optional args to maki
		which acts only as forwarder. The command
		goes unchanged to the server.

		Usage: /raw <command> [<further text>]
	"""
	if not args:
		return gui.myPrint("Usage: /raw <command>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	# upper-case the command
	args[0] = args[0].upper()

	com.raw(server, " ".join(args))

def makiWhois(currentServer, currentChannel, args):
	"""
		Query a user's identity on the current server.

		Usage: /whois <user mask>
	"""
	if not args:
		return gui.myPrint("No server activated.")

	com.sushi.whois(currentServer.name, args[0])

""" TEKKA USER COMMANDS """

def tekkaQuery(currentServer, currentTab, args):
	"""
		Starts a query dialog with the given user.

		Usage: /query <nick>
	"""
	if not args:
		return gui.myPrint("Usage: /query <nick>")

	if not currentServer:
		return gui.myPrint("Can't determine server.")

	nick = args[0]

	if not gui.tabs.searchTab(currentServer.name, nick):
		# no query started

		tab = gui.tabs.createQuery(currentServer.name, nick)
		tab.connected = True
		gui.tabs.addTab(currentServer.name, tab)

		output = tab.buffer

		# fetch and write history to query (if any)
		for line in com.fetchLog(currentServer.name, nick,
			UInt64(config.get("chatting","last_log_lines","10"))):

			output.insertHTML(output.get_end_iter(),
				"%s" % gui.escape(line))

def tekkaClear(currentServer, currentTab, args):
	"""
		Clears the output of the current channel.

		Usage: /clear
	"""
	if currentTab: currentTab.buffer.set_text("")
	elif currentServer: currentServer.buffer.set_text("")

def tekkaHelp(currentServer, currentTab, args):
	"""
		Prints the doc-string of the given command.

		Usage: /help <command>
	"""
	if not args:
		return gui.myPrint("Usage: /help <command>")
	if commands.has_key(args[0]):
		gui.myPrint(commands[args[0]].__doc__.replace("\t",""))
	else:
		gui.myPrint("No help for %s available." % (args[0]))

def addCommand(command, function):
	"""
		Add a command.
		Returns True on success, otherwise False.
	"""
	global commands

	if commands.has_key(command):
		return False

	commands[command] = function

	return True

def removeCommand(command):
	"""
		Removes a command.
		Returns True on success, otherwise False.
	"""
	global commands

	if commands.has_key(command):
		del commands[command]
		return True

	return False

def setup(_config, _gui, _com):
	"""
		Setup the command module.
		  * Set modules
		  * Set command mapping
	"""
	global config, gui, com, commands

	config = _config
	gui = _gui
	com = _com

	commands = {
		"connect" : makiConnect,
		"nick" : makiNick,
		"part" : makiPart,
		"join" : makiJoin,
			"j" : makiJoin,
		"me"   : makiAction,
		"kick" : makiKick,
		"mode" : makiMode,
		"topic": makiTopic,
		"quit" : makiQuit,
		"away" : makiAway,
		"back" : makiBack,
	"nickserv" : makiNickserv,
		"ctcp" : makiCTCP,
		"notice" : makiNotice,
		"msg" : makiMessage,
		"oper" : makiOper,
		"kill" : makiKill,
		"list" : makiList,
		"raw" : makiRaw,
		"whois" : makiWhois,
		"query": tekkaQuery,
		"clear": tekkaClear,
		"help": tekkaHelp
	}
<commit_msg>Fix /mode.<commit_after>"""
Copyright (c) 2008 Marian Tietz
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
"""

import time
from dbus import UInt64

config = None
gui = None
com = None

commands = {}

def parseInput(text):
	"""
		TODO: document
	"""
	if not text:
		return

	serverTab,channelTab = gui.tabs.getCurrentTabs()

	if text[0] != "/":
		if not channelTab:
			return
		com.sendMessage(serverTab.name, channelTab.name, text)
	elif text[:2] == "//":
		if not channelTab:
			return
		com.sendMessage(serverTab.name, channelTab.name, text[1:])
	else:
		list = text[1:].split(" ")
		cmd = list[0]

		if not cmd:
			return gui.myPrint("No command given.")
		elif not commands.has_key(cmd):
			if not serverTab:
				return gui.myPrint("No server active.")
			gui.myPrint("Unknown command '%s'; Forwarding raw." % (cmd))
			com.raw(serverTab.name, cmd.upper() + " ".join(list[1:]))

		else:
			commands[cmd](serverTab, channelTab, list[1:])

def makiConnect(currentServer, currentChannel, args):
	"""
		Connect to the given server.

		Usage: /connect <server>
	"""
	if not args:
		return gui.myPrint("Usage: /connect <servername>")

	com.connectServer(args[0])

def makiQuit(currentServer, currentChannel, args):
	"""
		Quit the given server with an optional reason.
		If no server is given, the current server is quit.

		Usage: /quit <server> [<reason>]
		       /quit [<reason>]
	"""
	if args:
		# /quit <server> [<reason>]
		if gui.tabs.searchTab(None, args[0]):
			com.quitServer(args[0], " ".join(args[1:]))
		else:
			# /quit [<reason>]
			if not currentServer:
				return gui.myPrint("Could not determine server.")
			com.quitServer(currentServer.name, " ".join(args))
	else:
		# /quit
		if not currentServer:
			return gui.myPrint("Could not determine server.")
		com.quitServer(currentServer.name,"")

def makiNick(currentServer, currentChannel, args):
	"""
		Change your current nick to the given nick.

		Usage: /nick <new nick>
	"""
	if not args:
		return gui.myPrint("Usage: /nick <new nick>")

	if not currentServer:
		return gui.myPrint("Can't determine my server.")

	com.nick(currentServer.name, args[0])

def makiPart(currentServer, currentChannel, args):
	"""
		Part the given channel with an optional reason.
		If no channel is given, the current channel is parted.

		Usage: /part <channel> [<reason>]
		       /part [<reason>]
	"""
	if args and currentServer:
		# /part <channel> [<reason>]
		if gui.tabs.searchTab(currentServer.name, args[0]):
			com.part(args[0], " ".join(args[1:]))
		else:
			# /part [<reason>]
			if not currentChannel:
				return gui.myPrint("Could not determine channel.")
			com.part(currentServer.name, currentChannel.name, " ".join(args))
	else:
		# /part
		if not currentChannel:
			return gui.myPrint("Could not determine channel.")
		com.part(currentServer.name, currentChannel.name,"")

def makiJoin(currentServer, currentChannel, args):
	"""
		Joins the given channel with the optional key.

		Usage: /join <channel> [<key>]
	"""
	if not currentServer:
		return gui.myPrint("Can't determine server.")

	if not args:
		return gui.myPrint("Usage: /join <channel> [<key>]")

	com.join(currentServer.name, args[0], " ".join(args[1:]))

def makiAction(currentServer, currentChannel, args):
	"""
		Sends an action in third person view.

		Usage: /me <text>

		Example: nemo types: /me giggles.
		Results in: nemo giggles.
	"""
	if not args:
		return gui.myPrint("Usage: /me <text>")

	if not currentChannel:
		return gui.myPrint("Can't find active channel.")

	com.action(currentServer.name, currentChannel.name, " ".join(args))

def makiKick(currentServer, currentTab, args):
	"""
		Kick the given user with an optional reason from the
		current channel.

		Usage: /kick <user> [<reason>]
	"""
	if not args:
		return gui.myPrint("Usage: /kick <user> [<reason>]")

	if not currentTab or not currentTab.is_channel():
		return gui.myPrint("You're not on a channel")

	com.kick(currentServer.name, currentTab.name, args[0], " ".join(args[1:]))

def makiMode(currentServer, currentChannel, args):
	"""
		Sets a mode on the target.

		Usage: /mode <target> (+|-)<mode> [<param>]

		Example: /mode #xesio +o nemo
		OR:      /mode nemo +x
		OR:      /mode #xesio +m
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /mode <target> (+|-)<mode> [<param>]")

	if not currentServer:
		return gui.myPrint("Could not determine server.")

	if len(args) > 2:
		# a parameter is given
		com.mode(currentServer.name, args[0], "%s %s" % (args[1], " ".join(args[2:])))
	else:
		com.mode(currentServer.name, args[0], args[1])

def makiTopic(serverTab, channelTab, args):
	"""
		Sets the topic in the current channel.

		Usage: /topic <text>
	"""
	if not args:
		return gui.myPrint("Usage: /topic <text>")
	else:
		topic = " ".join(args)

	if not channelTab or not channelTab.is_channel():
		return gui.myPrint("No channel active.")

	com.setTopic(serverTab.name, channelTab.name, topic)

def makiAway(serverTab, channelTab, args):
	"""
		Sets you away with an optional reason.

		Usage: /away [<reason>]
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")

	com.setAway(serverTab.name, " ".join(args))

def makiBack(serverTab, channelTab, args):
	"""
		Sets you back from being away.

		Usage: /back
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")
	com.setBack(serverTab.name)

def makiNickserv(serverTab, channelTab, args):
	"""
		Authenticates you at NickServ with
		the data stored in maki.

		Usage: /nickserv
	"""
	if not serverTab:
		return gui.myPrint("Can't determine server.")

	com.nickserv(server)

def makiCTCP(serverTab, channelTab, args):
	"""
		Sends a CTCP message to the given target.

		Usage: /ctcp <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /ctcp <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.ctcp(serverTab.name, args[0], args[1])

def makiNotice(serverTab, channelTab, args):
	"""
		Sends a notice to the given target.
		The difference between /ctcp and /notice
		is, that /ctcp sends directly to the user
		while /notice sends the message over the
		server.

		Usage: /notice <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /notice <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.notice(serverTab.name, args[0], " ".join(args[1:]))

def makiMessage(serverTab, channelTab, args):
	"""
		Sends a message (PRIVMSG) to the target.
		The target can be a channel or a user.

		Usage: /msg <target> <message>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /msg <target> <message>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.sendMessage(serverTab.name, args[0], " ".join(args[1]))

def makiOper(serverTab, channelTab, args):
	"""
		Authentificate as IRC operator.

		Usage: /oper <user> <pass>
	"""
	if not args or len(args) < 2:
		return gui.myPrint("Usage: /oper <user> <pass>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.oper(serverTab.name, args[0], " ".join(args[1:]))

def makiKill(serverTab, channelTab, args):
	"""
		Kill a user on the network with an optional reason.

		Usage: /kill <user> [<reason>]
	"""
	if not args or len(args) < 1:
		return gui.myPrint("Usage: /kill <user> [<reason>]")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	com.kill(serverTab.name, args[0], " ".join(args[1:]))

def makiList(serverTab, channelTab, args):
	"""
		Start a channel listing.
		If channel is given, only the channel
		is listed.

		Usage: /list [<channel>]
	"""
	if not serverTab:
		return gui.myPrint("Could not determine server.")

	try:
		# channel specific listing?
		channel = args[0]
	except IndexError:
		# start a complete list..
		channel = ""

	gui.serverPrint(time.time(), serverTab.name, "Start of list.")
	com.list(serverTab.name, channel)

def makiRaw(serverTab, channelTab, args):
	"""
		Sends a command with optional args to maki
		which acts only as forwarder. The command
		goes unchanged to the server.

		Usage: /raw <command> [<further text>]
	"""
	if not args:
		return gui.myPrint("Usage: /raw <command>")

	if not serverTab:
		return gui.myPrint("Could not determine server.")

	# upper-case the command
	args[0] = args[0].upper()

	com.raw(server, " ".join(args))

def makiWhois(currentServer, currentChannel, args):
	"""
		Query a user's identity on the current server.

		Usage: /whois <user mask>
	"""
	if not args:
		return gui.myPrint("No server activated.")

	com.sushi.whois(currentServer.name, args[0])

""" TEKKA USER COMMANDS """

def tekkaQuery(currentServer, currentTab, args):
	"""
		Starts a query dialog with the given user.

		Usage: /query <nick>
	"""
	if not args:
		return gui.myPrint("Usage: /query <nick>")

	if not currentServer:
		return gui.myPrint("Can't determine server.")

	nick = args[0]

	if not gui.tabs.searchTab(currentServer.name, nick):
		# no query started

		tab = gui.tabs.createQuery(currentServer.name, nick)
		tab.connected = True
		gui.tabs.addTab(currentServer.name, tab)

		output = tab.buffer

		# fetch and write history to query (if any)
		for line in com.fetchLog(currentServer.name, nick,
			UInt64(config.get("chatting","last_log_lines","10"))):

			output.insertHTML(output.get_end_iter(),
				"%s" % gui.escape(line))

def tekkaClear(currentServer, currentTab, args):
	"""
		Clears the output of the current channel.

		Usage: /clear
	"""
	if currentTab: currentTab.buffer.set_text("")
	elif currentServer: currentServer.buffer.set_text("")

def tekkaHelp(currentServer, currentTab, args):
	"""
		Prints the doc-string of the given command.

		Usage: /help <command>
	"""
	if not args:
		return gui.myPrint("Usage: /help <command>")
	if commands.has_key(args[0]):
		gui.myPrint(commands[args[0]].__doc__.replace("\t",""))
	else:
		gui.myPrint("No help for %s available." % (args[0]))

def addCommand(command, function):
	"""
		Add a command.
		Returns True on success, otherwise False.
	"""
	global commands

	if commands.has_key(command):
		return False

	commands[command] = function

	return True

def removeCommand(command):
	"""
		Removes a command.
		Returns True on success, otherwise False.
	"""
	global commands

	if commands.has_key(command):
		del commands[command]
		return True

	return False

def setup(_config, _gui, _com):
	"""
		Setup the command module.
		  * Set modules
		  * Set command mapping
	"""
	global config, gui, com, commands

	config = _config
	gui = _gui
	com = _com

	commands = {
		"connect" : makiConnect,
		"nick" : makiNick,
		"part" : makiPart,
		"join" : makiJoin,
			"j" : makiJoin,
		"me"   : makiAction,
		"kick" : makiKick,
		"mode" : makiMode,
		"topic": makiTopic,
		"quit" : makiQuit,
		"away" : makiAway,
		"back" : makiBack,
	"nickserv" : makiNickserv,
		"ctcp" : makiCTCP,
		"notice" : makiNotice,
		"msg" : makiMessage,
		"oper" : makiOper,
		"kill" : makiKill,
		"list" : makiList,
		"raw" : makiRaw,
		"whois" : makiWhois,
		"query": tekkaQuery,
		"clear": tekkaClear,
		"help": tekkaHelp
	}
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
CGI script that takes takes a POST to the address ./add_comment (normally from
a comment form) and sends that comment formatted in yaml to the email address
set in COMMENT_EMAIL.

The resulting yaml file is meant to be used with Jekyll::StaticComments. See
https://github.com/mpalmer/jekyll-static-comments/
http://theshed.hezmatt.org/jekyll-static-comments/
"""

import web
import cgi
import time
import os, os.path
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# config
COMMENT_EMAIL = "blog@example.com"
MAX_SIZE = 1024
MAX_SIZE_COMMENT = 102400

URLS = (
    '/add_comment', 'CommentHandler'
)

def is_test():
    """
    Returns true iff the environment variable WEBPY_ENV is set to "test".
    """
    webpy_env = os.environ.get('WEBPY_ENV', '')
    return webpy_env == 'test'

class CommentHandler:
    """
    Class meant to be used by web.py.
    Handles POST requests in the POST method
    """
    DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
    ACK_MSG = """
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">

            <meta http-equiv="content-type" content="text/html; charset=utf-8" />
            <meta http-equiv="refresh" content="5;url=%(return_url)s" />
            <title>Comment Received</title>

Comment Received

Thank you for your comment. It will be reviewed and published shortly.

You are now returning to the page you were on. Click the link if you are not redirected automatically.

%(return_url)s

    """
    ERROR_MSG = """
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">

            <meta http-equiv="content-type" content="text/html; charset=utf-8" />
            <title>Problem with input</title>

Error!

The following error was detected:

        %(error_msg)

    """
    SMTPCONF = {
        'host': 'localhost',
        'port': 1025
    }
    def POST(self):
        """
        Handle a POST request: gets its content, transforms it into yaml, email
        the result and returns a confirmation page.
        """
        try:
            input_ = web.input()
        except ValueError:
            referer = web.ctx.env.get('HTTP_REFERER', '/')
            return self.ERROR_MSG % {
                'error_msg': "Input is too big, you should write less! Hit the"
                    " back button and try again.",
                'return_url': referer
            }
        comment = {
            'author_ip': web.ctx.ip,
            'date_gmt': time.strftime(self.DATE_FORMAT, time.gmtime()),
            'date': time.strftime(self.DATE_FORMAT, time.localtime())
        }
        comment.update(self._input_data_iterator(input_))
        self._email_comment(comment, COMMENT_EMAIL)
        web.header('Content-Type', 'text/html')
        return self.ACK_MSG % {'return_url': input_.return_url}

    def _sanitize_field(self, data_, max_size=None):
        """
        Sanitize a string for use as a yaml value.
        """
        if max_size is not None:
            data = data_[:max_size]
        else:
            data = data_
        return data.replace("'", "").replace('\n', '\n  ')

    def _input_data_iterator(self, input_):
        """
        Transforms the POST input as returned by web.input() into a dictionary.
        This only keeps the keys that we are interested, truncates values to a
        maximum size and sanitizes the values.
        """
        keys = ( 'author', 'author_email', 'author_url', 'content', 'post_id')
        for key in keys:
            if hasattr(input_, key):
                max_size = MAX_SIZE
                if key == 'content':
                    max_size = MAX_SIZE_COMMENT
                value = self._sanitize_field(getattr(input_, key), max_size)
                yield (key, value)

    def _yml_from_dict(self, d):
        """
        Generates a yaml string from a dict
        """
        s = u""
        for item in d.iteritems():
            s += u"%s: '%s'\n" % item
        return s

    def _file_name(self, comment):
        """
        Generates a suitable file name for a comment
        """
        return comment['date_gmt'].replace(' ', '_') + '.yaml'

    def _email_comment(self, comment, email):
        """
        Send a comment by email
        """
        comment_string = self._yml_from_dict(comment)
        comment_string = comment_string.encode('UTF-8')
        comment_attachment = MIMEText(comment_string,
                                      #_subtype='x-yaml',
                                      _charset='UTF-8')
        comment_attachment.add_header('Content-Disposition', 'inline',
                                      filename=self._file_name(comment))

        message = MIMEMultipart()
        message['Subject'] = "[blogcomment] New comment from %s on %s" % (
                                                      comment['author_email'],
                                                      comment['post_id'])
        message['From'] = 'noreply@emont.org'
        message['To'] = email
        message.attach(MIMEText("A new comment has been posted!\n"))

        message.attach(comment_attachment)

        if not is_test():
            s = smtplib.SMTP(**self.SMTPCONF)
            s.sendmail(email, [email], message.as_string())
            s.quit()

# limit the size of POST requests to 10kb
cgi.maxlen = MAX_SIZE_COMMENT
app = web.application(URLS, globals())

if (not is_test()) and __name__ == "__main__":
    app.run()
<commit_msg>Declared some methods as static<commit_after>#!/usr/bin/env python
"""
CGI script that takes takes a POST to the address ./add_comment (normally from
a comment form) and sends that comment formatted in yaml to the email address
set in COMMENT_EMAIL.

The resulting yaml file is meant to be used with Jekyll::StaticComments. See
https://github.com/mpalmer/jekyll-static-comments/
http://theshed.hezmatt.org/jekyll-static-comments/
"""

import web
import cgi
import time
import os, os.path
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

# config
COMMENT_EMAIL = "blog@example.com"
MAX_SIZE = 1024
MAX_SIZE_COMMENT = 102400

URLS = (
    '/add_comment', 'CommentHandler'
)

def is_test():
    """
    Returns true iff the environment variable WEBPY_ENV is set to "test".
    """
    webpy_env = os.environ.get('WEBPY_ENV', '')
    return webpy_env == 'test'

class CommentHandler:
    """
    Class meant to be used by web.py.
    Handles POST requests in the POST method
    """
    DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
    ACK_MSG = """
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">

            <meta http-equiv="content-type" content="text/html; charset=utf-8" />
            <meta http-equiv="refresh" content="5;url=%(return_url)s" />
            <title>Comment Received</title>

Comment Received

Thank you for your comment. It will be reviewed and published shortly.

You are now returning to the page you were on. Click the link if you are not redirected automatically.

%(return_url)s

    """
    ERROR_MSG = """
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">

            <meta http-equiv="content-type" content="text/html; charset=utf-8" />
            <title>Problem with input</title>

Error!

The following error was detected:

        %(error_msg)

    """
    SMTPCONF = {
        'host': 'localhost',
        'port': 1025
    }
    def POST(self):
        """
        Handle a POST request: gets its content, transforms it into yaml, email
        the result and returns a confirmation page.
        """
        try:
            input_ = web.input()
        except ValueError:
            referer = web.ctx.env.get('HTTP_REFERER', '/')
            return self.ERROR_MSG % {
                'error_msg': "Input is too big, you should write less! Hit the"
                    " back button and try again.",
                'return_url': referer
            }
        comment = {
            'author_ip': web.ctx.ip,
            'date_gmt': time.strftime(self.DATE_FORMAT, time.gmtime()),
            'date': time.strftime(self.DATE_FORMAT, time.localtime())
        }
        comment.update(self._input_data_iterator(input_))
        self._email_comment(comment, COMMENT_EMAIL)
        web.header('Content-Type', 'text/html')
        return self.ACK_MSG % {'return_url': input_.return_url}

    @staticmethod
    def _sanitize_field(data_, max_size=None):
        """
        Sanitize a string for use as a yaml value.
        """
        if max_size is not None:
            data = data_[:max_size]
        else:
            data = data_
        return data.replace("'", "").replace('\n', '\n  ')

    def _input_data_iterator(self, input_):
        """
        Transforms the POST input as returned by web.input() into a dictionary.
        This only keeps the keys that we are interested, truncates values to a
        maximum size and sanitizes the values.
        """
        keys = ( 'author', 'author_email', 'author_url', 'content', 'post_id')
        for key in keys:
            if hasattr(input_, key):
                max_size = MAX_SIZE
                if key == 'content':
                    max_size = MAX_SIZE_COMMENT
                value = self._sanitize_field(getattr(input_, key), max_size)
                yield (key, value)

    @staticmethod
    def _yml_from_dict(d):
        """
        Generates a yaml string from a dict
        """
        s = u""
        for item in d.iteritems():
            s += u"%s: '%s'\n" % item
        return s

    @staticmethod
    def _file_name(comment):
        """
        Generates a suitable file name for a comment
        """
        return comment['date_gmt'].replace(' ', '_') + '.yaml'

    def _email_comment(self, comment, email):
        """
        Send a comment by email
        """
        comment_string = self._yml_from_dict(comment)
        comment_string = comment_string.encode('UTF-8')
        comment_attachment = MIMEText(comment_string,
                                      #_subtype='x-yaml',
                                      _charset='UTF-8')
        comment_attachment.add_header('Content-Disposition', 'inline',
                                      filename=self._file_name(comment))

        message = MIMEMultipart()
        message['Subject'] = "[blogcomment] New comment from %s on %s" % (
                                                      comment['author_email'],
                                                      comment['post_id'])
        message['From'] = 'noreply@emont.org'
        message['To'] = email
        message.attach(MIMEText("A new comment has been posted!\n"))

        message.attach(comment_attachment)

        if not is_test():
            s = smtplib.SMTP(**self.SMTPCONF)
            s.sendmail(email, [email], message.as_string())
            s.quit()

# limit the size of POST requests to 10kb
cgi.maxlen = MAX_SIZE_COMMENT
app = web.application(URLS, globals())

if (not is_test()) and __name__ == "__main__":
    app.run()
<|endoftext|>


<commit_before># Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from grammar_printer import GrammarPrinter

class Compiler(object):
    def __init__(self, grammar, classname):
        self.grammar = grammar
        self.classname = classname
        self.printer = GrammarPrinter(grammar)
        self.val = None
        self.err = None
        self.indent = 0
        self.shiftwidth = 4
        self.istr = ' ' * self.shiftwidth

    def walk(self):
        self.val = []
        self._ext('from new_parser_base import NewParserBase',
                  '',
                  '',
                  'class %s(NewParserBase):' % (self.classname))

        for rule_name, node in self.grammar.rules.items():
            docstring = self.printer._proc(node)
            self._indent()
            self._ext('',
                      'def _%s_(self):' % rule_name)
            self._indent()
            self._ext('""" %s """' % docstring)
            self._proc(node)
            self._dedent()
            self._dedent()

        if self.err:
            return None, self.err
        return '\n'.join(self.val) + '\n', None

    def _nyi(self, label):
        self._ext("# nyi - %s" % label)

    def _indent(self):
        self.indent += 1

    def _dedent(self):
        self.indent -= 1

    def _ext(self, *lines):
        for l in lines:
            self.val.append('%s%s' % (' ' * self.indent * self.shiftwidth, l))

    def _proc(self, node):
        node_type = node[0]
        fn = getattr(self, '_' + node_type + '_', None)
        if not fn:
            import pdb; pdb.set_trace()
        return fn(node)

    def _choice_(self, node):
        for i, choice in enumerate(node[1]):
            self._ext('def choice_%d():' % i)
            self._indent()
            self._proc(choice)
            self._dedent()
            self._ext('choice_%d()' % i)
            if i < len(node[1]) - 1:
                self._ext('if not self.err:',
                          self.istr + 'return',
                          '')

    def _seq_(self, node):
        for i, s in enumerate(node[1]):
            self._proc(s)
            if i < len(node[1]) - 1:
                self._ext('if self.err:',
                          self.istr + 'return',
                          '')

    def _label_(self, node):
        self._proc(node[1])
        self._ext('if not self.err:',
                  self.istr + 'v_%s = self.val' % node[2])

    def _post_(self, _node):
        return self._nyi('post')

    def _apply_(self, node):
        self._ext('self._%s_()' % node[1])
        self._return_on_err()

    def _action_(self, node):
        self._ext('return %s' % self._proc(node[1]))

    def _not_(self, node):
        self._proc(node[1])
        self._ext('if not self.err:',
                  self.istr + ' self.err = "not"',
                  self.istr + ' self.val = None',
                  self.istr + ' return')

    def _pred_(self, _node):
        return self._nyi('pred')

    def _lit_(self, node):
        self._ext('self._expect("%s")' % node[1])

    def _paren_(self, node):
        return self._proc(node[1])

    def _py_plus_(self, node):
        return "%s + %s" % (self._proc(node[1]), self._proc(node[2]))

    def _py_qual_(self, _node):
        return self._nyi('py_qual')

    def _py_lit_(self, node):
        return "'%s'" % node[1]

    def _py_var_(self, node):
        return 'v_%s' % node[1]

    def _py_num_(self, node):
        return node[1]

    def _py_arr_(self, _node):
        return self._nyi('py_arr')
<commit_msg>fix action, py_qual, py_arr<commit_after># Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from grammar_printer import GrammarPrinter

class Compiler(object):
    def __init__(self, grammar, classname):
        self.grammar = grammar
        self.classname = classname
        self.printer = GrammarPrinter(grammar)
        self.val = None
        self.err = None
        self.indent = 0
        self.shiftwidth = 4
        self.istr = ' ' * self.shiftwidth

    def walk(self):
        self.val = []
        self._ext('from new_parser_base import NewParserBase',
                  '',
                  '',
                  'class %s(NewParserBase):' % (self.classname))

        for rule_name, node in self.grammar.rules.items():
            docstring = self.printer._proc(node)
            self._indent()
            self._ext('',
                      'def _%s_(self):' % rule_name)
            self._indent()
            self._ext('""" %s """' % docstring)
            self._proc(node)
            self._dedent()
            self._dedent()

        if self.err:
            return None, self.err
        return '\n'.join(self.val) + '\n', None

    def _nyi(self, label):
        self._ext("# nyi - %s" % label)

    def _indent(self):
        self.indent += 1

    def _dedent(self):
        self.indent -= 1

    def _ext(self, *lines):
        for l in lines:
            self.val.append('%s%s' % (' ' * self.indent * self.shiftwidth, l))

    def _proc(self, node):
        node_type = node[0]
        fn = getattr(self, '_' + node_type + '_', None)
        if not fn:
            import pdb; pdb.set_trace()
        return fn(node)

    def _choice_(self, node):
        for i, choice in enumerate(node[1]):
            self._ext('def choice_%d():' % i)
            self._indent()
            self._proc(choice)
            self._dedent()
            self._ext('choice_%d()' % i)
            if i < len(node[1]) - 1:
                self._ext('if not self.err:',
                          self.istr + 'return',
                          '')

    def _seq_(self, node):
        for i, s in enumerate(node[1]):
            self._proc(s)
            if i < len(node[1]) - 1:
                self._ext('if self.err:',
                          self.istr + 'return',
                          '')

    def _label_(self, node):
        self._proc(node[1])
        self._ext('if not self.err:',
                  self.istr + 'v_%s = self.val' % node[2])

    def _post_(self, _node):
        return self._nyi('post')

    def _apply_(self, node):
        self._ext('self._%s_()' % node[1])

    def _action_(self, node):
        self._ext('self.val = %s' % self._proc(node[1]),
                  'self.err = None')

    def _not_(self, node):
        self._proc(node[1])
        self._ext('if not self.err:',
                  self.istr + ' self.err = "not"',
                  self.istr + ' self.val = None',
                  self.istr + ' return')

    def _pred_(self, _node):
        return self._nyi('pred')

    def _lit_(self, node):
        self._ext('self._expect("%s")' % node[1])

    def _paren_(self, node):
        return self._proc(node[1])

    def _py_plus_(self, node):
        return "%s + %s" % (self._proc(node[1]), self._proc(node[2]))

    def _py_qual_(self, _node):
        return 'None # NYI - py_qual'

    def _py_lit_(self, node):
        return "'%s'" % node[1]

    def _py_var_(self, node):
        return 'v_%s' % node[1]

    def _py_num_(self, node):
        return node[1]

    def _py_arr_(self, _node):
        return 'None # NYI - py_arr'
<|endoftext|>


<commit_before>"""
    Composer Integration for Sublime Text 2

    @author  Nuno Franco da Costa <nuno@francodacosta.com>
    @license BSD - see LICENSE.md
    @link    git@github.com:francodacosta/composer-sublime.git
"""

import sublime
import sublime_plugin
import functools
import os
import subprocess
import time
import thread
import json

def debug_msg(msg):
    """
        Debug messages
    """
    if Prefs.debug == 1:
        print "[Composer] " + msg

class Prefs:
    """
        Plugin preferences
    """

    @staticmethod
    def load():
        settings = sublime.load_settings('composer-sublime.sublime-settings')

        Prefs.debug                     = settings.get('show_debug', 1)
        Prefs.showOutput                = settings.get('show_output')
        Prefs.showStatus                = settings.get('show_status')

        Prefs.composerCommand           = settings.get('composer_command')
        Prefs.composerFile              = settings.get('composer_file', 'composer.json')

        Prefs.composerInstallExtra      = settings.get('composer_install_extra')
        Prefs.composerUpdateExtra       = settings.get('composer_update_extra')
        Prefs.composerSelfUpdateExtra   = settings.get('composer_selfupdate_extra')
        Prefs.composerRequireExtra      = settings.get('composer_require_extra')
        Prefs.composerDumpAutoloadExtra = settings.get('composer_dumpautoload_extra')
        Prefs.composerValidateExtra     = settings.get('composer_validate_extra')

Prefs.load()

class FolderLocator():
    def __init__(self, baseFolder):
        self.baseFolder    = baseFolder
        self.currentFolder = baseFolder

    def exists(self, folder, file):
        path = os.path.join(folder,file)
        return os.path.exists(path)

    def locate(self, file):
        while (not self.exists(self.currentFolder, file)) :
            debug_msg("looking for %s in %s" % (file, self.currentFolder))
            self.currentFolder = os.path.dirname(self.currentFolder)
            if '/' == self.currentFolder :
                raise Exception ("Could not find '%s'. I started at %s and went all the way up to the root folder" % (file,self.baseFolder))
            return self.locate(file)

        debug_msg("found file in %s" % (self.currentFolder))
        return self.currentFolder

class OutputWindow(object):
    def __init__(self, window, name = 'composer'):
        self.window       = window
        self.name         = name
        self.outputWindow = None
        self.enabled      = 1

    def setEnabled(self, bool):
        self.enabled = bool

    def getOutputWindow(self):
        if (None is self.outputWindow):
            self.outputWindow = self.window.get_output_panel(self.name)
            self.clear()

        return self.outputWindow

    def show(self):
        if self.enabled is False:
            return

        self.getOutputWindow()
        self.window.run_command("show_panel", {"panel": "output." + self.name})

    def clear(self):
        outputWindow = self.getOutputWindow()
        outputWindow.set_read_only(False)
        edit = outputWindow.begin_edit()
        outputWindow.erase(edit, sublime.Region(0, outputWindow.size()))
        outputWindow.end_edit(edit)
        outputWindow.set_read_only(True)

    def write(self, data):
        if self.enabled is False :
            return

        str = data.decode("utf-8")
        str = str.replace('\r\n', '\n').replace('\r', '\n')
        outputWindow = self.getOutputWindow()
        self.show()

        # selection_was_at_end = (len(self.output_view.sel()) == 1
        #  and self.output_view.sel()[0]
        #    == sublime.Region(self.output_view.size()))
        self.outputWindow.set_read_only(False)
        edit = outputWindow.begin_edit()
        outputWindow.insert(edit, outputWindow.size(), str)
        #if selection_was_at_end:
        outputWindow.show(outputWindow.size())
        outputWindow.end_edit(edit)
        outputWindow.set_read_only(True)

class Worker(object):

    def __init__(self, command, workingDir, outputWindow = None, statusBar = None):
        self.command      = command
        self.workingDir   = workingDir
        self.outputWindow = outputWindow
        self.statusBar    = statusBar
        self.proc         = None
        self.counter = 0

    def doWork(self):
        self.startStatusProgress()
        shell = os.name == 'nt'

        self.appendData("executing: %s\n" % ' '.join(self.command))

        try:
            self.proc = subprocess.Popen(
                self.command,
                shell  = shell,
                stdout = subprocess.PIPE,
                stderr = subprocess.PIPE,
                cwd    = self.workingDir
            )

            if self.proc.stdout:
                thread.start_new_thread(self.readStdOut, ())
            if self.proc.stderr:
                thread.start_new_thread(self.readStdErr, ())

        except Exception, e:
            msg = "Error: %s" % e
            debug_msg(msg)
            self.appendData(msg)
            self.statusBar.stop = True
            self.statusBar.error = True
            # self.stopStatusProgress()
            thread.start_new_thread(self.statusBar.timedMessage,(msg))

    def appendData(self, data):
        if self.outputWindow is None:
            debug_msg("Skipping output window messages")
            return
        self.counter = self.counter + 1
        self.outputWindow.window.active_view().set_status("Composer", "%s" % self.counter)
        self.outputWindow.write(data)

    def startStatusProgress(self):
        if self.statusBar is None:
            debug_msg("Skipping status bar messages")
            return
        self.statusBar.start()

    def stopStatusProgress(self):
        if self.statusBar is None:
            debug_msg("Skipping status bar messages")
            return
        self.statusBar.stop = True
        # self.statusBar.clear()

    def readStdOut(self):
        while True:
            data = os.read(self.proc.stdout.fileno(), 2 ** 15)
            if "" == data :
                self.proc.stdout.close()
                self.appendData("\n-- Terminated -- \n")
                self.statusBar.stop = True
                break
            else:
                sublime.set_timeout(functools.partial(self.appendData, data), 0)

    def readStdErr(self):
        while True:
            data = os.read(self.proc.stderr.fileno(), 2 ** 15)
            if "" == data :
                self.proc.stderr.close()
                # self.appendData("\n--- Execution Finished ---")
                #
                break
            else:
                sublime.set_timeout(functools.partial(self.appendData, data), 0)
        pass

class StatusMessage():
    def __init__(self, view):
        self.view = view
        self.stop = False
        self.enabled = False
        self.error = False

    def setEnabled(self, boolean):
        self.enabled = boolean

    def message(self, msg):
        if self.enabled is False :
            return

        self.view.set_status("composer", msg )

    def timedMessage(self, msg, sleep = 5):
         self.message(msg)
         time.sleep(sleep)
         self.clear()

    def clear(self):
        self.view.erase_status('composer')

    def showStatusProgress(self, progress = 1, size=10):
        # t=0
        while self.stop is False:
            if progress ==  2 * size:
                progress = 0

            if progress < size :
                before = progress + 1
                after = (size ) - before
            else:
                before = size - progress % size -1
                after = (size ) - before

            msg = "Running Composer [%s=%s]" % (' ' * before, ' ' * after)

            self.message(msg)
            #sublime.set_timeout(functools.partial(self.view.set_status, msg), 0)
            time.sleep(0.1)
            progress += 1
            # t +=1
            # print t
            # if t == 20:
            #     break
        if self.error is False :
            self.message("Composer finished")
            time.sleep(3)
        self.clear()

    def start(self):
        thread.start_new_thread(self.showStatusProgress, ())

class BaseComposerCommand(sublime_plugin.TextCommand):

    def showTimedStatusMessage(self, msg):
        sm = self.getStatusMessage()
        sm.timedMessage(msg)

    def locateComposerJsonFolder(self):
        locator = FolderLocator(os.path.dirname(self.view.file_name()))
        return locator.locate(Prefs.composerFile)

    def getOutputWindow(self):
        outputWindow = OutputWindow(self.view.window())
        outputWindow.setEnabled(Prefs.showOutput)
        outputWindow.clear()

        return outputWindow

    def prepareCommandList(self, binary, command, args):
        command = [binary, command]
        if (len(args) > 0) :
            command = command + args

        return  command

    def getStatusMessage(self):
        sm = StatusMessage(self.view)
        sm.setEnabled(Prefs.showStatus)

        return sm

    def statusMessage(self, msg, statusMessage):
        statusMessage.message(msg)
        time.sleep(5)
        statusMessage.clear()

    def go(self, binary, command, args):
        self.binary = binary
        self.command = command
        self.args =args

        outputWindow = self.getOutputWindow()
        outputWindow.write("-- Starting Composer --\n")
        outputWindow.write("binary   : %s\n"   % (self.binary,))
        outputWindow.write("command  : %s\n"   % (self.command,))
        outputWindow.write("arguments: %s\n\n" % (' '.join(self.args),))

        statusMessage = self.getStatusMessage()

        cmd = self.prepareCommandList(
            binary  = self.binary,
            command = self.command,
            args    = self.args
        )

        try:
            workingDir = self.locateComposerJsonFolder()
            os.chdir(workingDir)
        except Exception, e :
            outputWindow.write("Error: : %s" % e)
            msg = "[ERROR] Composer.json not found"
            thread.start_new_thread(self.statusMessage, (msg, statusMessage))
            # statusMessage.message('Could not find composer.json')
            # time.sleep(3)
            # statusMessage.clear()
            #sublime.set_timeout(functools.partial(self.statusMessage, (msg, statusMessage)), 3)

            return

        worker = Worker(
            command      = cmd,
            workingDir   = workingDir,
            outputWindow = outputWindow,
            statusBar    = statusMessage
        )

        worker.doWork()
    def is_visible(self):
        st_version = 2

        # Warn about out-dated versions of ST3
        if sublime.version() == '':
            st_version = 3
            print('Package Control: Please upgrade to Sublime Text 3 build 3012 or newer')

        elif int(sublime.version()) > 3000:
            st_version = 3

        if st_version == 3 :
            return False

        return True

class Packagist(object):
    def getPackages(self):
        pass

    def searchPackages(self):
        pass

class ComposerJsonPackages(object):
    def __init__(self):
        self.packages = []

    def addPackage(self, name, version = '*'):
        self.packages.append([name, version])

    def removePackage(self, index):
        del (self.packages[index])

    def toList(self):
        return self.packages

    def toDict(self):
        ret = {}
        for key, data in self.packages:
            ret[key] = data

        return ret

class ComposerJsonFileLoader(object):
    def __init__(self, file):
        self.composerFile = file
        self.packageList = None

        self.getPackages()

    def getPackages(self):

        if self.packageList is None:
            require = self.toJson()['require']
            packageList = ComposerJsonPackages()

            for key in require:
                packageList.addPackage(key, require[key])

            self.packageList = packageList

        return self.packageList

    def removePackage(self, index):
        self.packageList.removePackage(index)

    def addPackage(self, name, version = '*'):
        print "before: ", len (self.packageList.toList())
        self.packageList.addPackage(name, version)
        print "after: ", len (self.packageList.toList())

    def toJson(self):
        return json.load(open(self.composerFile))
        pass

    def save(self):
        jsonObj = self.toJson()
        jsonObj['require'] = self.packageList.toDict()

        json.dump(jsonObj, open(self.composerFile, 'w'),indent=4 )

class ComposerInstallCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'install'
        args = Prefs.composerInstallExtra

        self.go(bin, cmd, args)

class ComposerUpdateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'update'
        args = Prefs.composerUpdateExtra

        self.go(bin, cmd, args)

class ComposerSelfUpdateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'self-update'
        args = Prefs.composerSelfUpdateExtra

        self.go(bin, cmd, args)

class ComposerDumpAutoloadCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'dump-autoload'
        args = Prefs.composerDumpAutoloadExtra

        self.go(bin, cmd, args)

class ComposerValidateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'validate'
        args = Prefs.composerValidateExtra

        self.go(bin, cmd, args)

class EditComposerFileCommand(BaseComposerCommand):
    def run(self, edit):
        composerJsonFile = os.path.join(self.locateComposerJsonFolder(), 'composer.json')
        self.view.window().open_file(composerJsonFile)

class ComposerRemovePackageCommand(BaseComposerCommand):
    def run(self, edit):
        self.composerJson = ComposerJsonFileLoader(os.path.join(self.locateComposerJsonFolder(), 'composer.json') )

        packages = self.composerJson.getPackages().toList()
        self.view.window().show_quick_panel(packages, self.removePackage)

    def removePackage(self, index):
        try:
            self.composerJson.removePackage(index)
            self.composerJson.save()
            thread.start_new_thread(self.showTimedStatusMessage, ("package removed",))
        except Exception, e:
            ow = OutputWindow(self.view.window())
            ow.write("Composer Error:\n\t" )
            ow.write("%s" % e)

class ComposerAddPackageCommand(BaseComposerCommand):
    def run(self, edit):
         self.input = self.view.window().show_input_panel("Package to add:", "Syntax: package name : version (if not provided defaults to *)", self.doAddPackage, None, None)
         self.input.sel().add(sublime.Region(0, 100))

    def doAddPackage(self, rawPackage):
        try:
            self.composerJson = ComposerJsonFileLoader(os.path.join(self.locateComposerJsonFolder(), 'composer.json') )

            splitInput = rawPackage.split(':')
            name = splitInput[0]
            if 1 == len(splitInput) :
                version = "*"
            else:
                version =splitInput[1]

            if 0 == len(name):
                raise Exception('Please provide a package name')

            bin  = Prefs.composerCommand
            cmd  = 'require'
            args = ["%s:%s" %(name, version)] + Prefs.composerRequireExtra

            self.go(bin, cmd, args)

        except Exception, e:
            ow = OutputWindow(self.view.window())
            ow.write("Composer Error:\n\t" )
            ow.write("%s" % e)

<commit_msg>making python2 code working on python 3<commit_after>"""
    Composer Integration for Sublime Text 2

    @author  Nuno Franco da Costa <nuno@francodacosta.com>
    @license BSD - see LICENSE.md
    @link    git@github.com:francodacosta/composer-sublime.git
"""

try:
    import sublime
    import sublime_plugin
    import functools
    import os
    import subprocess
    import time
    import thread
    import json
except Exception:
    print ('some modules could not be inported (it is ok if using ST3')

def debug_msg(msg):
    """
        Debug messages
    """
    if Prefs.debug == 1:
        print( "[Composer] " + msg)

class Prefs:
    """
        Plugin preferences
    """

    @staticmethod
    def load():
        settings = sublime.load_settings('composer-sublime.sublime-settings')

        Prefs.debug                     = settings.get('show_debug', 1)
        Prefs.showOutput                = settings.get('show_output')
        Prefs.showStatus                = settings.get('show_status')

        Prefs.composerCommand           = settings.get('composer_command')
        Prefs.composerFile              = settings.get('composer_file', 'composer.json')

        Prefs.composerInstallExtra      = settings.get('composer_install_extra')
        Prefs.composerUpdateExtra       = settings.get('composer_update_extra')
        Prefs.composerSelfUpdateExtra   = settings.get('composer_selfupdate_extra')
        Prefs.composerRequireExtra      = settings.get('composer_require_extra')
        Prefs.composerDumpAutoloadExtra = settings.get('composer_dumpautoload_extra')
        Prefs.composerValidateExtra     = settings.get('composer_validate_extra')

Prefs.load()

class FolderLocator():
    def __init__(self, baseFolder):
        self.baseFolder    = baseFolder
        self.currentFolder = baseFolder

    def exists(self, folder, file):
        path = os.path.join(folder,file)
        return os.path.exists(path)

    def locate(self, file):
        while (not self.exists(self.currentFolder, file)) :
            debug_msg("looking for %s in %s" % (file, self.currentFolder))
            self.currentFolder = os.path.dirname(self.currentFolder)
            if '/' == self.currentFolder :
                raise Exception ("Could not find '%s'. I started at %s and went all the way up to the root folder" % (file,self.baseFolder))
            return self.locate(file)

        debug_msg("found file in %s" % (self.currentFolder))
        return self.currentFolder

class OutputWindow(object):
    def __init__(self, window, name = 'composer'):
        self.window       = window
        self.name         = name
        self.outputWindow = None
        self.enabled      = 1

    def setEnabled(self, bool):
        self.enabled = bool

    def getOutputWindow(self):
        if (None is self.outputWindow):
            self.outputWindow = self.window.get_output_panel(self.name)
            self.clear()

        return self.outputWindow

    def show(self):
        if self.enabled is False:
            return

        self.getOutputWindow()
        self.window.run_command("show_panel", {"panel": "output." + self.name})

    def clear(self):
        outputWindow = self.getOutputWindow()
        outputWindow.set_read_only(False)
        edit = outputWindow.begin_edit()
        outputWindow.erase(edit, sublime.Region(0, outputWindow.size()))
        outputWindow.end_edit(edit)
        outputWindow.set_read_only(True)

    def write(self, data):
        if self.enabled is False :
            return

        str = data.decode("utf-8")
        str = str.replace('\r\n', '\n').replace('\r', '\n')
        outputWindow = self.getOutputWindow()
        self.show()

        # selection_was_at_end = (len(self.output_view.sel()) == 1
        #  and self.output_view.sel()[0]
        #    == sublime.Region(self.output_view.size()))
        self.outputWindow.set_read_only(False)
        edit = outputWindow.begin_edit()
        outputWindow.insert(edit, outputWindow.size(), str)
        #if selection_was_at_end:
        outputWindow.show(outputWindow.size())
        outputWindow.end_edit(edit)
        outputWindow.set_read_only(True)

class Worker(object):

    def __init__(self, command, workingDir, outputWindow = None, statusBar = None):
        self.command      = command
        self.workingDir   = workingDir
        self.outputWindow = outputWindow
        self.statusBar    = statusBar
        self.proc         = None
        self.counter = 0

    def doWork(self):
        self.startStatusProgress()
        shell = os.name == 'nt'

        self.appendData("executing: %s\n" % ' '.join(self.command))

        try:
            self.proc = subprocess.Popen(
                self.command,
                shell  = shell,
                stdout = subprocess.PIPE,
                stderr = subprocess.PIPE,
                cwd    = self.workingDir
            )

            if self.proc.stdout:
                thread.start_new_thread(self.readStdOut, ())
            if self.proc.stderr:
                thread.start_new_thread(self.readStdErr, ())

        except Exception:
            e = sys.exc_info()[1]
            msg = "Error: %s" % e
            debug_msg(msg)
            self.appendData(msg)
            self.statusBar.stop = True
            self.statusBar.error = True
            # self.stopStatusProgress()
            thread.start_new_thread(self.statusBar.timedMessage,(msg))

    def appendData(self, data):
        if self.outputWindow is None:
            debug_msg("Skipping output window messages")
            return
        self.counter = self.counter + 1
        self.outputWindow.window.active_view().set_status("Composer", "%s" % self.counter)
        self.outputWindow.write(data)

    def startStatusProgress(self):
        if self.statusBar is None:
            debug_msg("Skipping status bar messages")
            return
        self.statusBar.start()

    def stopStatusProgress(self):
        if self.statusBar is None:
            debug_msg("Skipping status bar messages")
            return
        self.statusBar.stop = True
        # self.statusBar.clear()

    def readStdOut(self):
        while True:
            data = os.read(self.proc.stdout.fileno(), 2 ** 15)
            if "" == data :
                self.proc.stdout.close()
                self.appendData("\n-- Terminated -- \n")
                self.statusBar.stop = True
                break
            else:
                sublime.set_timeout(functools.partial(self.appendData, data), 0)

    def readStdErr(self):
        while True:
            data = os.read(self.proc.stderr.fileno(), 2 ** 15)
            if "" == data :
                self.proc.stderr.close()
                # self.appendData("\n--- Execution Finished ---")
                #
                break
            else:
                sublime.set_timeout(functools.partial(self.appendData, data), 0)
        pass

class StatusMessage():
    def __init__(self, view):
        self.view = view
        self.stop = False
        self.enabled = False
        self.error = False

    def setEnabled(self, boolean):
        self.enabled = boolean

    def message(self, msg):
        if self.enabled is False :
            return

        self.view.set_status("composer", msg )

    def timedMessage(self, msg, sleep = 5):
         self.message(msg)
         time.sleep(sleep)
         self.clear()

    def clear(self):
        self.view.erase_status('composer')

    def showStatusProgress(self, progress = 1, size=10):
        # t=0
        while self.stop is False:
            if progress ==  2 * size:
                progress = 0

            if progress < size :
                before = progress + 1
                after = (size ) - before
            else:
                before = size - progress % size -1
                after = (size ) - before

            msg = "Running Composer [%s=%s]" % (' ' * before, ' ' * after)

            self.message(msg)
            #sublime.set_timeout(functools.partial(self.view.set_status, msg), 0)
            time.sleep(0.1)
            progress += 1
            # t +=1
            # #print t
            # if t == 20:
            #     break
        if self.error is False :
            self.message("Composer finished")
            time.sleep(3)
        self.clear()

    def start(self):
        thread.start_new_thread(self.showStatusProgress, ())

class BaseComposerCommand(sublime_plugin.TextCommand):

    def showTimedStatusMessage(self, msg):
        sm = self.getStatusMessage()
        sm.timedMessage(msg)

    def locateComposerJsonFolder(self):
        locator = FolderLocator(os.path.dirname(self.view.file_name()))
        return locator.locate(Prefs.composerFile)

    def getOutputWindow(self):
        outputWindow = OutputWindow(self.view.window())
        outputWindow.setEnabled(Prefs.showOutput)
        outputWindow.clear()

        return outputWindow

    def prepareCommandList(self, binary, command, args):
        command = [binary, command]
        if (len(args) > 0) :
            command = command + args

        return  command

    def getStatusMessage(self):
        sm = StatusMessage(self.view)
        sm.setEnabled(Prefs.showStatus)

        return sm

    def statusMessage(self, msg, statusMessage):
        statusMessage.message(msg)
        time.sleep(5)
        statusMessage.clear()

    def go(self, binary, command, args):
        self.binary = binary
        self.command = command
        self.args =args

        outputWindow = self.getOutputWindow()
        outputWindow.write("-- Starting Composer --\n")
        outputWindow.write("binary   : %s\n"   % (self.binary,))
        outputWindow.write("command  : %s\n"   % (self.command,))
        outputWindow.write("arguments: %s\n\n" % (' '.join(self.args),))

        statusMessage = self.getStatusMessage()

        cmd = self.prepareCommandList(
            binary  = self.binary,
            command = self.command,
            args    = self.args
        )

        try:
            workingDir = self.locateComposerJsonFolder()
            os.chdir(workingDir)
        except Exception :
            e = sys.exc_info()[1]
            outputWindow.write("Error: : %s" % e)
            msg = "[ERROR] Composer.json not found"
            thread.start_new_thread(self.statusMessage, (msg, statusMessage))
            # statusMessage.message('Could not find composer.json')
            # time.sleep(3)
            # statusMessage.clear()
            #sublime.set_timeout(functools.partial(self.statusMessage, (msg, statusMessage)), 3)

            return

        worker = Worker(
            command      = cmd,
            workingDir   = workingDir,
            outputWindow = outputWindow,
            statusBar    = statusMessage
        )

        worker.doWork()
    def is_visible(self):
        st_version = 2

        # Warn about out-dated versions of ST3
        if sublime.version() == '':
            st_version = 3
            print('Package Control: Please upgrade to Sublime Text 3 build 3012 or newer')

        elif int(sublime.version()) > 3000:
            st_version = 3

        if st_version == 3 :
            return False

        return True

class Packagist(object):
    def getPackages(self):
        pass

    def searchPackages(self):
        pass

class ComposerJsonPackages(object):
    def __init__(self):
        self.packages = []

    def addPackage(self, name, version = '*'):
        self.packages.append([name, version])

    def removePackage(self, index):
        del (self.packages[index])

    def toList(self):
        return self.packages

    def toDict(self):
        ret = {}
        for key, data in self.packages:
            ret[key] = data

        return ret

class ComposerJsonFileLoader(object):
    def __init__(self, file):
        self.composerFile = file
        self.packageList = None

        self.getPackages()

    def getPackages(self):

        if self.packageList is None:
            require = self.toJson()['require']
            packageList = ComposerJsonPackages()

            for key in require:
                packageList.addPackage(key, require[key])

            self.packageList = packageList

        return self.packageList

    def removePackage(self, index):
        self.packageList.removePackage(index)

    def addPackage(self, name, version = '*'):
        #print "before: ", len (self.packageList.toList())
        self.packageList.addPackage(name, version)
        #print "after: ", len (self.packageList.toList())

    def toJson(self):
        return json.load(open(self.composerFile))
        pass

    def save(self):
        jsonObj = self.toJson()
        jsonObj['require'] = self.packageList.toDict()

        json.dump(jsonObj, open(self.composerFile, 'w'),indent=4 )

class ComposerInstallCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'install'
        args = Prefs.composerInstallExtra

        self.go(bin, cmd, args)

class ComposerUpdateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'update'
        args = Prefs.composerUpdateExtra

        self.go(bin, cmd, args)

class ComposerSelfUpdateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'self-update'
        args = Prefs.composerSelfUpdateExtra

        self.go(bin, cmd, args)

class ComposerDumpAutoloadCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'dump-autoload'
        args = Prefs.composerDumpAutoloadExtra

        self.go(bin, cmd, args)

class ComposerValidateCommand(BaseComposerCommand):
    def run(self, edit):
        bin  = Prefs.composerCommand
        cmd  = 'validate'
        args = Prefs.composerValidateExtra

        self.go(bin, cmd, args)

class EditComposerFileCommand(BaseComposerCommand):
    def run(self, edit):
        composerJsonFile = os.path.join(self.locateComposerJsonFolder(), 'composer.json')
        self.view.window().open_file(composerJsonFile)

class ComposerRemovePackageCommand(BaseComposerCommand):
    def run(self, edit):
        self.composerJson = ComposerJsonFileLoader(os.path.join(self.locateComposerJsonFolder(), 'composer.json') )

        packages = self.composerJson.getPackages().toList()
        self.view.window().show_quick_panel(packages, self.removePackage)

    def removePackage(self, index):
        try:
            self.composerJson.removePackage(index)
            self.composerJson.save()
            thread.start_new_thread(self.showTimedStatusMessage, ("package removed",))
        except Exception:
            e = sys.exc_info()[1]
            ow = OutputWindow(self.view.window())
            ow.write("Composer Error:\n\t" )
            ow.write("%s" % e)

class ComposerAddPackageCommand(BaseComposerCommand):
    def run(self, edit):
         self.input = self.view.window().show_input_panel("Package to add:", "Syntax: package name : version (if not provided defaults to *)", self.doAddPackage, None, None)
         self.input.sel().add(sublime.Region(0, 100))

    def doAddPackage(self, rawPackage):
        try:
            self.composerJson = ComposerJsonFileLoader(os.path.join(self.locateComposerJsonFolder(), 'composer.json') )

            splitInput = rawPackage.split(':')
            name = splitInput[0]
            if 1 == len(splitInput) :
                version = "*"
            else:
                version =splitInput[1]

            if 0 == len(name):
                raise Exception('Please provide a package name')

            bin  = Prefs.composerCommand
            cmd  = 'require'
            args = ["%s:%s" %(name, version)] + Prefs.composerRequireExtra

            self.go(bin, cmd, args)

        except Exception:
            e = sys.exc_info()[1]
            ow = OutputWindow(self.view.window())
            ow.write("Composer Error:\n\t" )
            ow.write("%s" % e)

<|endoftext|>


<commit_before>"""
Jhonatan da Silva
Last Updated version :
Tue Jan 31 19:26:59 2017
Number of code lines:
15
"""
#teste
import matplotlib.pyplot as plt
import numpy as np
import time
x_axis = np.arange(9)
y_axis = np.arange(9)

plt.scatter(x_axis,y_axis)
plt.show()

print('acabou')
print('isso só vai ser printado depois de eu fechar a imagem')
time.sleep(2)

plt.scatter(x_axis,y_axis)
plt.show()
<commit_msg>update<commit_after>"""
Jhonatan da Silva
Last Updated version :
Tue Jan 31 20:17:47 2017
Number of code lines:
15
"""
import matplotlib.pyplot as plt
import numpy as np
import time
x_axis = np.arange(9)
y_axis = np.arange(9)

plt.scatter(x_axis,y_axis)
plt.show()

print('acabou')
print('isso só vai ser printado depois de eu fechar a imagem')
time.sleep(2)

plt.scatter(x_axis,y_axis)
plt.show()
<|endoftext|>


<commit_before>#!/usr/bin/env python

import math
import re

'''Calculus Made Easy'''

cmds = ['limit', 'derivative']

class calculusME:
    def __init__(self):
        self.cleanup()
        print(
"""Rules of CalculusME:
    -- use parentheses ie (2x+2)/(1x+1)
    -- use 'x' for variable
    -- if just 'x', put '1x'
    -- type 'help' for options
    -- type 'quit' to exit
    -- absolutely, positively NO SPACES!""")

        self.lim = None
        while True:
            cmd = raw_input('>')
            for k in re.findall('\-\-(\w+)', cmd):
                cmd = cmd.replace(" --"+k,'')
                self.opts[k] = True
            if cmd == 'help':
                print self.options()
            elif cmd == ('quit' or 'exit'):
                break
            elif cmd in cmds:
                print getattr(self, cmd)()
            else:
                print 'no command %s' % cmd

    def options(self):
        return(
"""Options:
    -- limit
    -- derivative""")

    def format_equation(self):
        '''format f(x) for exponents'''
        self.lim = self.lim.replace('^', '**')

    def substitute_x(self, eq, x):
        opx = '(\+|\-|\/|\*)x'
        while opx:
            try:
                '''find operator in front of x'''
                op = re.search(
                    opx, eq).group(1)
                '''increment x with operator'''
                eq = eq.replace(op+'x', x)
            except:
                opx = False

        opx = '(\+|\-|\/|\*)x'
        '''replace x multiples and increment it'''
        eq = eq.replace('x', '*'+x)
        return eq

    def derivative(self):
        try:
            dydx = []
            eq = ""
            f_of_x = raw_input("f(x)=")
            fprime = raw_input("f'@")
            f_of_a = self.substitute_x(f_of_x, "("+str(fprime)+")")
            f_of_a_plus_x = self.substitute_x(
                f_of_x,"("+str(fprime)+'+1x)')
            self.lim = "(("+f_of_a_plus_x+")-("+f_of_a+"))/(1x)"
            self.x = 0
            return self.limit().replace('limit','derivative')
        except:
            return 'error, please review your submission'
        finally:
            self.cleanup()

    def limit(self):
        '''if f(x) is not defined, ask for it'''
        if self.lim is None:
            self.lim = raw_input('lim ')
            self.x = raw_input('x->')
        if self.lim is 'x':
            return 'limit is '+self.x
        self.format_equation()
        try:
            approaching = []
            side = 1
            x = self.x
            i = 0
            while i <= 7:
                if i is 6:
                    '''if we're approaching from the left,
                       then we're done'''
                    if side is -1:
                        break
                    '''if we're approaching from the right,
                       switch to the left'''
                    i = 1
                    side = -1
                    continue
                i += 1
                '''get .0001 more away from approaching int'''
                inc = .0001*i*side
                eq = self.substitute_x(
                    self.lim, str(int(x)+inc))
                approaching.append(eval(eq))
                if self.opts['show_work'] is True:
                    print str(eq)+" = "+str(eval(eq))

            for l in approaching:
                '''if the difference from one limit
                   to the next is greater than one,
                   the limit does not exist'''
                if abs(l-approaching[-1]) > 1:
                    return 'limit does not exist'
            '''we found the limit'''
            if abs(round(approaching[1])-approaching[1]) < .01:
                return 'limit is '+str(round(approaching[1]))
            return 'limit is '+str(round(approaching[0], 2))

        except ZeroDivisionError:
            return 'no dividing by zero'
        except:
            return 'unforeseen error. please try again'
        finally:
            self.cleanup()

    def cleanup(self):
        self.lim = None
        self.x = None
        self.opts = {'show_work': False}

m = calculusME()
<commit_msg>exit/quit command<commit_after>#!/usr/bin/env python

import math
import re

'''Calculus Made Easy'''

cmds = ['limit', 'derivative']

class calculusME:
    def __init__(self):
        self.cleanup()
        print(
"""Rules of CalculusME:
    -- use parentheses ie (2x+2)/(1x+1)
    -- use 'x' for variable
    -- if just 'x', put '1x'
    -- type 'help' for options
    -- type 'quit' to exit
    -- absolutely, positively NO SPACES!""")

        self.lim = None
        while True:
            cmd = raw_input('>')
            for k in re.findall('\-\-(\w+)', cmd):
                cmd = cmd.replace(" --"+k,'')
                self.opts[k] = True
            if cmd == 'help':
                print self.options()
            elif cmd == 'quit' or cmd == 'exit':
                break
            elif cmd in cmds:
                print getattr(self, cmd)()
            else:
                print 'no command %s' % cmd

    def options(self):
        return(
"""Options:
    -- limit
    -- derivative""")

    def format_equation(self):
        '''format f(x) for exponents'''
        self.lim = self.lim.replace('^', '**')

    def substitute_x(self, eq, x):
        opx = '(\+|\-|\/|\*)x'
        while opx:
            try:
                '''find operator in front of x'''
                op = re.search(
                    opx, eq).group(1)
                '''increment x with operator'''
                eq = eq.replace(op+'x', x)
            except:
                opx = False

        opx = '(\+|\-|\/|\*)x'
        '''replace x multiples and increment it'''
        eq = eq.replace('x', '*'+x)
        return eq

    def derivative(self):
        try:
            dydx = []
            eq = ""
            f_of_x = raw_input("f(x)=")
            fprime = raw_input("f'@")
            f_of_a = self.substitute_x(f_of_x, "("+str(fprime)+")")
            f_of_a_plus_x = self.substitute_x(
                f_of_x,"("+str(fprime)+'+1x)')
            self.lim = "(("+f_of_a_plus_x+")-("+f_of_a+"))/(1x)"
            self.x = 0
            return self.limit().replace('limit','derivative')
        except:
            return 'error, please review your submission'
        finally:
            self.cleanup()

    def limit(self):
        '''if f(x) is not defined, ask for it'''
        if self.lim is None:
            self.lim = raw_input('lim ')
            self.x = raw_input('x->')
        if self.lim is 'x':
            return 'limit is '+self.x
        self.format_equation()
        try:
            approaching = []
            side = 1
            x = self.x
            i = 0
            while i <= 7:
                if i is 6:
                    '''if we're approaching from the left,
                       then we're done'''
                    if side is -1:
                        break
                    '''if we're approaching from the right,
                       switch to the left'''
                    i = 1
                    side = -1
                    continue
                i += 1
                '''get .0001 more away from approaching int'''
                inc = .0001*i*side
                eq = self.substitute_x(
                    self.lim, str(int(x)+inc))
                approaching.append(eval(eq))
                if self.opts['show_work'] is True:
                    print str(eq)+" = "+str(eval(eq))

            for l in approaching:
                '''if the difference from one limit
                   to the next is greater than one,
                   the limit does not exist'''
                if abs(l-approaching[-1]) > 1:
                    return 'limit does not exist'
            '''we found the limit'''
            if abs(round(approaching[1])-approaching[1]) < .01:
                return 'limit is '+str(round(approaching[1]))
            return 'limit is '+str(round(approaching[0], 2))

        except ZeroDivisionError:
            return 'no dividing by zero'
        except:
            return 'unforeseen error. please try again'
        finally:
            self.cleanup()

    def cleanup(self):
        self.lim = None
        self.x = None
        self.opts = {'show_work': False}

m = calculusME()
<|endoftext|>