Wednesday, December 3, 2014

Notepad++ Language Selector


Notepad++ Language Selector

I keep code samples that I find useful as small text files. I store them as vanilla txt files as opposed to the language in which they are written so that they will open in Notepad++ (NPP) instead of the editor. In other words, I don't want my c++ examples to open in an IDE, just notepad.

Notepad++ has syntax highlighting for various languages, but it is based on the file type. Therefore, all my SQL examples show up as normal text. I thought it would be nice if I could have NPP select the language format based on a simple keyword in the text file.

I asked this question 4 years ago on stackoverflow (the answer was that it couldn’t be done), and then I realized I could achieve this goal using the python plugin! I’m going to assume you already know how to use the python plugin for NPP and how to setup your environment. If not, refer to my post about custom timestamps in NPP.


Walkthrough

The first line of the file will start with "##", followed by the menucommand code for that language

The 3 step process:

  1. Define a function that will switch the language after the file is opened
  2. Write a command that links your function to the “File Opened” notification in NPP
  3. Put it all together


Step 1 and 2: Define your function and link to notification


#if found determine the menu command and switch language in NPP
def switch_language_view(args):
    notepad.activateBufferID(args["bufferID"])
    lineone = editor.getLine(0)
    if '##' in lineone:
     lineone = lineone[lineone.rfind('##'):].replace('##', '')
     lineone = "MENUCOMMAND." + lineone.upper()
     try:
      notepad.menuCommand( eval(lineone) )
     except:
      pass

#command to link notification
notepad.callback(switch_language_view, [NOTIFICATION.FILEOPENED])

  • This script grabs the first line of the file and looks for the command. After it finds the ## tag, it tries to send the menu command to notepad
  • Quick note about args: you need the args so that the script gets access to the current file being opened. Otherwise (as I discovered) it will read the first line of your code instead!
  • The last line is a separate call that links your function with the NPP event NOTIFICATION.FILEOPENED


Step 3: Put it all together

You have to place the code (both parts) in a special python script that will run when NPP starts. It’s called startup.py, and I pasted the above code at the end of that file, one after the other.

Some things to note about startup.py:
By default, this script is only run before you run your first python script. You want to change this behavior, so you need to change a configuration setting in the plugin.

  1. Menu: Plugins > Python Script > Configuration
  2. Switch Initialisation from “LAZY” to “ATSTARTUP” (there’s an explanation in the dialog)

On my PC, the startup.py script is located in the Program Files folder:
C:\Program Files (x86)\Notepad++\plugins\PythonScript\scripts\startup.py

This unfortunately means it might have some protective permissions. There are two things you could do to make your life somewhat easier:

  1. Open Notepad.exe (yes notepad) as an Administrator, which will allow you to save any changes
  2. Change the permissions on startup.py to allow Full Control for all users on your computer
I started out with option 1, but after some initial issues I switched to option 2 which made things much easier to debug using the Python Console in NPP.


Test Script

Setup the test script:

  1. Menu: Plugins > Python Script > New Python Script
  2. It will ask you for a new file name, I choose: switch_language.py
  3. A new tab will appear in NP++ for you to enter the script
  4. After saving, you should be able to run this code from the menu: Plugins > Python Script > Scripts > switch_language.py
  5. Make sure you have a test file active when you test the script!
  6. This script writes the result to the python console in NPP (make sure you have it displayed)


#This is the script I used (for testing):
#script to test switching language syntax of active file    
lineone = editor.getLine(0)
if '##' in lineone:
    lineone = lineone[lineone.rfind('##'):].replace('##', '')
    lineone = "MENUCOMMAND." + lineone.upper()
    try:
notepad.menuCommand( eval(lineone) )
   except:
     pass

console.write(lineone)


Example using the test script

Wednesday, November 19, 2014

Clipboard Timestamp

Clipboard Timestamp

Launchy that timestamp into your clipboard

.background

Looking back through my blog, one of my most popular posts was how to write a timestamp script for Notepad++ in Python. I've been finding myself wishing I had that feature in more and more place, including web apps.

I had the idea to write a script that would generate the timestamp I wanted, and then place it in the Windows clipboard. This would allow me to generate and paste a timestamp anywhere I wanted. I ended up writing 2 scripts, the first was in Python and later I wrote a second in Powershell. Each as their advantages and disadvantages detailed below.

.launch

I tried a few techniques for calling the script, but in the end I settled on a tool I already use, called Launchy. Launchy is a super-simple (cross platform) application launcher with some powerful extra features. One of these features is that it can call scripts, and it even gives focus back to the application I was using after it is done!

http://www.launchy.net

.python

It's extremely safe to say that I don't know Python, but I've been programming since I was very little so I know how to hack around a language. It took me longer to figure out the little intricacies of the language than to write the actual script. I found an example on stackoverflow and then incorporated it with my existing code from Notepad++.

The Python community has a couple different ways of accessing the clipboard, but the one I liked best was to use a built-in GUI library called Tkinter. I don't like having to install a separate library when a built-in method is available.

When you run the script, a command window flashes temporarily, which was annoying. In Windows just rename your script to “.pyw” to avoid this. There are similar solutions for other platforms, just in case you are interested.

You have to have Python installed for this script to work, which could be a big downside if you don't already have it installed. I don't have a problem with this, but I have a hard time recommending a script that requires that you install a toolset you may never use for anything else.

# cdate.pyw
# add date/time to clipboard
# output example: 10/14/2014 JMJ
import time, sys
s_time = "%s JMJ" % (time.strftime('%m-%d-%Y'))

#s_time contains the timestamp text, now add it to the clipboard
from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append(s_time)
r.destroy()

sys.exit(0)


references:
http://stackoverflow.com/questions/579687/how-do-i-copy-a-string-to-the-clipboard-on-windows-using-python/4203897#4203897
http://stackoverflow.com/questions/1689015/run-python-script-without-dos-shell-appearing

.powershell

While researching how to link my python script into Launchy, I ran into an article explaining how to launch powershell commands. It made a lot of sense to write the same script in Powershell, since no additional software would be required.

Powershell has a command called “clip” that allows you to pipe text directly into the Windows clipboard. Very nice. I had the command written in just a few minutes.

However, powershell scripts do not like to run without opening a command window. It is very annoying. I ended up using a technique where you create a VBS script (!!!) to call the powershell command. I feel weird about using VBS in this way, but it works. Unfortunately it requires you add a bunch of quotes to escape out all the layers of script calls (VBS > CMD > PowerShell). If you don't care about initials you can remove that part entirely. If your initials are “JMJ” perhaps you have it best of all.


‘pclip.vbs
'add date/time to clipboard via powershell (yes, there are a lot of escaped quotes in this code)
‘output example: 10/14/2014 JMJ
command = "powershell.exe -nologo -command (get-date -format d).ToString() + """""" JMJ"""""" | clip "
set shell = CreateObject("WScript.Shell")
shell.Run command,0


references:
http://technet.microsoft.com/en-us/library/ee692801.aspx
http://www.faqforge.com/windows/how-to-execute-powershell-scripts-without-pop-up-window

.set up Launchy

  1. Under the Launchy options, switch to the Catalog tab.
  2. Add a new Directory (+), and include the folder where your scripts are located.
  3. Under File Types, enter either *.pyw or *.vbs (depending on which solution you went with)

The great thing about Launchy is that it will return focus to the application I was using after I run the script. This makes the script very easy to call from other programs and online apps.

.wrap-up

I can't decide which is going to be more useful, having a simple timestamp available inside any program or website I'm using, or the fact that I can build more scripts and run them very easily through Launchy.

Wednesday, September 17, 2014

SSRS Color Wheel

SSRS (2005) Color Wheel

...more like a color list, but who's keeping score

I don't think there is anything in the development world more looked down upon than writing a report. It's kind of got a little shame attached to it. While your friends are (seemingly) out there creating the next Twitter you are stuck building a list of sales grouped by region. However, I have always been a little fond of it. I have an interest in design and layout, problem solving, and organizing data: reporting can touch on all of them.


Recently I had a request to change the color scheme of a report I was working with. This wasn't out of the ordinary except they weren't too sure what they wanted. It got to the point where I started to wonder if their significant other had similar thoughts when they shopped for paint.

However, our team had an idea - why not provide a report that listed all the default colors available in the system, along with all their official names. This had some immediate advantages:
  • The user could refer to a color they wanted by name
  • SSRS 2005 has a "bug" where colors on the report don't look the same when that report is exported to Excel
 
Now that's what I call a sexy report!

[The Plan]

I looked into different ways of building this report and came up with the plan below. Unfortunately I was not able to generate the color list completely in code. It got to the point where I thought I would have to build an external library to provide the list from System.Drawing, and I'm not a fan of maintaining a code library for a simple color list.

Instead, I built the list of available colors using a simple query. While this may seem a little rudimentary, it has the additional benefit of encouraging management to implement a standard color scheme. This could be the first step towards using the database to provide a standardized color palette for reporting.

I'm not big on providing downloads for examples. I feel that involves a level of trust that I cannot provide. So I explain how to do it below. I use SQL Server SSRS 2005 terms, because that's what the client is using.

[The Dataset]

MainDS:
-- manual list of colors in VS2005 system
Select 'Black' as [color_name] union all
Select 'White' union all
Select 'DimGray' union all
Select 'Gray' union all
Select 'DarkGray' union all
Select 'Silver' union all
Select 'LightGray' union all
Select 'Gainsboro' union all
Select 'WhiteSmoke' union all
Select 'Maroon' union all
Select 'DarkRed' union all
Select 'Red' union all
Select 'Brown' union all
Select 'Firebrick' union all
Select 'IndianRed' union all
Select 'Snow' union all
Select 'LightCoral' union all
Select 'RosyBrown' union all
Select 'MistyRose' union all
Select 'Salmon' union all
Select 'Tomato' union all
Select 'DarkSalmon' union all
Select 'Coral' union all
Select 'OrangeRed' union all
Select 'LightSalmon' union all
Select 'Sienna' union all
Select 'SeaShell' union all
Select 'Chocolate' union all
Select 'SaddleBrown' union all
Select 'SandyBrown' union all
Select 'PeachPuff' union all
Select 'Peru' union all
Select 'Linen' union all
Select 'Bisque' union all
Select 'DarkOrange' union all
Select 'BurlyWood' union all
Select 'Tan' union all
Select 'AntiqueWhite' union all
Select 'NavajoWhite' union all
Select 'BlanchedAlmond' union all
Select 'PapayaWhip' union all
Select 'Moccasin' union all
Select 'Orange' union all
Select 'Wheat' union all
Select 'OldLace' union all
Select 'FloralWhite' union all
Select 'DarkGoldenrod' union all
Select 'Goldenrod' union all
Select 'Cornsilk' union all
Select 'Gold' union all
Select 'Khaki' union all
Select 'LemonChiffon' union all
Select 'PaleGoldenrod' union all
Select 'DarkKhaki' union all
Select 'Beige' union all
Select 'LightGoldenrodYellow' union all
Select 'Olive' union all
Select 'Yellow' union all
Select 'LightYellow' union all
Select 'Ivory' union all
Select 'OliveDrab' union all
Select 'YellowGreen' union all
Select 'DarkOliveGreen' union all
Select 'GreenYellow' union all
Select 'Chartreuse' union all
Select 'LawnGreen' union all
Select 'DarkSeaGreen' union all
Select 'LightGreen' union all
Select 'ForestGreen' union all
Select 'LimeGreen' union all
Select 'PaleGreen' union all
Select 'DarkGreen' union all
Select 'Green' union all
Select 'Lime' union all
Select 'Honeydew' union all
Select 'SeaGreen' union all
Select 'MediumSeaGreen' union all
Select 'SpringGreen' union all
Select 'MintCream' union all
Select 'MediumSpringGreen' union all
Select 'MediumAquamarine' union all
Select 'Aquamarine' union all
Select 'Turquoise' union all
Select 'LightSeaGreen' union all
Select 'MediumTurquoise' union all
Select 'DarkSlateGray' union all
Select 'PaleTurquoise' union all
Select 'Teal' union all
Select 'DarkCyan' union all
Select 'Cyan' union all
Select 'Aqua' union all
Select 'LightCyan' union all
Select 'Azure' union all
Select 'DarkTurquoise' union all
Select 'CadetBlue' union all
Select 'PowderBlue' union all
Select 'LightBlue' union all
Select 'DeepSkyBlue' union all
Select 'SkyBlue' union all
Select 'LightSkyBlue' union all
Select 'SteelBlue' union all
Select 'AliceBlue' union all
Select 'DodgerBlue' union all
Select 'SlateGray' union all
Select 'LightSlateGray' union all
Select 'LightSteelBlue' union all
Select 'CornflowerBlue' union all
Select 'RoyalBlue' union all
Select 'MidnightBlue' union all
Select 'Lavender' union all
Select 'Navy' union all
Select 'DarkBlue' union all
Select 'MediumBlue' union all
Select 'Blue' union all
Select 'GhostWhite' union all
Select 'SlateBlue' union all
Select 'DarkSlateBlue' union all
Select 'MediumSlateBlue' union all
Select 'MediumPurple' union all
Select 'BlueViolet' union all
Select 'Indigo' union all
Select 'DarkOrchid' union all
Select 'DarkViolet' union all
Select 'MediumOrchid' union all
Select 'Thistle' union all
Select 'Plum' union all
Select 'Violet' union all
Select 'Purple' union all
Select 'DarkMagenta' union all
Select 'Fuchsia' union all
Select 'Magenta' union all
Select 'Orchid' union all
Select 'MediumVioletRed' union all
Select 'DeepPink' union all
Select 'HotPink' union all
Select 'LavenderBlush' union all
Select 'PaleVioletRed' union all
Select 'Crimson' union all
Select 'Pink' union all
Select 'LightPink'


[Extra Credit: Show each color's HTML Code color]

Report > Report Properties

References:

Added System.Drawing

Code:
Public Function HTMLColor(my_color as String) as String
Dim colorObj As System.Drawing.Color = System.Drawing.Color.FromName(my_color)
return String.Format("#{0:X2}{1:X2}{2:X2}", colorObj.R, colorObj.G, colorObj.B)
End Function

I got the meat of this function from a StackOverflow post:
http://stackoverflow.com/a/5207560/103131


[Layout]

Having everything in a query allowed me to get the most out of the layout options in SSRS. This made it really easy to setup a Table in the Layout to show what I wanted. I also added a column of White as a control. It really helped see the subtle differences in some of the lighter shades.

I put together a mock-up below:


[Column Name]: Property
[Color Name]: (value)=Fields!color_name.value
[Color]: (BackgroundColor)=Fields!color_name.value

[White]: (BackgroundColor)=White
[HTML Code]: (value)=Code.HTMLColor(Fields!color_name.Value)

I think this qualifies as a boring report, but it can be very useful when communicating which colors users want on their reports.

Tuesday, April 1, 2014

One Book Away, for Android

After nearly seven months (7 months!) since my final project for my Android program was completed, I have released it onto the app store. Introducing (formally)... One Book Away!

Go install it now at the Google Play store:
https://play.google.com/store/apps/details?id=com.mabon.onebook

If you like it, please leave a glowing review!

Now for some questions that no one is asking...


Where did this idea come from?
The idea for this app came to me a few years ago when I was trying to organize things I was waiting for at the library.  After placing holds on a few popular books or movies, I found they seemed to come all at the same time!  So I came up with a way to estimate how long I would have to wait for books and movies.

Originally, I thought it would be a greasemonkey script.  The only reason I decided to use Android was that I needed a project for my Android class and I couldn't think of anything else.  The first app was just a manual-entry calculator, but as I learned about the platform it grew into a full-blown useful app.

Some past iterations of the app:

Why did it take 7 months?
One of my instructors gave the advice to build something that you would find useful, then after building it decide if it would be useful to others.  At the very least you get something you find useful for the work you put in.  However, I ran into the problem of the app working well enough for me, so I wasn't as motivated to finish polishing it.  On top of that, I was only putting in about 1 day a week, and if a major issue arose it might take me 2 weeks to find a good solution.

What's your status?
I'm a full-time contractor, so I was looking for something to do on the side for fun.  I don't do any advertising for my apps, and I feel if I was ever going to look to do this more seriously it would be beneficial to me to keep publishing apps.

What got you into Android development?
I did some robotics development a few years ago that I very much liked.  The same bug that might render a web page incorrectly might cause your robot to turn left and run off the table.  Android development reminded me of that past, so I wanted to explore it further.

What do you think of Android development?
I've been on a c++ project for a few years, so getting back into Java was a little strange.  I don't like development that gets in my way, and I want it to be straight forward and just work.  Some parts are very nice, especially the xml files for the layout and strings.  Other parts I'm not so hot on, like the amount of code it takes to do what appears to be a simple task.

It took a while to get used to Eclipse coming from the easy debugging style of Visual Studio.  I switched to Android Studio as soon as I could, but in hindsight I think I should have waited until it was more stable.  In a lot of ways Android Studio held me up the most.

What's next?
Believe it or not, I have 2-3 more ideas I'm eager to start on.  I'd also like to work with someone fun to help keep the project moving, and keep it from being such a lonely process.