Adjusting our text editor for portability

The main changes we will need to make will be in the texteditor.py file. Open up this file and add the following:

...
import os
from pathlib import Path
...
def __init__(self):
...
self.config_dir = os.path.join(str(Path.home()), ".tkedit")
self.default_scheme_path = os.path.join(self.config_dir,
'schemes/default.yaml')
self.python_language_path = os.path.join(self.config_dir,
'languages/python.yaml')
self.font_scheme_path = os.path.join(self.config_dir,
'schemes/font.yaml')
self.create_config_directory_if_needed()

In order to access the user's home directory independent of the OS, we will use the pathlib module. The folder where we will be storing the user's YAML files will be called .tkedit and will live inside the user's home folder. To obtain the home folder, we can use Path.home().  This resulting folder is then joined to the .tkedit folder with os.path.join, and this is stored as our config_dir attribute.

Now that we have the folder stored, we can then construct paths inside of it where we will be storing our schemes and languages folders.

Once that is taken care of, we call a new method named create_config_directory_if_needed, which will take care of initializing these folders if they do not exist on the user's system:

def create_config_directory_if_needed(self):
if not os.path.exists(self.config_dir):
os.mkdir(self.config_dir)
os.mkdir(os.path.join(self.config_dir, 'schemes'))
os.mkdir(os.path.join(self.config_dir, 'languages'))

self.create_default_scheme_if_needed()
self.create_font_scheme_if_needed()
self.create_python_language_if_needed()

In this method, we use os.path.exists to check whether there is already a .tkedit folder in the user's home folder. If there is not, we use the os.mkdir method to create the directory, as well as the schemes and languages folders it needs to contain.

Since these folders may have just been created, we need to also put the default YAML files inside them if they aren't there already. We have three new methods for doing this:

def create_default_scheme_if_needed(self):
if not os.path.exists(self.default_scheme_path):
yaml_file_contents = "background: 'lightgrey' "
+ "foreground: 'black' "
+ "text_background: 'white' "
+ "text_foreground: 'black' "

with open(self.default_scheme_path, 'w') as yaml_file:
yaml_file.write(yaml_file_contents)

In this first method, we check for the default scheme, which controls the color of our application and the Text widget inside it. If the file does not exist, we use a string to represent the default content and write this as the content of our schemes/default.yaml file:

def create_font_scheme_if_needed(self):
if not os.path.exists(self.font_scheme_path):
yaml_file_contents = "family: Ubuntu Mono "
+ "size: 14"

with open(self.font_scheme_path, 'w') as yaml_file:
yaml_file.write(yaml_file_contents)

This second method does much the same thing, but for our schemes/font.yaml file, which controls the editor's font family and size:

    def create_python_language_if_needed(self):
if not os.path.exists(self.python_language_path):
yaml_file_contents = """
categories:
keywords:
color: orange
...
"""
with open(self.python_language_path, 'w') as yaml_file:
yaml_file.write(yaml_file_contents)

Our final new method does the same thing again for our languages/python.yaml file. I have omitted the content of this file for brevity; when following along, paste the content of the file in between the sets of speech marks.

You will notice that the indentation looks a little off here, which is because YAML is whitespace-sensitive. You may split each line as its own string for neatness, if you wish.

Now that our YAML files are taken care of, we need to replace all hardcoded references to them with the relevant attribute:

def __init__(self):
...
self.load_scheme_file(self.default_scheme_path)
self.configure_ttk_elements()

self.font_size = 15
self.font_family = "Ubuntu Mono"
self.load_font_file(self.font_scheme_path)
...
self.highlighter = Highlighter(self.text_area, self.python_language_path)

def update_font(self):
self.load_font_file(self.font_scheme_path)
self.text_area.configure(font=(self.font_family, self.font_size))

We will also have to update our fontchooser.py and colorchooser.py files to use the attributes:

### fontchooser.py
def save(self):
font_family = self.font_list.get(self.font_list.curselection()[0])
yaml_file_contents = f"family: {font_family} "
+ f"size: {self.size_input.get()}"

with open(self.master.font_scheme_path, 'w') as file:
file.write(yaml_file_contents)

self.master.update_font()


### colorchooser.py
def save(self):
yaml_file_contents = f"background: '{self.chosen_background_color.get()}' "
+ f"foreground: '{self.chosen_foreground_color.get()}' "
+ f"text_background: '{self.chosen_text_background_color.get()}' "
+ f"text_foreground: '{self.chosen_text_foreground_color.get()}' "

with open(self.master.default_scheme_path, "w") as yaml_file:
yaml_file.write(yaml_file_contents)
...

With that, we are ready to package! We can now begin the steps necessary for packaging up our application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset