First time here? Check out the FAQ!
1

How do you put a save hook into wing?

Wanting to add yapf formatting on save, but I need a way to capture the save event, run the formatter, update the buffer, then call the base save.

I see mentions about a pre-save event, but not finding any details anywhere.

Mark Jones's avatar
83
Mark Jones
asked 2017-11-07 13:38:00 -0600
Wingware Support's avatar
4.2k
Wingware Support
updated 2019-03-13 10:06:52 -0600
edit flag offensive 0 remove flag close merge delete

Comments

add a comment see more comments

2 Answers

1

Here's a different approach that does hook up to presave to replace the contents of the editor at save time, just before saving, with the output from yapf:

import subprocess
import wingapi

def run_yapf(doc=wingapi.kArgDocument):

  # Set to non-None to use an uninstalled copy of yapf
  kYapfDir = None
  #kYapfDir = '/Users/jpe/Documents/tmp/yapf'

  proj = wingapi.gApplication.GetProject()
  pyexec = proj.GetPythonExecutable(doc.GetFilename())

  orig_text = doc.GetText()

  argv = [pyexec, '-m', 'yapf']
  process = subprocess.Popen(argv, cwd=kYapfDir, stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  from_yapf, error_output = process.communicate(orig_text)
  if from_yapf != orig_text:
    doc.SetText(from_yapf)

def _connect_to_document(doc):
  def _on_presave(filename, encoding):
    # Called for autosave w/ filename set to non-None
    if filename is not None:
      return

    if doc.GetMimeType() == 'text/x-python':
      run_yapf(doc)

  connect_id = doc.Connect('presave', _on_presave)

def _init():
  wingapi.gApplication.Connect('document-open', _connect_to_document)
  for doc in wingapi.gApplication.GetOpenDocuments():
    _connect_to_document(doc)

_init()
Wingware Support's avatar
4.2k
Wingware Support
answered 2017-11-08 07:41:00 -0600
Wingware Admin's avatar
231
Wingware Admin
updated 2019-03-07 08:01:36 -0600
edit flag offensive 0 remove flag delete link

Comments

I'm assuming at this point any possibility of undo would be lost past the save wouldn't it.

Mark Jones's avatar Mark Jones (2018-02-23 14:38:00 -0600) edit

Yea, I think so but instead of calling SetText() on the doc you could call SetSelection() on the CAPIEditor instance to select all the text and then reach through the API with

ed.fEditor._fScint.replace_sel(from_yapf)

where ed is the instance of CAPIEditor.  Then one undo should return you to the pre-yapf text, but of course saving again would replace it again, etc, so more would be needed to allow saving without the replacement. 

Personally, I'd rather have a way to run yapf on the file on demand and not with every save.  Or more likely I'd just not use things like yapf since Python is extremely readable regardless of details of the formatting.

Wingware Support's avatar Wingware Support (2018-02-23 14:46:00 -0600) edit
add a comment see more comments
0

You want the save-point signal on the CAPIDocument.  Something like this:

import wingapi

def _connect_to_document(doc):
  def _on_modified(savepoint):
    if not savepoint:
      return
    # Execute yapf here, possibly with wingapi.gApplication.AsyncExecuteCommandLine
  connect_id = doc.Connect('save-point', _on_modified)

def _init():
  wingapi.gApplication.Connect('document-open', _connect_to_document)
  for doc in wingapi.gApplication.GetOpenDocuments():
    _connect_to_document(doc)

_init()
Wingware Support's avatar
4.2k
Wingware Support
answered 2017-11-07 16:05:00 -0600
Wingware Admin's avatar
231
Wingware Admin
updated 2019-03-07 08:01:08 -0600
edit flag offensive 0 remove flag delete link

Comments

This approach assumed that yapf would run and change the file on disk, and Wing would reload the changed file automatically afterward.  The other answer above is probably better, and is more complete in any case.

Wingware Support's avatar Wingware Support (2017-11-08 07:43:00 -0600) edit
add a comment see more comments

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account. This space is reserved only for answers. If you would like to engage in a discussion, please instead post a comment under the question or an answer that you would like to discuss.

Add Answer