Share useful IDE scripts

Howdy, just needed to sort lines in some code. When doing this in the past, I typically Copy/Paste into BBEdit, have it sort, then paste back into Xojo. However, it’s easy enough to do in Xojo Script, so I wrote this. Just use File > IDE Scripts > New IDE Script, paste it in and save as something like Sort Lines. It will work on just the selected text or the whole editor if nothing is selected.

With that, I’d also be interested in seeing scripts other people wrote for the IDE to make life a bit easier!

  Dim workOn As String
  
  If SelText <> "" Then
    workOn = SelText
  Else
    workOn = Text
  End If
  
  Dim lines() As String = workOn.Split(EndOfLine)
  lines.Sort
  
  If SelText <> "" Then
    SelText = Join(lines, EndOfLine)
  Else
    Text = Join(lines, EndOfLine)
  End If

So we are talking about IDE Script, not XojoScript

Yes, clarified title.

I saved this little doodad from Kem during the whole obfuscation debacle.
I modified my copy to work more like I’d expect, but you can find the original at the link at the top of the comments in the script.

I put it on pastebin to save reading space here

A common problem I have, and some others, is that there is no shortcut to toggle the Find panel on and off (<https://xojo.com/issue/28875>)…

This can be solved by making a simple one line script:

DoCommand "Find"

Then use your favorite Keyboard Shortcut program (or the one built into OS X if using Apple) and bind something like Ctrl+W to that script (in my mind, Ctrl+W = Where Is).

Now when you hit Ctrl+W the first time, the find panel appears and your cursor is in the Find text box. Hit Ctrl+W again (anywhere) and the find panel disappears.

In some situations (items shared in projects, SCM, etc…) it’s handy to reload a project. Use File > IDE Scripts > New IDE Script, name it Reload Project and populate it with:

dim proj as string = ProjectShellPath
DoCommand("CloseWindow")
OpenFile(proj)

You can then bind a key to your new Reload Project script (OS specific).

Or just hit Revert To Saved in the file menu ?

I was hoping that would work for me, but it does not. Basically, when I use Reload Project, it happens because I forgot to close the project before doing a merge in git, switching a branch, etc…

Revert to Saved only becomes active when you have changes that are not saved, not when something external (such as a SCM) changes the code, as far as I can tell.

Edit: Actually, now that I have the reload script, I no longer close and re-open the project manually. I leave it open, go do my commits, merge in other changes, switch branches, make a release, etc… then when returning from SCM work, just hit Cmd+Shift+R and the world is good.

The IDE’s find panel has its powers, but many times I just wish to do a quick find in the current method only and have the cursor go right to that spot. Pressing Find Next would then move the cursor to the next match, and when reaching the bottom of the file, start searching from the top again.

I have created two scripts to accomplish just that. I call them Find and Find Next. I bind Ctrl+F to File > IDE Scripts > Find.xojo_script and Ctrl+G to File > IDE Scripts > Find Next.xojo_script. On OS X, I have begun using KeyboardMaestro and am enjoying it quite a bit for all sorts of automated Xojo tasks and general keyboard tasks.

These scripts are likely to be modified and changed, so I have added them to my GitHub repo https://github.com/jcowgar/xojo-ide-scripts-misc

Find.xojo_script

[code]
//
// Setup
//

const kFilename = “~/.cowgar-xojo-find”

//
// Utility Methods
//

sub WriteFile(filename as String, content as String)
content = ReplaceAll(content, “”"", “”"")

call DoShellCommand("printf """ + content + """ > " + filename)

end sub

//
// Find Code
//

dim cursorPosition as Integer = SelStart
dim find as String = Input(“Find what?”)

if find.Trim = “” then
Beep
return
end if

dim pos as Integer = Instr(SelStart, Text, find)

if pos = 0 then
Beep
return
end if

SelStart = pos - 1

WriteFile("~/.cowgar-xojo-find", Str(pos) + “,” + find)[/code]

Find Next.xojo_script

[code]
//
// Setup
//

const kStateFilename = “~/.cowgar-xojo-find”

//
// Utility Methods
//

sub WriteFile(filename as String, content as String)
content = ReplaceAll(content, “”"", “”"")

call DoShellCommand("printf """ + content + """ > " + filename)

end sub

function ReadFile(filename as String) as String
return DoShellCommand("cat " + filename)
end function

function ReadFindData(byref startPosition as Integer, byref find as String) as Boolean
dim content as String = ReadFile(kStateFilename).Trim

if content = "" or InStr(content,",") = 0 then
  return false
end if

startPosition = Val(NthField(content, ",", 1))
find = NthField(content, ",", 2).Trim

return (find <> "")

end function

//
// Find Next
//

dim cursorPosition as Integer = SelStart
dim startPosition as Integer
dim find as String

if not ReadFindData(startPosition, find) then
Beep
return
end if

dim pos as Integer = Instr(startPosition + 1, Text, find)

WriteFile(kStateFilename, Str(pos) + “,” + find)

if pos = 0 then
Beep
return
end if

SelStart = pos - 1[/code]

Oh, I forgot to mention, the above will work only on Linux and OS X, IDE Scripting does not have file access, so I utilized a few shell commands to read/write files via the DoShellCommand call. They could probably be modified to work on Windows, I just am not sure of the shell commands needed.

Have you considered that you could write into a constant using ConstantValue instead of hitting the disk every time? Heck, you could probably just name the constant based on the thing you are searching and only store the position.

printf :

http://msdn.microsoft.com/en-us/library/windows/hardware/ff564716(v=vs.85).aspx

cat :

Greg, yes I did consider that and actually wrote the first version like that. I created a module XojoIdeScriptState where I could use this idea to store state between executions. I had two constants FindLastPos and FindText. (hence my thread: https://forum.xojo.com/16321-dead-code-stripping-strip-unused-modules-and-constants)

The problem comes in when you use SCM. That module now has to be checked into SCM, when branching, merging, committing, etc… it has to be constantly dealt with, just because you did a search. If you ignore that module, then your project will not open on another computer or with other developers you are working with. If you include the module, then it becomes quite a mess. Not a price I was willing to pay for the search functionality.

Do you have another idea how one could get around the SCM issue when using a module like this? I’d be great if the IDE would provide some mechanism to store state.

I don’t. Because I do a full code review before checking things in, I typically just revert those parts.

OK. When I commit, or people on my team, we do full code reviews also, but I tend to commit the smallest possible change that produces a positive effect, so I tend to commit very often. For me, I just don’t want to hit revert local changes all the time on this file just for the sake of searching.

Writing the file in Find.xojo_script takes 2.4ms, reading and writing the file in Find Next.xojo_script takes 4.9ms, so I don’t think it’s that big of a deal.

Sometimes it is nice to just hit a single key and see a complete diff of your project. I use git, but this can probably be adapted to any other SCM system. I named it Diff.xojo_script and I bind it to Ctrl+C (Mac OS X) for “Changes” since Ctrl+D is a key I use often (Delete).

  dim cmd as String
  cmd = "cd $PROJECT_PATH && git difftool"
  
  dim status as Integer
  dim result as String
  result = DoShellCommand(cmd, 3000, status)
  
  if status <> 0 then
    Print "Error: " + Str(status) + ": " + result
  end if

When writing Notes in Xojo, I always use Markdown format, as that is what XojoDoc understands. So, as I am writing, I’d like to get a preview of my note, formatted according to markdown.

So, I created this little script and bound it to ^W. I edit my note, press ^W. The first time, I then open it in Marked 2. There after, Marked 2 is watching the file and when I press ^W the next time, Marked 2 instantly shows me an updated view, scrolling to the place of my last change, of course.

  //
  // Utility Methods
  //
  
  sub WriteFile(filename as String, content as String)
    content = ReplaceAll(content, """", "\""")
    
    call DoShellCommand("printf """ + content + """ > " + filename)
  end sub
  
  //
  // Write the current editor content (hopefully a Note) to the file that Marked 2 will be showing
  //

  WriteFile("~/.xojo-view-note.md", Text)