text: .
  Did you read sublimetext.com/docs/3/porting_guide.html?
  Yes, but it didn't really help me.
  Turns out, all I had to do was comment out begin_edit, well I thought it was, but now when I continue typing my cursor is left at the last edit position. What the?
  Weird, moving self.view.end_edit() to just after when I edit the stack works. Oh well...
  You should not manually call end_edit(). It is called for you when your TextCommand exits. See the code in sublime_plugin.py.
  You get an edit object passed in to a TextCommands run() function. This is used to encapsulate all the modifications that are done by the text command into a single undo group. You can pass edit objects to other functions, but it doesn't make sense to store them in objects, pass them to other threads, or pass them to set_timeout calls. When the run() function of the text command returns, the edit object should never be accessed again: it wouldn't make sense to try and group the modifications into the same undo group, as other undo groups may have been created in the mean time.
  In S3, using an edit object after run() has returned will result in your insert/erase/replace calls silently failing. I'll change this so an exception is thrown, making things a little more explicit.
  begin_edit() was removed from the S3 API because it was too easy for plugins to call begin_edit without a matching end_edit, or to call begin_edit and expect the edit object to be valid over time, and leave the undo stack in an invalid state.
  In other words, Sublime Text is a nanny state, and we are its hapless moron inhabitants, unfit to wield sharp knives.
  I like that poetry
  Well, the real-real reason begin_edit was removed is that it's easy to get it wrong, and when it does go wrong, it's not obvious to a user what's gone wrong, or what caused it. An alternative would have been to find a way where this situation could have been detected and reported to the user, but getting rid of begin_edit results in less code, and run_command(...) is a reasonable substitute.
  I for one appreciate your decision to make our lives easier Jon. Thank you
  I think a solution for the common use-case of begin_edit would be helpful. begin_edit is still really helpful is when using an input panel (async edits). In the example below I'm doing something trivial (and run_command('insert') works), but in the plugin I'm porting now I'm manipulating regions and replacing lots of text... non-trivial. My work around is to create a new command, and pass it all the parameters it needs via run_command. This is not good clean code, and it's def not an improvement from try: begin_edit ...finally: end_edit.
  begin_edit
  run_command('insert')
  run_command
  try: begin_edit ...finally: end_edit
  Would this, or something like it, be possible?
  # i don't want to create a new command, so instead...
  region = sublime.Region(a, b)
  text = 'gonna insert it'
  def insert_text(edit):
  self.view.replace(edit, region, text)
  run_command(insert_text)
  agree, had same idea myself, think we are on the right track