Any and all help with this is immensely appreciated, I've also included the process diagram below.
http://s24.postimg.org/oac2n66tx/Perfect_API_Page_1.jpg
        That won't work in CraftOS. You'd need to create your own OS to add this functionality.
Er, could you not override os.pullEvent() so that it acts as a coroutine manager, in addition to its normal functionality?
Although I guess I'd have to learn how to force CraftOS to yield….. : /
--[[file as coroutine]]
while true do 
  print('coroutine is live')
  coroutine.yield()
end
>lua
lua>parallel.waitForAny(os.loadAPI('file'),os.run({},"/rom/programs/shell"))
coroutine live
CraftOS 1.7
>[Enter]
>[Enter]
>exit
coroutine live --Presses [Enter]
coroutine live --Presses [Enter]
coroutine live --Presses [Enter]
coroutine live --Presses [Enter]
coroutine live --Presses [Enter]
parallel.waitForAny(function() os.loadAPI('file') end, function() os.run({},"/rom/programs/shell") end)Er, could you not override os.pullEvent() so that it acts as a coroutine manager, in addition to its normal functionality?
parallel.waitForAny() expects you to pass it at least two function pointers. If you try to execute the functions yourself, than you'll instead end up passing the parallel API whatever those functions return. Your code isn't even managing to start parallel.waitForAny() - it's instead busy trying to resolve the arguments you wish to pass to it.
Now if you wrapped those calls inside function declarations, like so, then it'd do something closer to what you're wanting:parallel.waitForAny(function() os.loadAPI('file') end, function() os.run({},"/rom/programs/shell") end)
It's worth pointing out that the technique I initially suggested isn't simple coding. You won't be able to use the parallel API to pull it off; you'd need to understand how that API works so that you could devise your own coroutine manager.
If you're happy running a second shell alongside your code (which is what the above line does), then by all means stick with that.
-- The function we're going to run alongside everything else:
-- (Just an example of what you might use)
local function activeCode()
	local counted = 0
	
	repeat
		local x, y = term.getCursorPos()
		local xSize, ySize = term.getSize()
		
		term.setCursorPos(1, ySize)
		term.write("Events counted: "..counted.." (F12 to kill)")
		term.setCursorPos(x, y)
		
		local event, par = os.pullEvent()
		counted = counted + 1
	until event == "key" and par == keys.f12
end
local myCoroutine, oldCoroutineYield, hackySystem, myCoroutineFilter = coroutine.create(activeCode), coroutine.yield, false
coroutine.yield = function(filter)
	if hackySystem then
		return oldCoroutineYield(filter)
	else
		local myEvent, ok
		hackySystem = true
		
		repeat
			myEvent = {oldCoroutineYield()}
			if coroutine.status(myCoroutine) ~= "dead" and (myEvent[1] == myCoroutineFilter or myEvent[1] == "terminate" or not myCoroutineFilter) then
				ok, myCoroutineFilter = coroutine.resume(myCoroutine, unpack(myEvent))
			end
		until myEvent[1] == filter or myEvent[1] == "terminate" or not filter
		
		hackySystem = false
		if coroutine.status(myCoroutine) == "dead" then coroutine.yield = oldCoroutineYield end
		return unpack(myEvent)
	end
end
function activeCode()
  msgBuffer = {}
  while true do
    local e = {os.pullEvent()}
    if e and e[2] == "modem_message" then
      msgBuffer[#msgBuffer+1] = {e[6],e[3]}
    end
    os.pullEventRaw()
  end
end
--Backup pullEventRaw and create our internal coroutine
local pullEventRaw_Backup = os.pullEventRaw
local coActive = coroutine.create(activeCode)
--Override os.pullEventRaw()
function os.pullEventRaw(sFilter)
  while true do
    local event = {pullEventRaw_Backup()}
    --Define internal coroutines to check for
    if coroutine.status(coActive) == "suspended" then
      coroutine.resume(coActive, unpack(event))
    end
    --Return any events
    if sFilter == event[1] or not sFilter then
      return unpack(event)
    end
  end
end
My code doesn't actually fail to handle the filter - it just doesn't need to save it. See if you can follow my logic here:
*My os.pullEventRaw pulls events without the filter and then waits until it finds an appropriate one
*When calling coroutine.resume, the stuff I pass is going to be passed to another "instance" of the same function, which, as I said, doesn't pass anything back anyway.
If you're talking about my code, the mechanism for preventing duplicates should be quite obvious to you. At least, I can't think of a weak point.
Your code does prevent duplication, but doesn't handle terminate events correctly–these should bypass the filtering.
My code doesn't actually fail to handle the filter - it just doesn't need to save it. See if you can follow my logic here:
*My os.pullEventRaw pulls events without the filter and then waits until it finds an appropriate one
*When calling coroutine.resume, the stuff I pass is going to be passed to another "instance" of the same function, which, as I said, doesn't pass anything back anyway.
Er, yes, it does need to save it. See, when the function you build your coFoo() coroutine out of - foo() - yields, it passes back whatever parameter was handed to coroutine.yield() (in your case, the string "modem_message"). It expects this to mean it'll only be resumed when there's an event of that type at the front of the queue.
So what happens if you resume it with a different event type? Well, if the rest of the code in foo() is rigged to assume it'll only be resumed with "modem_message" events (which would be quite reasonable), odds are it'll crash messily, yes?
os.pullEvent( "message" )
function os.pullEventRaw(sFilter)
  while true do
    local event = {pullEventRaw_Backup()}
    --Define internal coroutines to check for
    if coroutine.status(coActive) == "suspended" then
      coroutine.resume(coActive, unpack(event))
    end
    --Return any events
    if sFilter == event[1] or not sFilter then
      return unpack(event)
    end
  end
end
…which calls the old os.pullEventRaw without any parameters. Therefor, nothing will ever be passed by coroutine.yield, short of the user calling coroutine.yield directly themselves.
I'm not able to fix the duplicating events - any sort of coroutine manager (even parallel) running somewhere will screw it up - because os.pullEventRaw will be called multiple times per event. I really don't know how I'd figure out if the function is being called in some sort of coroutine manager, if it's possible at all.