Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1: Added A_Comma, A_DQ/A_SQ, A_CR/A_CRLF/A_LF. #295

Closed
wants to merge 1 commit into from

Conversation

jeeswg
Copy link
Contributor

@jeeswg jeeswg commented Aug 17, 2022

Documentation

A_Comma. This variable contains a comma character.
A_CR. This variable contains a carriage return (CR) character.
A_CRLF. This variable contains two characters: a carriage return (CR) and a newline (linefeed/LF).
A_DQ. This variable contains a double-quote mark.
A_LF. This variable contains a newline (linefeed/LF) character.
A_SQ. This variable contains a single-quote mark.

Descriptions based on:
Escape Sequences - Definition & Usage | AutoHotkey v2
Variables and Expressions - Definition & Usage | AutoHotkey v2

There is a precedent for SQ and DQ:
Syntax - IBM Documentation
Computing Fundamentals and Programming in C - Nasib Singh Gill - Google Books

Comments

A_DQ / A_SQ

I define and use a custom DQ variable for double quotes very very regularly, and would benefit greatly from a BIV (built-in variable).
(E.g. in my main function libs: vDQ := Chr(34) appears 57 times, Chr(34) appears 395 times.)
Quite often, I'm writing some quick code, and I wish that A_DQ were available.

I've tried A_Quote, but it uses too much screen real estate, so is impractical for many use cases such as: command-line strings, or strings with multiple quote characters. It is as long as Chr(34), 7 characters, which is also rather long.

Also, if it was A_Quote, what about a single quote equivalent? A_Apos for apostrophe? Hence A_DQ and A_SQ.

Comparisons: the BIVs are short, readable from a distance, meaningful ('DQ' v. '34') and v1/v2 compatible:

A_DQ (proposal)
"""" (AHK v1)
"`"" (AHK v2)
'"' (AHK v2)
Chr(34) (AHK v1/v2)
Chr(0x22) (AHK v1/v2)

A_SQ (proposal)
"'" (AHK v1/v2)
'`'' (AHK v2)
Chr(39) (AHK v1/v2)
Chr(0x27) (AHK v1/v2)

A_CR / A_CRLF / A_LF

E.g. VBA has vbCrLf, vbCr, vbLf and vbTab, amongst others.
Miscellaneous constants | Microsoft Docs

I chose all capital letters, because they're easier to type and look more elegant. (You can hold shift the whole time.)

Some uses:

  • To clearly signal that a line ending character is being used, and which character.
  • Using variable names makes it easier to change pad strings at a later date. I.e. replacing variable names, and not characters within literal strings.
  • When working simultaneously in AutoHotkey and other languages, where the escape character differs, it is easier to avoid escape characters, and use variables instead. (In the simplest scenario, anything in quotes is literal, with escaped characters stored as variables.)
  • ... And it is easier to use variables than to try to repeatedly replace/un-replace escape characters (which can easily go wrong, e.g. \\\n).
  • "abc`ndef" is bad for spellchecking versus "abc`n" "def" or "abc" A_LF "def". I.e. there is no word 'ndef'.
  • When working with VBA, you can copy over code that contains vbCrLf or equivalent, and just replace the variable names, without worrying about defining variables.
  • Converting var = "abc" "def" lines in AHK v1, in preparation for AHK v2. With A_DQ unavailable, you have to pick a short but custom variable (requiring storing a variable definition somewhere), or the long and readability-reducing but universal Chr(34). A_DQ, short and universal, gives you a simple solution.

A_Comma

Useful to make it more explicit that a comma is being used.
E.g. in a function call full of literal and parameter-separating commas.
Or similarly for a command in AHK v1.

Also, in situations where there are known to be no literal commas, quick-and-dirty parsing algorithms can be written more simply.

Test code

;==================================================

;test code: A_Comma, A_DQ/A_SQ, A_CR/A_CRLF/A_LF (AHK v1)

;==================================================

;6 new variables, 2 existing variables:
;alphabetical order: A_Comma, A_CR, A_CRLF, A_DQ, A_LF, (A_Space), A_SQ, (A_Tab)

Assert(A_Space, " ")
Assert(A_Tab, "`t")
Assert(A_Comma, ",")
Assert(A_DQ, Chr(34)) ;"
Assert(A_SQ, "'")
Assert(A_CR, "`r")
Assert(A_CRLF, "`r`n")
Assert(A_LF, "`n")

vOutput := ""
for _, vValue in StrSplit("Space,Tab,Comma,DQ,SQ,CR,CRLF,LF", A_Comma)
	vOutput .= "A_" vValue " (length " StrLen(A_%vValue%) ") |" A_%vValue% "|" A_CRLF
MsgBox(vOutput)

MsgBox("done")
return

;==================================================

;simplified version of function:
MsgBox(Text:="Press OK to continue.")
{
	MsgBox, % Text
}

;==================================================

Assert(vValue1, vValue2)
{
	;Clipboard := vValue1
	;return

	if (vValue1 != vValue2)
		throw Error("Assert mismatch.`r`n" "Return value: " vValue1 "`r`n" "Expected value: " vValue2, -1)
}

;==================================================

Error(Message, Params*) ;Message, What, Extra
{
	local What
	if (Params.Length() > 2)
		throw Exception("Too many parameters passed to function.", -1)
	if !Params.HasKey(1)
		Params[1] := 0
	What := Params[1]
	if What is integer
		Params[1]--
	return Exception(Message, Params*)
}

;==================================================

@ghost
Copy link

ghost commented Aug 17, 2022

If I were you I'd slam all those things into a separate ahk file, place it in the global Lib folder and #include it only where and when necessary. Did that with variables required for AHK_L <=> AHK Basic compatibility and it works just fine.

@jeeswg
Copy link
Contributor Author

jeeswg commented Aug 17, 2022

@Drugwash2:
By that logic, if I want to use scripts by Alice/Bob/Carol/Drugwash, I also need to use their respective 'A_' variable functions. What if those functions clash, using the same names, or work differently.

The same thing applies when you want to share a quick bit of code to a forum ...
Do I edit the code to use Chr(34), instead of an additional function, for the user's convenience, resulting in 2 forks of my function to maintain, or do I copy and paste an additional function just to produce the quote, that may interfere with the global namespace of variable/function names.

In general, it simplifies things to use as few dependencies as possible.
E.g. using Chr(34) is preferable to including an auxiliary function.
But always using the minimum number of dependencies can have drawbacks like using obscure/slow/verbose functionality where BIFs aren't available, or recreating the same nested/auxiliary function repeatedly.
The middle way: every so often, it helps to make certain things built-in.
Btw in my main function libs: vDQ := Chr(34) appears 57 times, Chr(34) appears 395 times.
I could finally streamline all that. Remove the former, replace the latter.
Anyhow, I'm not saying that I'm always right, but I do always carefully consider everything, for the benefit of the entire community.
See also: [v1/v2] Additional special character built-in variables - AutoHotkey Community.

@ghost
Copy link

ghost commented Aug 17, 2022

Something else to consider:

  • unnecessarily increasing the size of the AHK executables/binaries, especially where compression is not feasible (i.e. in Linux+Wine)
  • littering this repository followers' mailboxes with notifications of pull requests that (almost?) never pass
  • diverting people's attention from more important things

For what it's worth I personally never felt the need to replace a comma with a seven-letter placeholder, nor the other suggested BIVs. It's all about coding style, and it would be interesting to find out how many AHK coders would really really need all those BIVs. By the number of comments in the thread you linked to it doesn't look like there would be many.

But maybe I'm wrong. Or maybe not. After all it's just a personal opinion.

@jeeswg
Copy link
Contributor Author

jeeswg commented Aug 17, 2022

@Drugwash2:
Good points.
'I do always carefully consider everything'.
I have been as successful as other PR submitters, and in PRs that didn't pass, often the code still made it to AHK v1/v2 in other commits.
Some of the 'less interesting' PRs, are to save Lexikos time (one hopes), to let him focus on things that interest him more.
There have been other threads re. built-in character constants, in the past, e.g. several mention 'A_CRLF'.

@jeeswg
Copy link
Contributor Author

jeeswg commented Sep 10, 2022

I've observed the comments here re. single/double quotes:
[v1/v2] Additional special character built-in variables - AutoHotkey Community

Single quotes

a literal single quote is not problematic:

Single quotes are just as problematic as double quotes, they just never needed escaping in AHK v1, because you couldn't define strings with single quotes.
And both of these can be hard to read in various fonts: "'" and '`'' versus A_SQ.

"'" (AHK v1/v2)
'`'' (AHK v2)

What users are asking for

In the comments, people want:

  • short variable names
  • single and double quote variables
  • readable/meaningful variable names

Quote/Quot/Q and Apos/QQ v. DQ and SQ

If CR and LF weren't common, people would be suggesting A_CarriageReturn or A_Return or A_Linefeed. It's unsurprising that people think they want A_Quote, because it's readable. But it only takes a day or week to get used to CR / LF, likewise, it only takes a day or week to get used to SQ / DQ, which, all things considered are the most sensible choice (I've come across), when short length is a priority.

There is a precedent for SQ and DQ:
Syntax - IBM Documentation
Computing Fundamentals and Programming in C - Nasib Singh Gill - Google Books
(Just try searching: "SQ" "DQ" "single quote" "double quote" or "SQ" "DQ" "single quotation" "double quotation".)

I considered various short variable names, but felt A_SQ and A_DQ gave the best overall pairing. And were the only good choice I saw.

Anyone suggesting A_Quote, really ought to suggest a variable name for single quotes.
But A_Quote is way too long, think about long strings and command-line strings, often containing 2, 4, or more, double quotes.
A_DQ is easier to type than A_Quote: all the letters are on the left of the keyboard, and you hold shift for every character.
A_Quote is more awkward to type, A_DQ is more satisfying to type.

The words 'single'/'double' and 'quote'/'quotation' appear in that order in the AHK documentation already, and commonly appear in that order in Unicode character names:
E.g. 'Single-quote marks (') and double-quote marks (")'.
E.g. 'LEFT SINGLE QUOTATION MARK', 'RIGHT SINGLE QUOTATION MARK'.

Other points

Formatted strings. I'd welcome something like one or both of these, but still feel A_SQ and A_DQ are very worthwhile:
F"abc ${var} def"
D"abc %var% def"

A_Comma. An example where it adds 'at a glance' clarity:

	vText := StrReplace(vText, A_DQ "," A_DQ, ",")
	vText := StrReplace(vText, A_DQ A_Comma A_DQ, A_Comma)

@Lexikos
Copy link
Collaborator

Lexikos commented Nov 23, 2022

An example where it adds 'at a glance' clarity:

I find it clearer and more elegant to use single quoted strings, with syntax highlighting. Escaped double quotes aren't much worse with proper highlighting.

@Lexikos Lexikos closed this Nov 23, 2022
@jeeswg
Copy link
Contributor Author

jeeswg commented Nov 24, 2022

I particularly wanted A_DQ (and A_SQ). The other variables would depend on the wishes/demands of others.
It's one of the PRs that would make a big difference to me on a daily basis.
With A_DQ, I could avoid spending even a second thinking about Run(Chr(34) path Chr(34) " " Chr(34) arg Chr(34)) or dq := Chr(34) etc.

Single Quote Avoidance

I avoid using single quotes to define strings.
I prefer to keep all string definitions consistent, e.g. for simplicity's sake, and searching, and parsing, and thus use double quotes.
(Also, I copy/paste between multiple languages, and many languages don't use single quotes to define strings, e.g. C++ and AHK v1.)

(Also, a personal preference, I find single quotes for string definitions, a bit silly-looking.)
(I'd prefer that no-one writing AHK code would use single quotes to define strings.)

The one place where single quotes could be used, that I'd approve of, is code in a string, for an Eval function (e.g. JavaScript), or to create a temporary AutoHotkey script (via FileAppend).
I.e. single quotes used within double quotes, or vice versa.

Using A_SQ and A_DQ can facilitate writing such Eval code. E.g.:

msg := "abc'def`"ghi" ;AHK v1: msg := "abc'def""ghi"
msg := "abc" A_SQ "def" A_DQ "ghi"
;since all literal single/double quotes have been removed, we can now safely replace " with ':
msg := 'abc' A_SQ 'def' A_DQ 'ghi'
;we can now store the code in a string:
code .= "`r`n" "msg := 'abc' A_SQ 'def' A_DQ 'ghi'"

Backtick Avoidance

If not using single quotes, that only leaves: dq := "`"".
I'm not a fan of how that looks.

(I sometimes store lists of characters as strings, and select the string to count the characters.)
(This fails when backticks are used, hence I use variables instead for such characters.)

(Also, it's not great if copying/pasting between multiple languages.)
(Few (no?) other languages use backticks to escape double quotes.)
(Although I think using backticks, not backslashes, for everyday use, is a great idea, particularly when defining paths, or using RegEx. Because you avoid having to double up literal backslashes.)

Syntax Highlighting Dependence Avoidance

Again, personal preference, I prefer not to depend on syntax highlighting.
I find it marginally useful to grey out comments, and confirm types are written correctly in C++ code. E.g. in Notepad2/Visual Studio.
A lot of places have incorrect/no syntax highlighting e.g. html codeboxes on various websites, including GitHub.
And syntax highlighting can be distracting when parsers incorrectly colour things.
(And different parsers use different colours, reducing its usefulness/effectiveness/convenience. Some online, which you can't modify.)

(People often overcomplicate their code structures and coding setup.)
(Writing code without syntax highlighting nudges/pushes you to write better/simpler/clearer code.)

Libraries and Two-way Compatibility

I'm working on a massive library, to share, that is intended to be AHK v1/v2 two-way compatible.
(And I'll be sharing my AHK v2 backport library, and AHK string/date/maths/sort/object etc functions for JavaScript library, in Nov/Dec 2022.)
A_DQ, a VarRef(var) 'function' (equivalent to &var), and perhaps one or two other (very minor) features, would simplify that enormously.
Neither of these work in AHK v1:

dq := '"'
dq := "`""

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants