ID:727857
 
Keywords: text
Resolved
The copytext(), findtext(), and findtextEx() procs now accept negative values for indexes. 0 still means the end of the string, but -1 is the last character, -2 is next-to-last, and so on. For example, copytext(msg,-4) is equivalent to copytext(msg,length(msg)-3). In addition, these procs are less prone to crash with "out of bounds" errors if given bad input. copytext(msg,3,2) for instance now returns a blank string instead of crashing. This behavior only affects worlds compiled in the new version.
Applies to:DM Language
Status: Resolved (495)

This issue has been resolved.
Currently, if you use a negative value in functions such as:
findtext(Haystack,Needle,Start=1,End=0)
findtextEx(Haystack,Needle,Start=1,End=0)
copytext(T,Start=1,End=0)

you will get a runtime error about index out of bounds or something. However, wouldn't it make sense that if the value '0' is the position of the last character of any string...that a value such as -1, could be the position right before the last character?

It'd save a lot of effort in parsing things, I think, instead of having to length() things to get the position of where something ends, especially if you know you only need the last x amt of characters from the string.

var/x = "dantom is cool"
copytext(x,-4,0) //ALOT simpler than
copytext(x,length("dantom is")+2,0)
copytext(x,length(x)-3,0)
Most languages I've used support this feature. I've used it a lot in those languages. I think it would be very useful.
Super Saiyan X wrote:
copytext("dantom is cool",-4,0) //ALOT simpler than
copytext("dantom is cool",length("dantom is")+1,0)

Simpler because you aren't really doing the same thing?
var/someText="dantom isn't cool"
copytext(someText,-4,0)
copytext(someText,length(someText)-4,0)
It is technically the same thing. I'm just checking the length of whatever I know I needed to cut...but yeah. Same concept. Whatevs.
I like this idea, but I feel I should point out your workaround examples are incorrect. Because BYOND uses 1-based offsets for strings, 0 is equivalent to length(x)+1, so -4 would be length(x)-3.
I feel like this could be easily worked around with a user-written proc but would definitely be useful if it was native.
disregarding my failed workarounds...any ideas on where this can go on THE LIST? It seems like a really simple change.
I'm not sure if it'd be better to support negative indexes or just have separate procs that work from the right side of the string. For example, copytextend("something", 5) would return the last 5 characters of the string. findtext would be different - instead of starting at an index (specified relative to the end of the string) and moving to the right it'd just start at the end and move to the left (which is probably more useful), findtextend(filepath, "\\") would find the index of the last \ in a path so you can isolate the file name.
In response to Forum_account
They have functions like that built into the C++ standard, so I don't see why BYOND can't have it. (Given that BYOND is programmed in C++.)
This feature is redundant and adds a befuddling variety to conventions. It can easily be implemented by user created procedures or even the preprocessor; hence there is no need to implement it.

proc/copytextNeg(string, start, end) return copytext(string, length(string) - start, end)

Is ALOT simpler than implementing it into DM.
The entire point of my suggestion would be that it WOULDN'T need a new procedure. You wouldn't need to use length and whatnot. It'd be all handled internally, as Forum_account stated, reading from right to left. While I disagree with the need to create another procedure, there is definitely a way to detect negative values in arguments, and force it to read right to left.
I'm pretty up for this being added; I actually found myself trying to do it recently because other languages support it and I'm naturalized to being able to go 'Get me the last two characters.'

I don't feel it's particularly 'befuddling' to have this functionality. It's befuddling to have to do a sort of awkward workaround where you grab the length() first.
The whole point of my posting was to point out that said feature obfuscates conventionality, and that if you want to go about such then you should consider a workaround. The preprocessor technically doesn't create a new procedure- so I guess that can be something you could look into.

Why have said feature if you can easily live without it or go about aforementioned workaround? It doesn't make much sense for BYOND Dev's to invest their time on this.
Why do we make any feature requests, or bug reports, or anything if we can easily live without it or workaround them in most cases? Simply because it's better to have an intuitive feature being native without having to use workarounds.
In response to Super Saiyan X
Super Saiyan X wrote:
Why do we make any feature requests, or bug reports, or anything if we can easily live without it or workaround them in most cases? Simply because it's better to have an intuitive feature being native without having to use workarounds.

Not really; doesn't influence performance as much as something like pixel movement did. We have feature requests to add something new to BYOND, not alternatives to something already possible through workarounds.
I don't think this is complex at all to integrate into DM, and is worth adding; I've just been focused on other issues and haven't gotten to this yet.
Lummox JR resolved issue with message:
The copytext(), findtext(), and findtextEx() procs now accept negative values for indexes. 0 still means the end of the string, but -1 is the last character, -2 is next-to-last, and so on. For example, copytext(msg,-4) is equivalent to copytext(msg,length(msg)-3). In addition, these procs are less prone to crash with "out of bounds" errors if given bad input. copytext(msg,3,2) for instance now returns a blank string instead of crashing. This behavior only affects worlds compiled in the new version.
Awesome request.
What happens when you have both the start and end as negative numbers? Such as: copytext("Text text",-4,-3)

EDIT: I tested it out, and the end character needs to be a less absolute than the starting position if in negative. So copytext("Text text",-4,-3) is the 6th position "t", whereas copytext("Text text",-3,-4) returns either "" or null. copytext("Text text",-4,-2) ends up as 6th-7th characters "te".