Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Why should you prefer autohotkey over python?


  • Please log in to reply
30 replies to this topic
skyd1v3r
  • Members
  • 73 posts
  • Last active: Apr 18 2010 11:42 AM
  • Joined: 18 Jun 2009
Once again someone tried to explain what I obviously understand.

As I said just before, there are no bugs but the correct proceeder.
Yet, the results are far apart from what people would except.
Whenever the string false is written to a variable although there are no quotationmarks , and that string, as not empty, is interpreted as true, code is likely to go havoc.

Yet, as I stated in my original post, working on the habbit of always using expression mode like If() and := is working on a habbit against bugs.

My conclusion is that there should be some command - SetExpressionMode,On or #ExpressionOnly - disabling the = operator completely. Only := and == (to be created) shall remain, all If-statements shall then be considered s If().

And guys, now stopo explaining why my above code does not work, or why my statements are wrong. I intentionally wrote what I wrote, to show some common bugs.

Tuncay
  • Members
  • 1943 posts
  • Last active: Apr 08 2012 06:07 AM
  • Joined: 07 Nov 2006
The explanations are not only going to you. There are other readers too. Btw, this is not the topic.^^

One more reason is, I can convert my scripts fastly into exe files and give them without problems to others. Where python scripts are not that easy (I know there is somewhere a solution).

n-l-i-d
  • Guests
  • Last active:
  • Joined: --
Let me give you an example of the similarities with many main languages (like Python). Here is a Perl script from here (a AdBlock to BFilter blocklist converting script).

#!/usr/bin/perl

use strict;               # to catch stupid errors

#
# BFilter directives for blocking and exempting Adblock Plus URL patterns
# (Strong and weak versions required, see comments below)
#
my $BLOCK_PREFIX_STRONG = "++++++";
my $BLOCK_PREFIX_WEAK = "+++";
my $EXEMPT_PREFIX_STRONG = "ALLOW";
my $EXEMPT_PREFIX_WEAK = "---";

#
# The main loop
#
while (defined(my $thisLine = <STDIN>))
{
    print processLine(trim($thisLine));
}
exit;


####################################
# Subroutines
####################################

#
# Process a single line from STDIN
#
sub processLine()
{
    # The incoming line has been stripped of leading and trailing
    # white space and the terminating newline.
    my ($line) = @_;

    # Copy blank lines
    if ($line =~ m/^$/)
    {
        return "\n";
    }

    # Handle comment and Adblock Plus header lines
    if ($line =~ m/^[\[!]/)
    {
        return "# $line\n";;
    }

    # Handle unimplemented lines
    # (These are Adblock Plus element-hiding patterns)
    if ($line =~ m/#/)
    {
        return "# <Element> $line\n";
    }

    # See if this is an Exception pattern
    # If so, strip "@@" from the front of the line.
    my $isException = ($line =~ m/^@@/);
    if ($isException)
    {
        $line =~ s/^@@//;
    }

    # Is the pattern already in regex form?
    my $isRegEx = ($line =~ m/^\/.*\/$/);

    # Used to construct the output line.
    my $prefix;
    my $pattern;

    # We process regex patterns differently from others.
    if ($isRegEx)
    {
        # Use the existing regex with an appropriate BFilter prefix.
        $prefix = $isException ? $EXEMPT_PREFIX_STRONG : $BLOCK_PREFIX_STRONG;
	$pattern = $line;
    }
    else
    {
        # If the pattern includes "filter options", which BFilter cannot support,
	# strip them from the line and use a weak BFilter prefix.
        my $isWeak = ($line =~ m/\$/);
        if ($isWeak)
        {
            $line =~ s/\$.*//;
        }

        # Check to see whether the pattern is anchored at one or both ends
	# if so, strip the anchor characters from the line.
        my $anchoredStart = ($line =~ m/^\|/);
        my $anchoredEnd = ($line =~ m/\|$/);
	if ($anchoredStart || $anchoredEnd)
	{
	    $line =~ s/\|//g;
	}

	# Remove redundant strings of wildcards
	$line =~ s/\*+/\*/g;

	# If the pattern contains a literal '?', we need to convert it 
	# to a regex because '?' is used as a wild card in BFilter.
        my $convertToRegEx = ($line =~ m/\?/);
        if ($convertToRegEx)
        {
	    # We replace ? with \? in the output regex.
	    # We also need to escape certain other characters that
	    # have special meaning in a regex: . + \
            $line =~ s/([\?\/\.\+])/\\\1/g;

	    # Are there wildcards at the unanchored beginning and/or end 
	    # of a pattern? If so, remove them now.
	    if (!$anchoredStart)
	    {
	        $line =~ s/^\*//;
	    }
	    if (!$anchoredEnd)
	    {
	        $line =~ s/\*$//;
	    }

	    # Translate * to .* in the regex.
            $line =~ s/[\*]/\.\*/g;

            # Build the regex version of the pattern.
	    $pattern = "/";
	    if ($anchoredStart)
	    {
	        $pattern = $pattern . '^';
	    }
	    $pattern = $pattern . $line;
	    if ($anchoredEnd)
	    {
	        $pattern = $pattern . '$';
	    }
	    $pattern = $pattern . "/";
        }
        else
        {
	    # regex not required. Construct an output pattern with
	    # appropriate anchoring.
	    $pattern = "";
	    if (!$anchoredStart)
	    {
	        # Add a wildcard if there is not already one at the start.
		if (!($line =~ m/^\*/))
		{
		    $pattern = $pattern . "*";
		}
	    }
	    $pattern = $pattern . $line;
	    if (!$anchoredEnd)
	    {
	        # Add a wildcard if there is not already one at the end.
		if (!($line =~ m/\*$/))
		{
		    $pattern = $pattern . "*";
		}
	    }
        }

        # Use the approprite prefix - weak or strong.
        if ($isException)
        {
            $prefix = $isWeak ? $EXEMPT_PREFIX_WEAK : $EXEMPT_PREFIX_STRONG;
        }
        else
        {
            $prefix = $isWeak ? $BLOCK_PREFIX_WEAK : $BLOCK_PREFIX_STRONG;
        }
    }

    return "$prefix $pattern\n";
}

#
# Remove the newine from the string then
# strip leading and trailing white space.
#
sub trim()
{
    my ($string) = @_;

    chomp $string;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;

    return $string;
}

Here is my conversion of the bulk of the script into AutoHotkey

BLOCK_PREFIX_STRONG := "++++++"
BLOCK_PREFIX_WEAK := "+++"
EXEMPT_PREFIX_STRONG := "ALLOW"
EXEMPT_PREFIX_WEAK := "---"

FileDelete, output.txt

Loop, Read, input.txt, output.txt
{
	a := A_LoopReadLine
	b := a
	
	; blank lines
	If RegExMatch(a, "^$")
	{
		FileAppend `n
		Continue
	}
		
	; comment and header lines
	If RegExMatch(a, "^[\[!]")
	{
		FileAppend # %a%`n
		Continue
	}
	
	; unimplemented element handlers
	If RegExMatch(a, "#")
	{
		FileAppend # <Element> %a%`n
		Continue
	}

	; is exception?
	isException := RegExMatch(b, "^@@")
	If (isException)
		StringTrimLeft, b, b, 2
		
	; is regex?
	isRegEx := RegExMatch(b, "^\/.*\/$")
	If (isRegEx)
	{
		prefix := isException ? EXEMPT_PREFIX_STRONG : BLOCK_PREFIX_STRONG
		pattern := b
	}
	Else
	{
		isWeak := RegExMatch(b, "\$")
    If (isWeak)
			b := RegExReplace(b, "(.*)\$.*", "$1")

		anchoredStart := RegExMatch(b, "^\|")
    anchoredEnd := RegExMatch(b, "\|$")		
		If (anchoredStart) OR (anchoredEnd)
			b := RegExReplace(b, "\|", "")
	
		b := RegExReplace(b, "\*+", "*")
	
		convertToRegEx := RegExMatch(b, "\?")
		If (convertToRegEx)
		{
			b := RegExReplace(b, "([\?\/\.\+])", "\$1")	
	
			If !(anchoredStart)
				b := RegExReplace(b, "^\*", "")
		
			If !(anchoredEnd)
				b := RegExReplace(b, "\*$", "")
			
			b := RegExReplace(b, "[\*]", ".*")
			
			pattern := "/"
			
			If (anchoredStart)
				pattern .= "^"
				
			pattern .= b
			
			If (anchoredEnd)
				pattern .= "$"
			
			pattern .= "/"
		}
		Else
		{
			pattern := ""
			
			If !(anchoredStart)
			{
				If !(RegExMatch(b, "^\*"))
					pattern .= "*"
			}
			
			pattern .= b
			
			If !(anchoredEnd)
			{
				If !(RegExMatch(b, "\*$"))
					pattern .= "*"
			}
		}
		
		If (isException)
      prefix := isWeak ? EXEMPT_PREFIX_WEAK : EXEMPT_PREFIX_STRONG
    Else
      prefix := isWeak ? BLOCK_PREFIX_WEAK : BLOCK_PREFIX_STRONG

		FileAppend %prefix% %pattern%`n
	}	
}

AutoHotkey is really not that difficult to understand and use for someone with a background in a "proper" language, and thus, again, in no sense a "joke". Sure, you can mess up if you treat AHK as a "proper" language, but that's something completely different.

n-l-i-d
  • Guests
  • Last active:
  • Joined: --
Here is the entire script, with the cmd/bat on the site incorporated.

cmd/bat of site:

@ECHO OFF
:: Path to files and URL
SET EASYLIST_URL=http://adblockplus.mozdev.org/easylist/abp_tracking+easylist.txt
SET TEMP_FILE=c:\windows\temp\bfilterlist.tmp
SET LOCAL_LIST_FILE="c:\Program Files\BFilter\conf\urls.local.save"
SET OUTPUT_FILE="c:\Program Files\BFilter\conf\urls.local"
:: Path to executables
SET PERL=c:\perl\bin\perl.exe
:: Get Perl from here: http://www.activestate.com/downloads/
SET WGET=c:\windows\wget.exe
:: Get Wget from here: http://www.christopherlewis.com/WGet/WGetFiles.htm
SET CONVERTER=c:\perl\bin\adblock2bfilter.pl
SET BFILTER="c:\Program Files\BFilter\bfilter.exe"

:: Pull down the list, pipe it to the converter and then pipe output to a temporary file
%WGET% -q -O - %EASYLIST_URL% | %PERL% %CONVERTER% > %TEMP_FILE%

:: If the temp file (finished bfilter list) exists then
:: Output a message and check if there is a local list file
:: If there is a local list file, append it to the new bfilter
:: and delete the temp file, and echo a message about it.
:: If there isn't a local list file, just move it.

if exist %TEMP_FILE% (
	echo Updating BFilter URLs: && if exist %LOCAL_LIST_FILE% (
		copy /Y %TEMP_FILE%+%LOCAL_LIST_FILE% %OUTPUT_FILE% && del /Q %TEMP_FILE% && echo Added local list file) else ( 
		move /Y %TEMP_FILE% %OUTPUT_FILE%))
		
:: Check if BFilter is running and if it is, kill it
tasklist | find /i "bfilter.exe"

:: If the FIND command above returns with an error it will skip the IF NOT
:: the IF NOT command checks to see if FIND returns with something other than 0 or 1. if so its
:: safe to assume the process was found and is running.

:: Also, killing the BFilter process is interesting. Couple points:
:: * There doesn't seem to be a normal way to tell a program to exit, not on the command line.
:: * Because of this, killing BFilter will cause a window to pop up complaining it was killed
:: * If you try to restart BFilter while that window is still open, it'll fail to bind to
::     127.0.0.1:8080 because the previous BFilter is still bound to it.
:: * Ugly solution: kill the window that pops up as well. Don't know how well this might work on
::     other versions of Windows, or even different setups. 

if errorlevel 0 if not errorlevel 1 (
	echo Killing the BFilter process ...
	taskkill /IM "bfilter.exe" && taskkill /F /IM "dwwin.exe" )

:: Start/Restart BFilter
:: Okay, we need to use start with a title - between the double quotes - 
:: because without it the cmd window hangs waiting for BFilter to exit. Which isn't
:: going to happen. Same if you don't use start.

echo Starting BFilter ...
start "BFilter" %BFILTER%

echo Done.

AHK script conversion of both perl-script and cmd/bat:

#NoEnv
#SingleInstance force
SetBatchLines -1

easylistUrl := "http://easylist.adblockplus.org/easylist.txt"
convFilePath := A_TEMP . "\bfilterlist.tmp"
easylistFilePath := A_TEMP . "\easylist.txt"
localListFilePath := A_ProgramFiles . "\BFilter\conf\urls.local.save"
localFilePath := A_ProgramFiles . "\BFilter\conf\urls.local"
bfilterPath := A_ProgramFiles . "\BFilter\bfilter.exe"

UrlDownloadToFile, %easylistUrl%, %easylistFilePath%
If ErrorLevel
{
  MsgBox Error downloading easylist`, exiting...
  ExitApp
}

BLOCK_PREFIX_STRONG := "++++++"
BLOCK_PREFIX_WEAK := "+++"
EXEMPT_PREFIX_STRONG := "ALLOW"
EXEMPT_PREFIX_WEAK := "---"

Loop, Read, %easylistFilePath%, %convFilePath%
{

	a := A_LoopReadLine
	b := a
	
	; blank lines
	If RegExMatch(a, "^$")
	{
		FileAppend `n
		Continue
	}
		
	; comment and header lines
	If RegExMatch(a, "^[\[!]")
	{
		FileAppend # %a%`n
		Continue
	}
	
	; unimplemented element handlers
	If RegExMatch(a, "#")
	{
		FileAppend # <Element> %a%`n
		Continue
	}

	; is exception?
	isException := RegExMatch(b, "^@@")
	If (isException)
		StringTrimLeft, b, b, 2
		
	; is regex?
	isRegEx := RegExMatch(b, "^\/.*\/$")
	If (isRegEx)
	{
		prefix := isException ? EXEMPT_PREFIX_STRONG : BLOCK_PREFIX_STRONG
		pattern := b
	}
	Else
	{
		isWeak := RegExMatch(b, "\$")
    If (isWeak)
			b := RegExReplace(b, "(.*)\$.*", "$1")

		anchoredStart := RegExMatch(b, "^\|")
    anchoredEnd := RegExMatch(b, "\|$")		
		If (anchoredStart) OR (anchoredEnd)
			b := RegExReplace(b, "\|", "")
	
		b := RegExReplace(b, "\*+", "*")
	
		convertToRegEx := RegExMatch(b, "\?")
		If (convertToRegEx)
		{
			b := RegExReplace(b, "([\?\/\.\+])", "\$1")	
	
			If !(anchoredStart)
				b := RegExReplace(b, "^\*", "")
		
			If !(anchoredEnd)
				b := RegExReplace(b, "\*$", "")
			
			b := RegExReplace(b, "[\*]", ".*")
			
			pattern := "/"
			
			If (anchoredStart)
				pattern .= "^"
				
			pattern .= b
			
			If (anchoredEnd)
				pattern .= "$"
			
			pattern .= "/"
		}
		Else
		{
			pattern := ""
			
			If !(anchoredStart)
			{
				If !(RegExMatch(b, "^\*"))
					pattern .= "*"
			}
			
			pattern .= b
			
			If !(anchoredEnd)
			{
				If !(RegExMatch(b, "\*$"))
					pattern .= "*"
			}
		}
		
		If (isException)
      prefix := isWeak ? EXEMPT_PREFIX_WEAK : EXEMPT_PREFIX_STRONG
    Else
      prefix := isWeak ? BLOCK_PREFIX_WEAK : BLOCK_PREFIX_STRONG

	}
  FileAppend %prefix% %pattern%`n	
}

IfExist %localListFilePath%
{
  FileRead, llfContents, %localListFilePath%
  FileAppend, %llfContents%, %convFilePath%
}

FileMove, %convFilePath%, %localFilePath%, 1

Process, Exist, bfilter.exe
If ErrorLevel
  Process, Close, bfilter.exe

Run % bfilterPath

I can put this in a ~250k executable. No need for Perl, no need for wget.

Tuncay
  • Members
  • 1943 posts
  • Last active: Apr 08 2012 06:07 AM
  • Joined: 07 Nov 2006
Thats a wonderful example, thanks.

I like AutoHotkey also for its size. And for execution of scripts, nothing else than the interpreter AutoHotkey.exe is needed. And the portability for usage on USB-Sticks (I have allways a copy of AutoHotkey.exe on my stick) makes it a perfect tool if you help others.

n-l-i-d
  • Guests
  • Last active:
  • Joined: --
Little update: I informed the webmaster of the site I mentioned of the AdBlock2BFilter script, and he put it on his site.

8)

lrh9
  • Members
  • 102 posts
  • Last active: Mar 14 2011 08:33 PM
  • Joined: 10 Jun 2009
I like how easy it is to create dynamic scripts in ahk. I know you can use about any other language to create dynamics programs, but it requires so much extra effort.

I like the way:

AHK is typeless.
Variables can take the place of function names.
You can use the contents of variables as variable names.
AHK is able to utilize high level Windows functionality.
AHK is interpreted.

n-l-i-d
  • Guests
  • Last active:
  • Joined: --

That's why it would be good if AHK the library would be separated from AHK the language. This way everyone could use the language one likes. You AHK, me Python.


Just FYI: The language might not be separate from the engine, but you could create an interop, there is already an AutoHotkey.dll. Have a look at the top section of the Wiki - Script Listing for ideas.

HTH

Lexikos
  • Administrators
  • 9441 posts
  • Last active:
  • Joined: 17 Oct 2006
If you really want to use Python, you could host Python within AutoHotkey as Thrawn has done for Lua...

  • Guests
  • Last active:
  • Joined: --
Would it be hard to separate the library from the language, btw? The separation seems logical even from a source code organization viewpoint.

Why mix the two in the first place?

Chicken Pie 4 Tea
  • Members
  • 379 posts
  • Last active: Jun 17 2014 06:29 AM
  • Joined: 18 Aug 2009
autohotkey is so simply to install or use on a usb
it is also far easier, I looked at Python, looked far more complicated and not as user friendly.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: Oct 02 2013 02:33 PM
  • Joined: 24 May 2006
Not comparable IMO.
Altho a bit more comparable with AHK_L.

m^2
  • Members
  • 100 posts
  • Last active: Mar 01 2011 09:31 AM
  • Joined: 28 Feb 2008
Recently, I was looking for a general purpose scripting language and chose Python. AHK was also one of considered choices. I knew AHK somewhat and Python - not at all. The main reason against AHK were troubles related to Unicode. But now I'm very happy with the choice. Like sb. pointed out already, some things take more coding than it would be necessary, because Python is much more safety-oriented. It's still bugging me sometimes. But nontheless it's hugely productive for almost any task that I needed it to. And it's much, much cleaner, more readable, more maintainable. AHK was always a mess for me and Python is one of the better ones in this regard.
*nix? I never used any regularly, I'm a pure Windows user and don't find Python to be *nix oriented. It's portability oriented - which is a great feature.

As to need for installation - there's movpy, it's USB-portable and doesn't need to be installed.

Though for hotkey scripting AHK would be obviously better. I didn't need it yet, but if I ever do, I'd choose AHK or AI (the former is preferable because of being FOSS).

JoeSchmoe
  • Members
  • 304 posts
  • Last active: Feb 28 2013 05:39 PM
  • Joined: 17 Feb 2008
It sounds like guest knows the language pretty well.

Personally, I've spent about 1 or 2% of the time I've spent programming AHK on figuring out the whole expressions vs. nonexpression thing. Yeah, it's stupid. But the rest of the language is so cool that I don't mind. Now I find it incredibly easy to bang out code that does what I want it to.

I regularly maintain a 3000 line program. I've considered porting it to C#, but decided it just wasn't worth it. AHK does everything I want it to and I love it.

JoeSchmoe
  • Members
  • 304 posts
  • Last active: Feb 28 2013 05:39 PM
  • Joined: 17 Feb 2008

I like how easy it is to create dynamic scripts in ahk. I know you can use about any other language to create dynamics programs, but it requires so much extra effort.

I like the way:

AHK is typeless.
Variables can take the place of function names.
You can use the contents of variables as variable names.
AHK is able to utilize high level Windows functionality.
AHK is interpreted.

Yes the more time passes, the more I realize I absolutely LOVE this. It's really changed the way I program. (I learned to program in C.)