Repository: kivy/kivy

Issue:
input_filter : negative numbers
The input_filter: float / int  property does not allow negative numbers. 
## <bountysource-plugin>

Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/17915572-input_filter-negative-numbers?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F42681&utm_medium=issues&utm_source=github).
</bountysource-plugin>



Discussion:
regular-expression for negative and non-negative numbers:     ^[-0-9][0-9]+

Is there a way to invert this expression?

I'm sorry but I can't find a simple way to have integer positive and negative, how is it working now? (I'm using the daily-repository of kivy on linux). Might be the wrong place but I didn't find any clear explanation in the commits

Negative integers do not work currently. https://github.com/kivy/kivy/pull/3745 should fix it.

Thank you for your answer. Is it possible to know when this change is going to be merged ? Roughly ? 

@Paradoxeuh, there is no eta, testing the pr and giving feedback helps speeding up the merge.

I want to finally add this but I don't to remove the ability to just have positive numbers. So I think we need options like `int_pos`, `int`, `float`, and `float_pos`. However, this breaks previous behavior for e.g. `int` not allowing negatives. Also, positive ints do not include zero. So I'm not sure what the best options are.

Resolving patch:
diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py
--- a/kivy/uix/textinput.py
+++ b/kivy/uix/textinput.py
@@ -680,39 +680,32 @@ def insert_text(self, substring, from_undo=False):
         if self.replace_crlf:
             substring = substring.replace(u'\r\n', u'\n')
 
-        mode = self.input_filter
-        if mode is not None:
-            chr = type(substring)
-            if chr is bytes:
-                int_pat = self._insert_int_patb
-            else:
-                int_pat = self._insert_int_patu
-
-            if mode == 'int':
-                substring = re.sub(int_pat, chr(''), substring)
-            elif mode == 'float':
-                if '.' in self.text:
-                    substring = re.sub(int_pat, chr(''), substring)
-                else:
-                    substring = '.'.join([re.sub(int_pat, chr(''), k) for k
-                                          in substring.split(chr('.'), 1)])
-            else:
-                substring = mode(substring, from_undo)
-            if not substring:
-                return
-
         self._hide_handles(EventLoop.window)
 
         if not from_undo and self.multiline and self.auto_indent \
                 and substring == u'\n':
             substring = self._auto_indent(substring)
 
+        mode = self.input_filter
+        if mode not in (None, 'int', 'float'):
+            substring = mode(substring, from_undo)
+            if not substring:
+                return
+
         cc, cr = self.cursor
         sci = self.cursor_index
         ci = sci()
         text = self._lines[cr]
         len_str = len(substring)
         new_text = text[:cc] + substring + text[cc:]
+        if mode is not None:
+            if mode == 'int':
+                if not re.match(self._insert_int_pat, new_text):
+                    return
+            elif mode == 'float':
+                if not re.match(self._insert_float_pat, new_text):
+                    return
+
         self._set_line_text(cr, new_text)
 
         wrap = (self._get_text_width(
@@ -2477,8 +2470,8 @@ def _refresh_hint_text(self):
     _lines = ListProperty([])
     _hint_text_lines = ListProperty([])
     _editable = BooleanProperty(True)
-    _insert_int_patu = re.compile(u'[^0-9]')
-    _insert_int_patb = re.compile(b'[^0-9]')
+    _insert_int_pat = re.compile(u'^-?[0-9]*$')
+    _insert_float_pat = re.compile(u'^-?[0-9]*\\.?[0-9]*$')
 
     readonly = BooleanProperty(False)
     '''If True, the user will not be able to change the content of a textinput.


Test patch: