diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e6acf98a192763563c8ad340db87fd9df7aa31d9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+# GUI для конфигов
+
+## Как запустить?
+
+`pip install dearpygui`
+
+`git clone http://tesla.parallel.ru/kuzmichovamary/gui.git`
+
+`cd gui`
+
+`python run prerun.py` -- один раз (тут собирается `config-parser` ;)
+
+`python run app.py`
+
diff --git a/app.py b/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..604dbaf3c9978f378ef4a38c600b101af582fd55
--- /dev/null
+++ b/app.py
@@ -0,0 +1,212 @@
+import re
+import ctypes
+
+import dearpygui.dearpygui as dpg
+
+from styles import GuiStyle, INDENT, SPACE, FONT_SIZE, ICON_PATH
+from config import load_config, dump_config
+
+ctypes.windll.shcore.SetProcessDpiAwareness(1)
+
+
+class ConfigEditor:
+    def __init__(self):
+        dpg.create_context()
+
+        self.styles = GuiStyle()
+        self.config = dict()
+        self.config_file_path = ""
+
+        self.construct_main_window()
+
+    def delete_config_window_and_clear_aliases(self, file_path):
+        if dpg.does_item_exist(file_path):
+            dpg.delete_item(file_path)
+        if dpg.does_item_exist(f"{file_path}_tab_bar"):
+            dpg.delete_item(f"{file_path}_tab_bar")
+        if dpg.does_item_exist(f"{file_path}_tab"):
+            dpg.delete_item(f"{file_path}_tab")
+
+        if dpg.does_alias_exist(file_path):
+            dpg.remove_alias(file_path)
+        if dpg.does_alias_exist(f"{file_path}_tab_bar"):
+            dpg.remove_alias(f"{file_path}_tab_bar")
+        if dpg.does_alias_exist(f"{file_path}_tab"):
+            dpg.remove_alias(f"{file_path}_tab")
+        for path in self.config:
+            namespaces = path.split('.')
+            for i in range(len(namespaces)):
+                path = self.config_file_path + '.' + '.'.join(namespaces[:i+1])
+                if dpg.does_alias_exist(path):
+                    dpg.remove_alias(path)
+                if dpg.does_alias_exist(f"{path}_tab_bar"):
+                    dpg.remove_alias(f"{path}_tab_bar")
+                if dpg.does_alias_exist(f"{path}_tab"):
+                    dpg.remove_alias(f"{path}_tab")
+                if dpg.does_alias_exist(f"{path}_text"):
+                    dpg.remove_alias(f"{path}_text")
+
+    def update_config(self):
+        for path in self.config:
+            self.config[path].value = dpg.get_value(f"{self.config_file_path}.{path}")
+
+    def manage_file(self, sender, sender_data, user_data):
+        if user_data == "save":
+            if not self.config_file_path:
+                return
+            self.update_config()
+            dump_config(self.config, self.config_file_path)
+            dpg.show_item("file_save_popup")
+            return
+
+        file_path = sender_data['file_path_name']
+
+        if user_data == "open":
+            self.delete_config_window_and_clear_aliases(self.config_file_path)
+            self.config_file_path = file_path
+            self.config = load_config(file_path)
+            self.construct_config_ui()
+        elif user_data == "save_as":
+            if not self.config_file_path:
+                return
+            self.update_config()
+            dump_config(config, file_path)
+            dpg.show_item("file_save_popup")
+
+    def set_file_path(self, sender, sender_data, user_data):
+        file_path = sender_data['file_path_name']
+        dpg.set_value(user_data, file_path)
+
+    def open_file_dialog(self, sender, sender_data, user_data):
+        dpg.show_item("file_dialog")
+        dpg.set_item_user_data("file_dialog", user_data)
+
+    def open_folder_dialog(self, sender, sender_data, user_data):
+        dpg.show_item("folder_dialog")
+        dpg.set_item_user_data("folder_dialog", user_data)
+
+    def construct_config_ui(self):
+        self.delete_config_window_and_clear_aliases(self.config_file_path)
+        if dpg.get_value("use_tabs_ui"):
+            self.construct_config_ui_tabs()
+        else:
+            self.construct_config_ui_collapsing_headers()
+
+    def construct_main_window(self):
+        dpg.bind_font(self.styles.montserrat_font)
+        dpg.bind_theme(self.styles.main_theme)
+
+        with dpg.window(label="config file editor", pos=(10, 10), width=800, height=600, tag="main", menubar=True):
+            with dpg.menu_bar():
+                with dpg.menu(label="file"):
+                    dpg.add_menu_item(label="open", callback=self.open_file_dialog, tag="open_btn", user_data="open")
+                    dpg.add_menu_item(label="save", callback=self.manage_file, tag="save_btn", user_data="save")
+                    dpg.add_menu_item(label="save as", callback=self.open_file_dialog, tag="save_as_btn", user_data="save_as")
+
+                with dpg.menu(label="view"):
+                    dpg.add_menu_item(label="use default theme", check=True, callback=lambda _, v: dpg.bind_theme(None if v else self.styles.main_theme), default_value=False)
+                    dpg.add_menu_item(label="use default font", check=True, callback=lambda _, v: dpg.bind_font(None if v else self.styles.montserrat_font), default_value=False)
+                    dpg.add_menu_item(label="use tabs [all entered data will be lost]", check=True, callback=lambda: self.construct_config_ui(), default_value=False, tag="use_tabs_ui")
+                    dpg.add_menu_item(label="show theme editor", callback=dpg.show_style_editor)
+
+                with dpg.menu(label="settings"):
+                    dpg.add_menu_item(label="auto save [not impl]", check=True, callback=lambda: print("TODO"), default_value=False)
+
+        with dpg.file_dialog(directory_selector=False, show=False, callback=self.manage_file, tag="file_dialog", width=600, height=400):
+            dpg.add_file_extension(".txt", color=(0, 255, 0, 255))
+            dpg.add_file_extension(".*", color=(255, 255, 255, 255))
+
+        with dpg.file_dialog(directory_selector=True, show=False, callback=self.set_file_path, tag="folder_dialog", width=500, height=400):
+            dpg.add_file_extension(".*", color=(255, 255, 255, 255))
+
+        with dpg.window(label="", autosize=True, no_resize=True, modal=True, tag="file_save_popup", show=False, pos=(40, 40)):
+            dpg.add_text("file saved successfully:)")
+
+    def construct_config_ui_collapsing_headers(self):
+        dpg.add_collapsing_header(label=self.config_file_path, parent="main", tag=self.config_file_path, indent=0, default_open=True)
+
+        for full_path in self.config:
+            namespaces = full_path.split('.')
+            parent = self.config_file_path
+            for level in range(len(namespaces) - 1):
+                path = self.config_file_path + '.' + '.'.join(namespaces[:level+1])
+
+                if not dpg.does_item_exist(path):
+                    dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
+
+                parent = path
+
+            self.create_widget(full_path)
+
+    def check_tabview(self, root):
+        for uuid in dpg.get_item_children(root, 1):
+            if dpg.get_item_type(uuid) == "mvAppItemType::mvTabBar":
+                return True, uuid
+        return False, None
+
+    def construct_config_ui_tabs(self):
+        tab_bar_exists, tab_bar_uuid = self.check_tabview("main")
+        if not tab_bar_exists:
+            tab_bar_uuid = dpg.add_tab_bar(parent="main", tag=f"{self.config_file_path}_tab_bar")
+        dpg.add_tab(label=self.config_file_path, parent=tab_bar_uuid, tag=f"{self.config_file_path}_tab")
+        dpg.add_child_window(parent=f"{self.config_file_path}_tab", tag=self.config_file_path, border=True, autosize_y=True, autosize_x=True)
+
+        for full_path in self.config:
+            namespaces = full_path.split('.')
+            parent = self.config_file_path
+            for level in range(len(namespaces) - 1):
+                path = self.config_file_path + '.' + '.'.join(namespaces[:level+1])
+
+                tab_bar_exists, tab_bar_uuid = self.check_tabview(parent)
+
+                if not tab_bar_exists:
+                    tab_bar_uuid = dpg.add_tab_bar(parent=parent, tag=f"{path}_tab_bar")
+                    dpg.set_item_height(parent, dpg.get_item_height(parent) + 4 * SPACE + FONT_SIZE)
+
+                if not dpg.does_item_exist(path):
+                    dpg.add_tab(label=namespaces[level], parent=tab_bar_uuid, tag=f"{path}_tab")
+                    dpg.add_child_window(parent=f"{path}_tab", tag=path, border=True, autosize_y=False, autosize_x=True, height=2 * SPACE)
+
+                parent = path
+
+            self.create_widget(full_path)
+
+    def create_widget(self, full_path):
+        tag = self.config_file_path + '.' + full_path
+        parent =  '.'.join([self.config_file_path] + full_path.split('.')[:-1])
+
+        if dpg.get_value("use_tabs_ui") and parent != self.config_file_path:
+            dpg.set_item_height(parent, dpg.get_item_height(parent) + 2 * SPACE + FONT_SIZE + SPACE)
+
+        value = self.config[full_path].value
+        value_type = self.config[full_path].value_type
+        key = self.config[full_path].key
+        comment = self.config[full_path].comment
+
+        with dpg.group(horizontal=True, parent=parent, indent=INDENT):
+            dpg.add_text(key, tag=f"{tag}_text")
+            if value_type == 'BOOLEAN':
+                dpg.add_checkbox(default_value=value, tag=tag)
+            elif value_type == 'DOUBLE':
+                dpg.add_input_double(default_value=value, tag=tag, format="%.10f")
+            elif value_type == 'INT':
+                dpg.add_input_int(default_value=value, tag=tag)
+            elif "dir" in key.lower():
+                dpg.add_input_text(default_value=value, tag=tag)
+                dpg.add_button(label="...", callback=self.open_folder_dialog, user_data=tag)
+            else:
+                dpg.add_input_text(default_value=value, tag=tag)
+            if comment:
+                dpg.add_text(comment, parent=dpg.add_tooltip(parent=f"{tag}_text"))
+
+    def run(self):
+        dpg.create_viewport(title='config file editor', width=800, height=600, small_icon=ICON_PATH)
+        dpg.setup_dearpygui()
+        dpg.show_viewport()
+        dpg.set_primary_window("main", True)
+        dpg.start_dearpygui()
+        dpg.destroy_context()
+
+if __name__ == "__main__":
+    app = ConfigEditor()
+    app.run()
diff --git a/config-parser/cfg-var.o b/config-parser/cfg-var.o
deleted file mode 100644
index 20eaa8dd91d4f24f5c227ebb0ca3bcefe6afe9e6..0000000000000000000000000000000000000000
Binary files a/config-parser/cfg-var.o and /dev/null differ
diff --git a/config-parser/config-parser.o b/config-parser/config-parser.o
deleted file mode 100644
index eb2c5d6b0a801b85f6ce64cf6cd0d996adb3bfa9..0000000000000000000000000000000000000000
Binary files a/config-parser/config-parser.o and /dev/null differ
diff --git a/config-parser/mem-stx.o b/config-parser/mem-stx.o
deleted file mode 100644
index 55c9bcc9447178b8fc5a061ebb5c477a27115342..0000000000000000000000000000000000000000
Binary files a/config-parser/mem-stx.o and /dev/null differ
diff --git a/config-parser/parser-cli b/config-parser/parser-cli
deleted file mode 100644
index 38c03d5d9b3c9e7f11d7a2d5bd1334c9736bfc55..0000000000000000000000000000000000000000
Binary files a/config-parser/parser-cli and /dev/null differ
diff --git a/config-parser/parser-cli.cpp b/config-parser/parser-cli.cpp
index 0b0044e4d7f5d4641c6a26942ef8dd1f236a0303..c732307f443308688b211b5a6a0bedbdec800115 100644
--- a/config-parser/parser-cli.cpp
+++ b/config-parser/parser-cli.cpp
@@ -3,11 +3,11 @@
 #include "config-parser.h"
 
 void print_usage(const char* prog_name) {
-    std::cout << "Usage: " << prog_name << " <filename> <variable_name>" << std::endl;
+    std::cout << "usage: " << prog_name << " <filename>\n";
 }
 
 int main(int argc, char* argv[]) {
-    if (argc < 2) {
+    if (argc != 2) {
         print_usage(argv[0]);
         return 1;
     }
@@ -16,54 +16,12 @@ int main(int argc, char* argv[]) {
         const char* filename = argv[1];
         nse::ConfigParser parser;
         if (!parser.run(filename)) {
-            std::cerr << "failed to parse the configuration file: " << filename << std::endl;
+            std::cerr << "failed to parse the configuration file: " << filename << "\n";
             return 1;
         }
         parser.print();
         return 0;
     }
 
-    const char* filename = argv[1];
-    const char* varname = argv[2];
-
-    nse::ConfigParser parser;
-
-    if (!parser.run(filename)) {
-        std::cerr << "failed to parse the configuration file: " << filename << std::endl;
-        return 1;
-    }
-
-    if (!parser.is_varname(varname)) {
-        std::cerr << "variable " << varname << " not found in the configuration file." << std::endl;
-        return 1;
-    }
-
-    parser.print();
-
-    nse::cfgVariable variable = parser.get_variable(varname);
-
-    variable.print();
-
-    // int int_val;
-    // float float_val;
-    // double double_val;
-    // std::string string_val;
-    // bool bool_val;
-
-    // if (parser.get_value(varname, &int_val)) {
-    //     std::cout << "Value: " << int_val << std::endl;
-    // } else if (parser.get_value(varname, &float_val)) {
-    //     std::cout << "Value: " << float_val << std::endl;
-    // } else if (parser.get_value(varname, &double_val)) {
-    //     std::cout << "Value: " << double_val << std::endl;
-    // } else if (parser.get_value(varname, string_val)) {
-    //     std::cout << "Value: " << string_val << std::endl;
-    // } else if (parser.get_value(varname, &bool_val)) {
-    //     std::cout << "Value: " << (bool_val ? "true" : "false") << std::endl;
-    // } else {
-    //     std::cerr << "Failed to get the value for variable " << varname << "." << std::endl;
-    //     return 1;
-    // }
-
     return 0;
 }
diff --git a/config-parser/parser-cli.exe b/config-parser/parser-cli.exe
deleted file mode 100644
index 55c8e34fa0a08e91616caab205c747882ed83a71..0000000000000000000000000000000000000000
Binary files a/config-parser/parser-cli.exe and /dev/null differ
diff --git a/config-parser/parser-cli.o b/config-parser/parser-cli.o
deleted file mode 100644
index 631a48ca271ca50a2d8e025204928afa2f6a9722..0000000000000000000000000000000000000000
Binary files a/config-parser/parser-cli.o and /dev/null differ
diff --git a/config-parser/str-com.o b/config-parser/str-com.o
deleted file mode 100644
index 8c2c3763be9e28d7bbfb6851e5e90bc9dddaad2f..0000000000000000000000000000000000000000
Binary files a/config-parser/str-com.o and /dev/null differ
diff --git a/config.py b/config.py
new file mode 100644
index 0000000000000000000000000000000000000000..e910835ea7f135174d59c63c0da322e71e29ca86
--- /dev/null
+++ b/config.py
@@ -0,0 +1,238 @@
+import re
+import subprocess
+import os
+from enum import Enum
+
+
+class CfgVar:
+    def __init__(self, key, value=None, value_type='STRING', comment=""):
+        self.key = key
+        self.value = value
+        self.value_type = value_type
+        self.comment = comment
+
+    def __repr__(self):
+        return f"CfgVar(key={self.key}, value={self.value}, comment={self.comment})"
+
+
+TokenType = Enum('TokenType', ['BRACE_OPEN', 'BRACE_CLOSE', 'VARIABLE', 'NAMESPACE'])
+
+
+class Token:
+    def __init__(self, type):
+        self.type = type
+
+    def __repr__(self):
+        return str(self.type)
+
+
+class Variable(Token):
+    def __init__(self, name, comment=""):
+        super().__init__(TokenType.VARIABLE)
+        self.name = name
+        self.comment = comment
+
+    def __repr__(self):
+        return f"VAR {self.name} [{self.comment}]"
+
+
+class Namespace(Token):
+    def __init__(self, name):
+        super().__init__(TokenType.NAMESPACE)
+        self.name = name
+
+    def __repr__(self):
+        return f"NAMESPACE {self.name}"
+
+
+def tokenize(file_path):
+    text = ""
+    if os.path.exists(file_path):
+        text = open(file_path, "r", encoding="utf-8").read()
+
+    tokens = []
+    it = text.__iter__()
+
+    try:
+        char = it.__next__()
+        while True:
+            if char == "{":
+                tokens.append(Token(TokenType.BRACE_OPEN))
+                char = it.__next__()
+            elif char == "}":
+                tokens.append(Token(TokenType.BRACE_CLOSE))
+                char = it.__next__()
+            elif char.isalpha():
+                name = char
+
+                char = it.__next__()
+                while char.isalnum() or char == "_" or char == ".":
+                    name += char 
+                    char = it.__next__()
+
+                char = it.__next__()
+                while char in (" ", "\t"):
+                    char = it.__next__()
+
+                if char == "=":
+                    tokens.append(Variable(name))
+
+                    char = it.__next__()
+                    while char != ";":
+                        char = it.__next__()
+
+                    char = it.__next__()
+                    while char in (" ", "\t"):
+                        char = it.__next__()
+
+                    if char == "#":
+                        
+                        char = it.__next__()
+
+                        while char in (" ", "\t"):
+                            char = it.__next__()
+
+                        comment = ""
+
+                        while char != "\n":
+                            comment += char
+                            char = it.__next__()
+
+                        if tokens[-1].type == TokenType.VARIABLE:
+                            tokens[-1].comment = comment    
+
+                        char = it.__next__()
+                else:
+                    tokens.append(Namespace(name))
+            elif char == "#":
+                while char != "\n":
+                    char = it.__next__()
+                char = it.__next__()
+            else:
+                char = it.__next__()
+    except StopIteration as e:
+        return tokens
+
+
+def parse(file_path):
+    stack = []
+
+    data = dict()
+
+    tokens = tokenize(file_path)
+    it = tokens.__iter__()
+
+    try:
+        while True:
+            token = it.__next__()
+            if token.type == TokenType.NAMESPACE:
+                stack.append(token.name)
+
+            if token.type == TokenType.BRACE_CLOSE:
+                stack.pop()
+
+            if token.type == TokenType.VARIABLE:
+                if stack:
+                    path = '.'.join(stack) + f'.{token.name}'
+                else:
+                    path = token.name
+                data[path] = CfgVar(token.name, comment=token.comment)
+    except StopIteration as e:
+        return data
+
+
+def load_config(file_path):
+    config = parse(file_path)
+
+    output = subprocess.run(["config-parser/parser-cli", file_path], capture_output=True, text=True)
+
+    for line in output.stdout.split("\n"):
+        match = re.match(r" > (\w+) '(.*)' = *(.*)", line)
+        if match:
+            value_type, path, value = match.groups()
+            config[path].value = get_value_from_str(value, value_type)
+            config[path].value_type = value_type
+
+    return config
+
+def construct_nested_dict(config):
+    config_nested = dict()
+    for path in config:
+        nss = path.split(".")
+
+        cur_ns = config_nested
+
+        for ns in nss[:-1]:
+            if ns not in cur_ns:
+                cur_ns[ns] = {}
+
+            cur_ns = cur_ns[ns]
+
+        cur_ns[nss[-1]] = config[path]
+    return config_nested
+
+def get_str_from_value(value, value_type):
+    if not value:
+        if value_type == 'STRING':
+            return '""'
+        elif value_type == 'INT':
+            return '0'
+        elif value_type == 'DOUBLE':
+            return '0.0'
+        elif value_type == 'BOOLEAN':
+            return 'false'
+    else:
+        if value_type == 'STRING':
+            return f'"{value}"'
+        elif value_type == 'BOOLEAN':
+            return str(value).lower()
+        elif value_type == 'DOUBLE':
+            return "{:.7f}".format(float(value))
+    return str(value)
+
+def get_value_from_str(string, value_type):
+    if not string:
+        if value_type == 'STRING':
+            return ""
+        elif value_type == 'INT':
+            return 0
+        elif value_type == 'DOUBLE':
+            return 0.0
+        elif value_type == 'BOOLEAN':
+            return False
+    else:
+        if value_type == 'STRING':
+            return string
+        elif value_type == 'BOOLEAN':
+            return string == 'true'
+        elif value_type == 'DOUBLE':
+            return float(string)
+        elif value_type == 'INT':
+            return int(string)
+
+def write_namespace(file, ns, ns_name, indent):
+    file.write("\n")
+    file.write(" " * indent + ns_name + "\n")
+    file.write(" " * indent + "{\n")
+    for key in ns:
+        if isinstance(ns[key], dict):
+            write_namespace(file, ns[key], key, indent + 4)
+        else:
+            file.write(" " * (indent + 4) + f"{key} = {get_str_from_value(ns[key].value, ns[key].value_type)};\n")
+    file.write(" " * indent + "}\n")
+    file.write("\n")
+
+def dump_config(config, file_path):
+    config_nested = construct_nested_dict(config)
+
+    indent = 0
+    with open(file_path, "w", encoding="utf-8") as file:
+        for key in config_nested:
+            if isinstance(config_nested[key], dict):
+                write_namespace(file, config_nested[key], key, indent)
+            else:
+                file.write(f"{key} = {get_str_from_value(config_nested[key].value, config_nested[key].value_type)};\n")
+
+
+if __name__ == '__main__':
+    print(load_config('config.txt'))
\ No newline at end of file
diff --git a/config_manager.py b/config_manager.py
deleted file mode 100644
index 567d99ff25b26cc1ebb34245d87fac4cc7d2c225..0000000000000000000000000000000000000000
--- a/config_manager.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import re
-import subprocess
-
-class ConfigManager:
-    def __init__(self, func):
-        self.file_path = ""
-        self.get_value_func = func
-        self.lines = []
-        self.config_data = {}
-
-    def is_initialized(self):
-        return self.file_path != ""
-
-    def init(self, file_path):
-        self.lines = []
-        self.config_data = {}
-        self.file_path = file_path
-
-        output = subprocess.run(["config-parser/parser-cli", self.file_path], capture_output=True, text=True)
-
-        for line in output.stdout.split("\n"):
-            match = re.match(r" > (\w+) '(.*)' = *(.*)", line)
-            if match:
-                self.lines.append(match.groups())
-
-    def construct_dict(self):
-        if self.config_data:
-            return
-
-        for value_type, path, value in self.lines:
-            nss = path.split(".")
-
-            cur_ns = self.config_data
-
-            for ns in nss[:-1]:
-                if ns not in cur_ns:
-                    cur_ns[ns] = {}
-
-                cur_ns = cur_ns[ns]
-
-            cur_ns[nss[-1]] = (path, value_type)
-
-    def get_value_str(self, path, value_type):
-        value = self.get_value_func(path, value_type)
-        if not value:
-            if value_type == 'STRING':
-                return '""'
-            elif value_type == 'INT':
-                return '0'
-            elif value_type == 'DOUBLE':
-                return '0.0'
-            elif value_type == 'BOOLEAN':
-                return 'false'
-        else:
-            if value_type == 'STRING':
-                return f'"{value}"'
-            elif value_type == 'BOOLEAN':
-                return str(value).lower()
-            elif value_type == 'DOUBLE':
-                return "{:.7f}".format(value)
-        return str(value)
-
-    def write_namespace(self, file, ns, ns_name, indent):
-        file.write("\n")
-        file.write(" " * indent + ns_name + "\n")
-        file.write(" " * indent + "{\n")
-        for key in ns:
-            if isinstance(ns[key], dict):
-                self.write_namespace(file, ns[key], key, indent + 4)
-            else:
-                file.write(" " * (indent + 4) + f"{key} = {self.get_value_str(*ns[key])};\n")
-        file.write(" " * indent + "}\n")
-        file.write("\n")
-
-    def save(self):
-        self.save_as(self.file_path)
-
-    def save_as(self, file_path):
-        self.construct_dict()
-
-        indent = 0
-        with open(file_path, "w", encoding="utf-8") as file:
-            for key in self.config_data:
-                if isinstance(self.config_data[key], dict):
-                    self.write_namespace(file, self.config_data[key], key, indent)
-                else:
-                    file.write(f"{key} = {self.get_value_str(*self.config_data[key])};\n")
-
-# file_path = "config.txt"
-# cfg_manager = ConfigManager(file_path, lambda p, t: t[0])
-# cfg_manager.save_config("config_my.txt")
\ No newline at end of file
diff --git a/dpg_gui_tabs.py b/dpg_gui_tabs.py
deleted file mode 100644
index 8c7712179cf8361802c1f2aab0160d97f3994657..0000000000000000000000000000000000000000
--- a/dpg_gui_tabs.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import dearpygui.dearpygui as dpg
-import re
-import ctypes
-from dpg_gui_styles import GuiStyle, INDENT
-from config_manager import ConfigManager
-
-ctypes.windll.shcore.SetProcessDpiAwareness(1)
-
-class ConfigEditor:
-    def __init__(self):
-        dpg.create_context()
-
-        self.styles = GuiStyle()
-
-        self.cfg_manager = ConfigManager(self.get_value)
-
-        self.construct_main_window()
-
-        dpg.bind_font(self.styles.montserrat_font)
-        dpg.bind_theme(self.styles.main_theme)
-
-        dpg.create_viewport(title='config file editor', width=800, height=600, small_icon='icon.ico')
-        dpg.setup_dearpygui()
-        dpg.show_viewport()
-        dpg.set_primary_window("main", True)
-
-    def manage_file(self, sender, app_data, user_data):
-        file_path = app_data['file_path_name']
-
-        if user_data == "open":
-            if self.cfg_manager.is_initialized():
-                dpg.delete_item(self.cfg_manager.file_path)
-                if dpg.does_alias_exist(self.cfg_manager.file_path):
-                    dpg.remove_alias(self.cfg_manager.file_path)
-                for _, path, _ in self.cfg_manager.lines:
-                    namespaces = path.split('.')
-                    for i in range(len(namespaces)):
-                        path = '.'.join(namespaces[:i+1])
-                        if dpg.does_alias_exist(path):
-                            dpg.remove_alias(path)
-
-            self.cfg_manager.init(file_path)
-            self.construct_config_window()
-        elif user_data == "save_as":
-            self.cfg_manager.save_as(file_path)
-
-    def set_file_path(self, sender, app_data, user_data):
-        file_path = app_data['file_path_name']
-        dpg.set_value(user_data, file_path)
-
-    def get_value(self, path, value_type):
-        return dpg.get_value(path)
-
-    def open_file_dialog(self, sender, app_data, user_data):
-        dpg.show_item("file_dialog")
-        dpg.set_item_user_data("file_dialog", user_data)
-
-    def open_folder_dialog(self, sender, app_data, user_data):
-        dpg.show_item("folder_dialog")
-        dpg.set_item_user_data("folder_dialog", user_data)
-
-    def construct_main_window(self):
-        with dpg.window(label="config file editor", width=800, height=600, tag="main", menubar=True, no_resize=False, no_close=False, no_move=False, no_collapse=False):
-            with dpg.menu_bar():
-                with dpg.menu(label="file"):
-                    dpg.add_menu_item(label="open", callback=self.open_file_dialog, tag="open_btn", user_data="open")
-                    dpg.add_menu_item(label="save", callback=self.cfg_manager.save, tag="save_btn")
-                    dpg.add_menu_item(label="save as", callback=self.open_file_dialog, tag="save_as_btn", user_data="save_as")
-
-                with dpg.menu(label="view"):
-                    dpg.add_menu_item(label="use default theme", check=True, callback=lambda _, v: dpg.bind_theme(None if v else self.styles.main_theme), default_value=False)
-                    dpg.add_menu_item(label="use default font", check=True, callback=lambda _, v: dpg.bind_font(None if v else self.styles.montserrat_font), default_value=False)
-                    dpg.add_menu_item(label="show theme editor", callback=dpg.show_style_editor)
-
-                with dpg.menu(label="settings"):
-                    dpg.add_menu_item(label="auto save [not impl]", check=True, callback=lambda: print("TODO"), default_value=False)
-
-        with dpg.file_dialog(directory_selector=False, show=False, callback=self.manage_file, tag="file_dialog", width=500, height=400):
-            dpg.add_file_extension(".txt", color=(0, 255, 0, 255))
-            dpg.add_file_extension(".*", color=(255, 255, 255, 255))
-
-        with dpg.file_dialog(directory_selector=True, show=False, callback=self.set_file_path, tag="folder_dialog", width=500, height=400):
-            dpg.add_file_extension(".*", color=(255, 255, 255, 255))
-
-    def construct_config_window(self):
-        dpg.add_collapsing_header(label=self.cfg_manager.file_path, parent="main", tag=self.cfg_manager.file_path, indent=0, default_open=True)
-
-        for var_type, full_path, value in self.cfg_manager.lines:
-            namespaces = full_path.split('.')
-            parent = self.cfg_manager.file_path
-            for level in range(len(namespaces) - 1):
-                path = '.'.join(namespaces[:level+1])
-
-                if not dpg.does_item_exist(path):
-                    dpg.add_collapsing_header(label=namespaces[level], parent=parent, tag=path, indent=INDENT)
-
-                parent = path
-
-            self.create_widget('.'.join(namespaces[:-1]), namespaces[-1], value, var_type)
-
-    def create_widget(self, path, key, value, value_type):
-        if path:
-            parent = path
-            tag = f"{path}.{key}"
-        else:
-            parent = self.cfg_manager.file_path
-            tag = key
-
-        with dpg.group(horizontal=True, parent=parent, indent=INDENT):
-            dpg.add_text(key)
-            if value_type == 'BOOLEAN':
-                dpg.add_checkbox(default_value=(value.lower() == "true"), tag=tag)
-            elif value_type == 'DOUBLE':
-                dpg.add_input_double(default_value=float(value), tag=tag, format="%.10f")
-            elif value_type == 'INT':
-                dpg.add_input_int(default_value=int(value), tag=tag)
-            elif "dir" in key.lower():
-                dpg.add_input_text(default_value=value, tag=tag)
-                dpg.add_button(label="...", callback=self.open_folder_dialog, user_data=tag)
-            else:
-                dpg.add_input_text(default_value=value, tag=tag)
-
-    def run(self):
-        dpg.start_dearpygui()
-        dpg.destroy_context()
-
-if __name__ == "__main__":
-    app = ConfigEditor()
-    app.run()
diff --git a/dpygui.py b/dpygui.py
deleted file mode 100644
index d8ea5b36bbfd4313b817b94a78b632a5274b6823..0000000000000000000000000000000000000000
--- a/dpygui.py
+++ /dev/null
@@ -1,100 +0,0 @@
-import dearpygui.dearpygui as dpg
-import dearpygui.demo as demo
-
-dpg.create_context()
-dpg.create_viewport(title='Custom Title', width=600, height=600)
-
-demo.show_demo()
-
-dpg.setup_dearpygui()
-dpg.show_viewport()
-dpg.set_primary_window("__demo_id", True)
-dpg.start_dearpygui()
-dpg.destroy_context()
-
-# List of default style items in Dear PyGui
-style_items = [
-    dpg.mvStyleVar_Alpha,
-	dpg.mvStyleVar_WindowPadding,
-	dpg.mvStyleVar_WindowRounding,
-	dpg.mvStyleVar_WindowBorderSize,
-	dpg.mvStyleVar_WindowMinSize,
-	dpg.mvStyleVar_WindowTitleAlign,
-	dpg.mvStyleVar_ChildRounding,
-	dpg.mvStyleVar_ChildBorderSize,
-	dpg.mvStyleVar_PopupRounding,
-	dpg.mvStyleVar_PopupBorderSize,
-	dpg.mvStyleVar_FramePadding,
-	dpg.mvStyleVar_FrameRounding,
-	dpg.mvStyleVar_FrameBorderSize,
-	dpg.mvStyleVar_ItemSpacing,
-	dpg.mvStyleVar_ItemInnerSpacing,
-	dpg.mvStyleVar_IndentSpacing,
-	dpg.mvStyleVar_CellPadding,
-	dpg.mvStyleVar_ScrollbarSize,
-	dpg.mvStyleVar_ScrollbarRounding,
-	dpg.mvStyleVar_GrabMinSize,
-	dpg.mvStyleVar_GrabRounding,
-	dpg.mvStyleVar_TabRounding,
-	dpg.mvStyleVar_ButtonTextAlign,
-	dpg.mvStyleVar_SelectableTextAlign
-]
-
-# # Function to print default styles
-# def print_default_styles():
-#     for item in dpg.get_all_items():
-#         print(dpg.get_item_info(item))
-#         print(dpg.get_item_theme(item))
-
-
-
-# import dearpygui.dearpygui as dpg
-
-# dpg.create_context()
-
-# with dpg.window(label="Tutorial", pos=(20, 50), width=275, height=225) as win1:
-#     t1 = dpg.add_input_text(default_value="some text")
-#     t2 = dpg.add_input_text(default_value="some text")
-#     with dpg.tab_bar(reorderable=True):
-#         with dpg.tab(label="Tab 1"):
-#             dpg.add_text("This is Tab 1")
-#         with dpg.tab(label="Tab 2"):
-#             dpg.add_text("This is Tab 2")
-#         with dpg.tab(label="Tab 3"):
-#             dpg.add_text("This is Tab 3")
-#     dpg.add_input_text(default_value="some text")
-
-# with dpg.window(label="Tutorial", pos=(320, 50), width=275, height=225) as win2:
-#     dpg.add_input_text(default_value="some text")
-#     dpg.add_input_int()
-
-# with dpg.theme() as container_theme:
-
-#     with dpg.theme_component(dpg.mvAll):
-#         dpg.add_theme_color(dpg.mvThemeCol_Tab, (150, 100, 100), category=dpg.mvThemeCat_Core)
-#         dpg.add_theme_style(dpg.dpg.mvStyleVar_FrameRounding, 5, category=dpg.mvThemeCat_Core)
-
-#     with dpg.theme_component(dpg.mvInputInt):
-#         dpg.add_theme_color(dpg.mvThemeCol_FrameBg, (100, 150, 100), category=dpg.mvThemeCat_Core)
-#         dpg.add_theme_style(dpg.dpg.mvStyleVar_FrameRounding, 5, category=dpg.mvThemeCat_Core)
-
-# dpg.bind_item_theme(win1, container_theme)
-# dpg.bind_theme(container_theme)
-
-# dpg.create_viewport(title='Custom Title', width=800, height=600)
-# dpg.setup_dearpygui()
-# dpg.show_viewport()
-# dpg.start_dearpygui()
-# dpg.destroy_context()
-
-# import dearpygui.dearpygui as dpg
-
-# dpg.create_context()
-# dpg.create_viewport()
-# dpg.setup_dearpygui()
-
-# dpg.show_font_manager()
-
-# dpg.show_viewport()
-# dpg.start_dearpygui()
-# dpg.destroy_context()
\ No newline at end of file
diff --git a/fonts/Montserrat-Medium.ttf b/fonts/Montserrat-Medium.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..dfc7e2fc59dfbfaf577dc2777f6bb910a6d04d1f
Binary files /dev/null and b/fonts/Montserrat-Medium.ttf differ
diff --git a/icon.ico b/icons/icon.ico
similarity index 100%
rename from icon.ico
rename to icons/icon.ico
diff --git a/prerun.py b/prerun.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad253af620e7981a9c14737483ba14132382754e
--- /dev/null
+++ b/prerun.py
@@ -0,0 +1,10 @@
+import os
+import subprocess
+
+os.chdir(os.path.join(os.getcwd(), 'config-parser'))
+subprocess.run(['g++', '-std=c++11', '-Wall', '-DEXCLUDE_GPU_BRANCH', '-c', 'parser-cli.cpp', '-o', 'parser-cli.o'])
+subprocess.run(['g++', '-std=c++11', '-Wall', '-DEXCLUDE_GPU_BRANCH', '-c', 'config-parser.cpp', '-o', 'config-parser.o'])
+subprocess.run(['g++', '-std=c++11', '-Wall', '-DEXCLUDE_GPU_BRANCH', '-c', 'cfg-var.cpp', '-o', 'cfg-var.o'])
+subprocess.run(['g++', '-std=c++11', '-Wall', '-DEXCLUDE_GPU_BRANCH', '-c', 'str-com.cpp', '-o', 'str-com.o'])
+subprocess.run(['g++', '-std=c++11', '-Wall', '-DEXCLUDE_GPU_BRANCH', '-o', 'parser-cli', 'parser-cli.o', 'config-parser.o', 'cfg-var.o', 'str-com.o'])
+os.chdir('..')
\ No newline at end of file
diff --git a/dpg_gui_styles.py b/styles.py
similarity index 87%
rename from dpg_gui_styles.py
rename to styles.py
index c449d189a47f14778f832fbfbb0dfed80463c5b1..adbc8bd92d5c0257f08f5c1156b9b17189c4ce8f 100644
--- a/dpg_gui_styles.py
+++ b/styles.py
@@ -1,15 +1,17 @@
 import dearpygui.dearpygui as dpg
 
-FONT_PATH = "D:\\fonts\\Montserrat\\static\\Montserrat-Medium.ttf"
+FONT_PATH = "fonts\\Montserrat-Medium.ttf"
+FONT_SIZE = 24
 ACCENT_COLOR = (0, 119, 200, 100)
 ROUNDING = 10
 SPACE = 10
 INDENT = 40
+ICON_PATH = "icons\\icon.ico"
 
 class GuiStyle:
     def __init__(self):
         self.font_registry = dpg.add_font_registry()
-        self.montserrat_font = dpg.add_font(FONT_PATH, 24, parent=self.font_registry)
+        self.montserrat_font = dpg.add_font(FONT_PATH, FONT_SIZE, parent=self.font_registry)
 
         self.main_theme = dpg.add_theme()
         theme_all = dpg.add_theme_component(dpg.mvAll, parent=self.main_theme, tag="theme_all")
@@ -59,4 +61,5 @@ class GuiStyle:
         dpg.add_theme_style(dpg.mvStyleVar_IndentSpacing, 30, category=dpg.mvThemeCat_Core, parent=theme_all)
         dpg.add_theme_style(dpg.mvStyleVar_ChildBorderSize, 3, category=dpg.mvThemeCat_Core, parent=theme_all)
         dpg.add_theme_style(dpg.mvStyleVar_WindowBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all)
-        dpg.add_theme_style(dpg.mvStyleVar_FrameBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all)
\ No newline at end of file
+        dpg.add_theme_style(dpg.mvStyleVar_FrameBorderSize, 0, category=dpg.mvThemeCat_Core, parent=theme_all)
+        dpg.add_theme_style(dpg.mvStyleVar_WindowMinSize, 200, 200, category=dpg.mvThemeCat_Core, parent=theme_all)
\ No newline at end of file