How to make sure a string of pure whitespace is invalid with a succinct code in Swift - ios

I am making a section with TextFields and Button("Continue") and then use .disable(isValidAddress) modifier to a whole section to disable the button. The code works well, but I am seeking any solution to make it more succinct with no need to write .hasPrefix() or .hasSuffix() to all parameters one by one.
var isValidAddress: Bool {
if name.hasPrefix(" ") || street.hasPrefix(" ") || city.hasPrefix(" ") || country.hasPrefix(" ") {
return false
} else if name.hasSuffix(" ") || street.hasSuffix(" ") || city.hasSuffix(" ") || country.hasSuffix(" ") {
return false
}
return true
}

var isValidAddress: Bool {
[street, name, city, etc..].reduce(true, { result, text in
if text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
return false
} else {
return result
}
})
}

You can add them to an array and trim white space and check if empty in a loop
func isValidAddress() -> Bool {
for field in [name, street, city, country] {
if field.trimmingCharacters(in: .whitespaces).isEmpty { return false }
}
return true
}
I used a function here but a computed property works just as well.

If you don't mind moving some complexity into extensions, you can tidy up the call site. This makes it more readable, and less error prone - you can easily add in another field without mistakes for example.
extension String {
func hasPrefixOrSuffix(_ s: String) -> Bool {
hasPrefix(s) || hasSuffix(s)
}
var noSpacesAtEnds: Bool {
!hasPrefixOrSuffix(" ")
}
}
let isValid = [name, street, city, country]
.allSatisfy(\.noSpacesAtEnds)
If you do mean none of them are "all whitespace strings" then:
extension String {
var isNotAllWhitespace: Bool {
!trimmingCharacters(in: .whitespaces).isEmpty
}
}
let isValid = [name, street, city, country]
.allSatisfy(\.isNotAllWhitespace)
One benefit of having named functions for these things is you can test the pieces, so you can write a test to ensure that isNotAllWhitespace works the way you expect. You couldn't if the logic like name.hasPrefix(" ") || street.hasPrefix(" ") is mixed in with your isValidAddress function.

Related

How to properly set DataStore for storing boolean value

I want to set a simple switch that'll save a boolean value and if then block in my function.
Currently I have this in my DataStore:
companion object {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore("userToken")
private val AutoRestartSystemUI = booleanPreferencesKey("AutoRestartSystemUIValue")
}
var getAutoRestartSystemUIValue: Flow<Boolean> = context.dataStore.data.map { preferences ->
(preferences[AutoRestartSystemUI] ?: "") as Boolean
}
suspend fun setAutoRestartSystemUI(value: Boolean) {
context.dataStore.edit { preferences ->
preferences[AutoRestartSystemUI] = value
}
}
}
and
Button(onClick = {
// if [pro.themed.manager.UserStore(context).getAutoRestartSystemUIValue = true] ()
CoroutineScope(Dispatchers.IO).launch {
UserStore(context).setAutoRestartSystemUI(false)
}
}) {
Text(text = UserStore(context).getAutoRestartSystemUIValue.collectAsState(
initial = ""
).toString())
}
in my activity. I have generally no idea of what I should do next and for some weird reason instead of showing value in a text (temp solution for testing) i have
How do i simplify datastore? How do I properly implement switch that'll make it = !it? How to set default value?

Jetpack Compose - How to manipulate the paste behaviour in a TextField

I want to be able to manipulate the paste behaviour of an TextField, something along the lines of -
override fun onPaste(pastedText: String){
}
Like how an EditText has
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
switch (item.getItemId()) {
case R.id.paste:
break;
}
return true;
}
I thought of a workaround. When the paste happens, your value usually typically changes by more than 1 symbol, so maybe something like this will work. I know it is hacky, and I would rather write this as a comment, but comment limits will not let me describe it completely.
TextField(
value = textValue,
onValueChange = { newValue ->
textValue = if (newValue.text.length > 1) {
doSomething()
newValue
} else {
newValue
}
}
)
UPD:
Oh I forgot that you can set up a modifier!
TextField(
value = textValue,
onValueChange = {...},
modifier = Modifier
.onKeyEvent { event: KeyEvent ->
if (
event.type == KeyEventType.KeyDown
&& event.key == Key.Paste
) {
// DO SOMETHING
return#onKeyEvent true
}
false
}
)

Match and extract special word in Dart

I tried to manipulate a text to match and extract special or some words in Dart. For example:
I want to check matching of words ends with a given word
String oldText = "website or show me to";
String newText = "show me to tell";
if (oldText.trim().endsWith(newText.trim())) {
final extractText = oldText.trim().substring(newText.length);
print(extractText);
} else {
print("Not matched");
}
I want to extract only word - "tell" so how can I do it? Need to use Regular expression?
Take a look here. I've implemented a regex which will check that tell is followed by end of line $. The regex is probably easier than any other method you might try, plus it's easy to change if conditions change.
void main() {
String oldText = "website or show me to";
String newText = "show me to tell";
RegExp parser = RegExp(r"tell$");
if (parser.hasMatch(oldText)) {
print(parser.stringMatch(oldText).toString());
} else {
print("Not matched");
}
if (parser.hasMatch(newText)) {
print(parser.stringMatch(newText).toString());
} else {
print("Not matched");
}
}
And here is an example where I have removed the check to a function and also set it up so that you can dynamically generate the regex:
void main() {
String oldText = "website or show me to";
String newText = "show me to tell";
String test = "tell";
RegExp parser = RegExp(test+r"$");
print(checkMatch(oldText, parser));
print(checkMatch(newText, parser));
}
checkMatch(text, parser) {
if (parser.hasMatch(text)) {
return(parser.stringMatch(text).toString());
} else {
return("Not matched");
}
}

xtext Format comment with AbstractFormatter2,

I am using AbstractFormatter2 with xtext 2.9.2
I want to put the comment in a specific column
My syntax looks something like this
terminal SL_COMMENT : '*' !('\n'|'\r')* ('\r'? '\n')?;
So far, I tried to put multiple spaces before my comment, but this doesn't work either
def dispatch void format(Model model, extension IFormattableDocument document) {
SL_COMMENTRule.prepend[space " "]
model.getEnte.format;
model.getMapset.format;
}
can anyone guide my how to format comments in general then how to put them in a specific column
comment formatting is done by commentreplacers
thus something like the following should work
override createCommentReplacer(IComment comment) {
val EObject grammarElement = comment.getGrammarElement();
if (grammarElement instanceof AbstractRule) {
val String ruleName = grammarElement.getName();
if (ruleName.startsWith("SL")) {
if (comment.getLineRegions().get(0).getIndentation().getLength() > 0) {
return new SinglelineDocCommentReplacer(comment, "//") {
override configureWhitespace(WhitespaceReplacer leading, WhitespaceReplacer trailing) {
leading.getFormatting().space = " ";
}
};
} else {
return new SinglelineCodeCommentReplacer(comment, "//") {
override configureWhitespace(WhitespaceReplacer leading, WhitespaceReplacer trailing) {
leading.getFormatting().space = " ";
}
}
}
}
}
super.createCommentReplacer(comment)
}

Criteria building in GORM

if (params.filters) {
def o = JSON.parse(params.filters);
def groupOp = o.groupOp
def fields = o.rules.field
def values = o.rules.data
def op = o.rules.op
println fields
println values
if(groupOp == "AND") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
and{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
and{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
and{ ge(fields[i], valu)}
}
}
}
if(groupOp == "OR") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
println 'eq';
or{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
println 'ne';
or{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
or{ ge(fields[i], valu)}
}
}
}
}
where params.filters is following JSON text.
{
"groupOp":"OR",
"rules":[
{
"field":"foo1",
"op":"le",
"data":"9.5"
},
{
"field":"foo2",
"op":"eq",
"data":"12345-123"
},
{
"field":"foo3",
"op":"cn",
"data":"IDM"
}
]
}
This data is coming from JQuery data grid.
Is there a better way of doing this?
In the code I have just listed only 3 operators, but in real I have 14 operations.
You can use String as Criteria operation, like:
A.withCriteria {
'eq' (id, 1)
}
so you might come to something like
A.withCriteria {
(groupOp) {
for (???) {
(op[i]) (fields[i], parsedVals[i])
}
}
}
Anyway you'll need to sanitize the web-submitted query for only allowed subset of operations. You don't want to receive end execute arbitrary sqlRestriction, right? :D So the code is going to be more complex then this anyway.
Note: wrapping and{} or or {} around single statement has no point, you need to put it around whole block of if-s.
I suggest that you have a look at the source code of the FilterPane plugin. Its service does essentially what you are doing and may give you some ideas for enhancements.

Resources