From ad8bd21df1fd356aa0992fa3b0647ce03783dc86 Mon Sep 17 00:00:00 2001 From: phil294 Date: Thu, 20 Jul 2023 11:02:01 +0200 Subject: [PATCH] Add Sort --- README.md | 8 +++--- docs/index.html | 14 ++++----- src/cmd/string/sort.cr | 65 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 src/cmd/string/sort.cr diff --git a/README.md b/README.md index cc82d04..ff6fda1 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ AHK_X11 can be used completely without a terminal. You can however if you want u
CLICK TO SEE WHICH COMMANDS ARE IMPLEMENTED AND WHICH ARE MISSING. Note however that this is not very representative. For example, no `Gui` sub command is included in the listing. For a better overview on what is already done, skim through the FULL DOCUMENTATION HERE. ```diff -DONE ?% (107/220): +DONE ?% (108/220): + Else, { ... }, Break, Continue, Return, Exit, GoSub, GoTo, IfEqual, Loop, SetEnv, Sleep, FileCopy, + SetTimer, WinActivate, MsgBox, Gui, SendRaw, #Persistent, ExitApp, + EnvAdd, EnvSub, EnvMult, EnvDiv, ControlSendRaw, IfWinExist/IfWinNotExist, SetWorkingDir, @@ -70,7 +70,7 @@ DONE ?% (107/220): + WinGetTitle, WinGetClass, PixelGetColor, CoordMode, GuiControl, ControlGetPos, ControlGetText, + WinGet, Input, Loop (parse a string), ToolTip, If var [not] in/contains MatchList, ControlSetText, + PixelSearch, #Include, InputBox, ClipWait, EnvSet, SetKeyDelay, SetMouseDelay, MouseClickDrag, -+ #NoTrayIcon, TrayTip, Random, Shutdown, RunAs, SoundGet, SoundSet, SoundPlay ++ #NoTrayIcon, TrayTip, Random, Shutdown, RunAs, SoundGet, SoundSet, SoundPlay, Sort NEW ?% (9/220): (not part of spec or from a more recent version) @@ Echo, ahk_x11_print_vars, FileRead, RegExGetPos, RegExReplace, EnvGet, Click @@ @@ -85,7 +85,7 @@ REMOVED ?% (11/220): # AutoTrim: It's always Off. It would not differentiate between %a_space% and %some_var%. # It's possible but needs significant work. -TO DO ?% (89/220): alphabetically +TO DO ?% (88/220): alphabetically - BlockInput, Control, ControlFocus, ControlGet, ControlGetFocus, - ControlMove, - DetectHiddenText, DetectHiddenWindows, Drive, DriveGet, DriveSpaceFree, @@ -100,7 +100,7 @@ TO DO ?% (89/220): alphabetically - Process, Progress, SetBatchLines, - SetCapslockState, SetControlDelay, SetDefaultMouseSpeed, SetFormat, - SetNumlockState, SetScrollLockState, SetStoreCapslockMode, SetTitleMatchMode, -- SetWinDelay, Sort, SoundGetWaveVolume, +- SetWinDelay, SoundGetWaveVolume, - SoundSetWaveVolume, SplashImage, SplashTextOn, SplashTextOff, SplitPath, StatusBarGetText, - StatusBarWait, StringCaseSense, StringSplit, StringTrimLeft, StringTrimRight, - SysGet, Thread, Transform, WinActivateBottom, diff --git a/docs/index.html b/docs/index.html index 459f5b2..9a4f634 100644 --- a/docs/index.html +++ b/docs/index.html @@ -590,7 +590,7 @@

Table of contents

SetFormat
  • - Sort + Sort
  • StringCaseSense @@ -2586,7 +2586,7 @@

    The "Last Found" Window

    Waits the specified amount of time before continuing. - Sort + Sort Arranges a variable's contents in alphabetical or numerical order. @@ -11869,7 +11869,7 @@

    Examples

    MsgBox But the file is not open in either Metapad or Notepad. -
    +
    #

    Sort

    [v1.0.13+]
    @@ -11907,14 +11907,14 @@

    Examples

    N: Numeric sort: Each item is assumed to be a number rather than a string (for example, if this option is not present, the string 233 is considered to be less than the string 40 due to alphabetical ordering). Both decimal and hexadecimal strings (e.g. 0xF1) are considered to be numeric. Strings that don't start with a number are considered to be zero for the purpose of the sort. Numbers are treated as 64-bit signed values.

    Pn: Sorts items based on character position n (do not use hexadecimal for n). If this option is not present, n defaults to 1, which is the position of the first character. The sort compares each string to the others starting at its nth character. If n is greater than the length of any string, that string is considered to be blank for the purpose of the sort. When used with option N (numeric sort), the string's character position is used, which is not necessarily the same as the number's digit position.

    R: Sorts in reverse order (alphabetically or numerically depending on the other options).

    -

    Random [v1.0.24+]: Sorts in random order. This option causes all other options except D and Z to be ignored. Examples:
    Sort, MyVar, Random
    Sort, MyVar, Random Z D|

    +

    Random Sorts in random order. This option causes all other options except D and Z to be ignored. Examples:
    Sort, MyVar, Random
    Sort, MyVar, Random Z D|

    Z: To understand this option, consider a variable that contains RED`nGREEN`nBLUE`n. If the Z option is not present, the last linefeed (`n) is considered to be part of the last item, and thus there are only 3 items. But by specifying the Z option, the last linefeed (if present) will be considered to delimit a blank item at the end of the list, and thus there are 4 items (the last being blank).

    -

    \ (backslash): Sorts items based on the substring that follows the last backslash in each. If an item has no backslash, the entire item is used as the substring. This option is useful for sorting bare filenames (i.e. excluding their paths). In the example below, the AAA.txt line is sorted above the BBB.txt line because their directories are ignored for the purpose of the sort:
    C:\BBB\AAA.txt
    C:\AAA\BBB.txt
    Note: Options N and P are ignored when the backslash option is present.

    +

    \ (backslash): Sorts items based on the substring that follows the last backslash in each. If an item has no backslash, the entire item is used as the substring. This option is useful for sorting bare filenames (i.e. excluding their paths). In the example below, the AAA.txt line is sorted above the BBB.txt line because their directories are ignored for the purpose of the sort:
    C:\BBB\AAA.txt
    C:\AAA\BBB.txt
    Note: Options N and P are ignored when the backslash option is present.

     

    Remarks

    This command is typically use to sort a variable that contains a list of lines, with each line ending in a linefeed (`n) character.

    -

    If VarName is clipboard and the clipboard contains files (such as those copied from an open Explorer window), those files will be replaced with a sorted list of their filenames. In other words, after the operation, the clipboard will no longer contain the files themselves.

    -

    If VarName is an environment variable, a script variable will be created to take its place. To put the sorted contents back into the environment variable and force the script to access it in the future, use this example:
    VarSort, MyEnvVar
    EnvSet, MyEnvVar, %MyEnvVar%
    MyEnvVar = ; make the script's variable blank so that MyEnvVar will be retrieved from the environment in the future.

    +

    If VarName is clipboard and the clipboard contains files (such as those copied from an open Explorer window), those files will be replaced with a sorted list of their filenames. In other words, after the operation, the clipboard will no longer contain the files themselves.

    +

    If VarName is an environment variable, a script variable will be created to take its place. To put the sorted contents back into the environment variable and force the script to access it in the future, use this example:
    VarSort, MyEnvVar
    EnvSet, MyEnvVar, %MyEnvVar%
    MyEnvVar = ; make the script's variable blank so that MyEnvVar will be retrieved from the environment in the future.

    The maximum capacity of a variable can be increased via #MaxMem.

    If a large variable was sorted and later its contents are no longer needed, you can free its memory by making it blank, e.g. MyVar =

     

    diff --git a/src/cmd/string/sort.cr b/src/cmd/string/sort.cr new file mode 100644 index 0000000..36d5f6d --- /dev/null +++ b/src/cmd/string/sort.cr @@ -0,0 +1,65 @@ +# Sort, VarName [, Options] +class Cmd::String::Sort < Cmd::Base + def self.min_args; 1 end + def self.max_args; 2 end + def run(thread, args) + var = args[0] + old_value = thread.get_var(var) + opt = args[1]? || "" + delimiter = '\n' + d_index = opt.index('D') + if d_index + d_char = opt[d_index + 1]? + delimiter = d_char if d_char + end + case_sensitive = opt.includes?('C') + numeric = opt.includes?('N') + p_index = opt.index('P') + pos = 1 + if p_index + p_char = opt[p_index + 1]? + pos = p_char.to_i if p_char + end + pos -= 1 + reverse = opt.includes?('R') + random = opt.includes?("Random") + rand = ::Random.new + z_option = opt.includes?('Z') + split = old_value.split(delimiter) + if ! z_option + if split.last? + if split.last.empty? + split.pop + split[split.size - 1] += delimiter + end + end + end + sorted = split.sort do |a, b| + puts "sort iter" + if random + next rand.next_bool ? 1 : -1 + end + if pos > 0 + a = a[pos..]? || "" + b = b[pos..]? || "" + end + if numeric + a = a.to_f + b = b.to_f + ret = a <=> b + else + if ! case_sensitive + a = a.downcase + b = b.downcase + end + ret = a <=> b + end + ret + end + if reverse + sorted.reverse! + end + new_value = sorted.join(delimiter) + thread.runner.set_user_var(var, new_value) + end +end \ No newline at end of file