diff --git a/src/functions.rs b/src/functions.rs
new file mode 100644
index 0000000..8b217e8
--- /dev/null
+++ b/src/functions.rs
@@ -0,0 +1,178 @@
+use std::{collections::HashMap, fs, process::exit};
+use tmdb::{model::*, themoviedb::*};
+use torrent_name_parser::Metadata;
+use youchoose;
+
+use crate::structs::{Language, MovieEntry};
+
+// Get the version from Cargo.toml
+const VERSION: &str = env!("CARGO_PKG_VERSION");
+
+// Function to process movie entries
+pub fn process_file(
+    filename: &String,
+    tmdb: &TMDb,
+    pattern: &str,
+    dry_run: bool,
+) -> (String, bool) {
+    // Get the basename
+    let mut file_base = String::from(filename);
+    let mut parent = String::from("");
+    match filename.rsplit_once("/") {
+        Some(parts) => {
+            parent = parts.0.to_string();
+            file_base = parts.1.to_string();
+        }
+        None => {}
+    }
+
+    // Parse the filename for metadata
+    let metadata = Metadata::from(file_base.as_str()).expect("Could not parse filename!");
+    // Search using the TMDb API
+    let mut search = tmdb.search();
+    search.title(metadata.title());
+
+    // Check if year is present in filename
+    if let Some(year) = metadata.year() {
+        search.year(year as u64);
+    }
+
+    let mut results = Vec::new();
+    if let Ok(search_results) = search.execute() {
+        results = search_results.results;
+    } else {
+        eprintln!("There was an error while searching {}!", filename);
+    }
+
+    let mut movie_list: Vec<MovieEntry> = Vec::new();
+    // Create movie entry from the result
+    for result in results {
+        let mut movie_details = MovieEntry::from(result);
+        // Get director's name, if needed
+        if pattern.contains("{director}") {
+            let with_credits: Result<Movie, _> =
+                tmdb.fetch().id(movie_details.id).append_credits().execute();
+            if let Ok(movie) = with_credits {
+                if let Some(cre) = movie.credits {
+                    let mut directors = cre.crew;
+                    directors.retain(|x| x.job == "Director");
+                    for person in directors {
+                        movie_details.director = person.name;
+                    }
+                }
+            }
+        }
+        movie_list.push(movie_details);
+    }
+
+    // If nothing is found, skip
+    if movie_list.len() == 0 {
+        eprintln!("Could not find any entries matching {}!", filename);
+        return ("".to_string(), true);
+    }
+
+    // Choose from the possible entries
+    let mut menu = youchoose::Menu::new(movie_list.iter())
+        .preview(display)
+        .preview_label(file_base.to_string());
+    let choice = menu.show()[0];
+
+    let mut extension = metadata.extension().unwrap_or("").to_string();
+    // Handle the case for subtitle files
+    let mut is_subtitle = false;
+    if ["srt", "ssa"].contains(&extension.as_str()) {
+        let languages = Language::generate_list();
+        let mut lang_menu = youchoose::Menu::new(languages.iter());
+        let lang_choice = lang_menu.show()[0];
+        if languages[lang_choice].short != "none".to_string() {
+            extension = format!("{}.{}", languages[lang_choice].short, extension);
+        }
+        is_subtitle = true;
+    }
+
+    // Create the new name
+    let mut new_name_base = movie_list[choice].rename_format(pattern.to_string());
+    if extension != "" {
+        new_name_base = format!("{}.{}", new_name_base, extension);
+    }
+    let mut new_name = String::from(new_name_base.clone());
+    if parent != "".to_string() {
+        new_name = format!("{}/{}", parent, new_name);
+    }
+
+    // Process the renaming
+    if *filename == new_name {
+        println!("[file] {} already has correct name.", filename);
+    } else {
+        println!("[file] {} -> {}", file_base, new_name_base);
+        // Only do the rename of --dry-run isn't passed
+        if dry_run == false {
+            fs::rename(filename, new_name.as_str()).expect("Unable to rename file!");
+        }
+    }
+    (new_name_base, is_subtitle)
+}
+
+// Display function for preview in menu
+fn display(movie: &MovieEntry) -> String {
+    let mut buffer = String::new();
+    buffer.push_str(&format!("Title: {}\n", movie.title));
+    buffer.push_str(&format!("Release year: {}\n", movie.year));
+    buffer.push_str(&format!("Language: {}\n", movie.language));
+    buffer.push_str(&format!("Director: {}\n", movie.director));
+    buffer.push_str(&format!("TMDb ID: {}\n", movie.id));
+    buffer.push_str(&format!("Overview: {}\n", movie.overview));
+    buffer
+}
+
+// Function to process the passed arguments
+pub fn process_args(mut args: Vec<String>) -> (Vec<String>, HashMap<&'static str, bool>) {
+    // Remove the entry corresponding to the running process
+    args.remove(0);
+    let mut entries = Vec::new();
+    let mut settings = HashMap::from([("dry_run", false), ("directory", false)]);
+    for arg in args {
+        match arg.as_str() {
+            "--help" | "-h" => {
+                println!("  The expected syntax is:");
+                println!(
+                    "  movie_rename <filename(s)> [-n|--dry-run] [-d|--directory] [-v|--version]"
+                );
+                println!(
+                "  There needs to be a config file names movie_rename.conf in your $XDG_CONFIG_HOME."
+                );
+                println!("  It should consist of two lines. The first line should have your TMDb API key.");
+                println!(
+                    "  The second line should have a pattern, that will be used for the rename."
+                );
+                println!("  In the pattern, the variables need to be enclosed in {{}}, the supported variables are `title`, `year` and `director`.");
+                println!(
+                "  Default pattern is `{{title}} ({{year}}) - {{director}}`. Extension is always kept."
+                );
+                println!("Passing --directory assumes that the arguments are directory names, which contain exactly one movie and optionally subtitles.");
+                println!("  Pass --help to get this again.");
+                exit(0);
+            }
+            "--dry-run" | "-n" => {
+                println!("Doing a dry run...");
+                settings.entry("dry_run").and_modify(|x| *x = true);
+            }
+            "--directory" | "-d" => {
+                println!("Running in directory mode...");
+                settings.entry("directory").and_modify(|x| *x = true);
+            }
+            "--version" | "-v" => {
+                println!("movie_rename {}", VERSION);
+                exit(0);
+            }
+            other => {
+                if other.starts_with("-") {
+                    eprintln!("Unknown argument passed: {}", other);
+                } else {
+                    entries.push(arg);
+                }
+            }
+        }
+    }
+    (entries, settings)
+}
diff --git a/src/main.rs b/src/main.rs
index 0a7e0b9..9b7bb37 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,58 +1,11 @@
 use load_file::{self, load_str};
-use std::{collections::HashMap, env, fmt, fs, path::Path, process::exit};
-use tmdb::{model::*, themoviedb::*};
-use torrent_name_parser::Metadata;
-use youchoose;
+use std::{env, fs, path::Path, process::exit};
+use tmdb::themoviedb::*;
 
-// Get the version from Cargo.toml
-const VERSION: &str = env!("CARGO_PKG_VERSION");
-
-// Struct for movie entries
-struct MovieEntry {
-    title: String,
-    id: u64,
-    director: String,
-    year: String,
-    language: String,
-    overview: String,
-}
-
-impl MovieEntry {
-    // Create movie entry from results
-    fn from(movie: SearchMovie) -> MovieEntry {
-        MovieEntry {
-            title: movie.title,
-            id: movie.id,
-            director: String::from("N/A"),
-            year: String::from(movie.release_date.split('-').next().unwrap_or("N/A")),
-            language: movie.original_language,
-            overview: movie.overview.unwrap_or(String::from("N/A")),
-        }
-    }
-
-    // Generate desired filename from movie entry
-    fn rename_format(&self, mut format: String) -> String {
-        format = format.replace("{title}", self.title.as_str());
-        if self.year.as_str() != "N/A" {
-            format = format.replace("{year}", self.year.as_str());
-        } else {
-            format = format.replace("{year}", "");
-        }
-        if self.director.as_str() != "N/A" {
-            format = format.replace("{director}", self.director.as_str());
-        } else {
-            format = format.replace("{director}", "");
-        }
-        format
-    }
-}
-
-// Implement display trait for movie entries
-impl fmt::Display for MovieEntry {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{} ({})", self.title, self.year)
-    }
-}
+// Import all the modules
+mod functions;
+use functions::{process_args, process_file};
+mod structs;
 
 fn main() {
     // Read arguments from commandline
@@ -142,167 +95,3 @@ fn main() {
         }
     }
 }
-
-// Function to process movie entries
-fn process_file(filename: &String, tmdb: &TMDb, pattern: &str, dry_run: bool) -> (String, bool) {
-    // Get the basename
-    let mut file_base = String::from(filename);
-    let mut parent = String::from("");
-    match filename.rsplit_once("/") {
-        Some(parts) => {
-            parent = parts.0.to_string();
-            file_base = parts.1.to_string();
-        }
-        None => {}
-    }
-
-    // Parse the filename for metadata
-    let metadata = Metadata::from(file_base.as_str()).expect("Could not parse filename!");
-    // Search using the TMDb API
-    let mut search = tmdb.search();
-    search.title(metadata.title());
-
-    // Check if year is present in filename
-    if let Some(year) = metadata.year() {
-        search.year(year as u64);
-    }
-
-    let mut results = Vec::new();
-    if let Ok(search_results) = search.execute() {
-        results = search_results.results;
-    } else {
-        eprintln!("There was an error while searching {}!", filename);
-    }
-
-    let mut movie_list: Vec<MovieEntry> = Vec::new();
-    // Create movie entry from the result
-    for result in results {
-        let mut movie_details = MovieEntry::from(result);
-        // Get director's name, if needed
-        if pattern.contains("{director}") {
-            let with_credits: Result<Movie, _> =
-                tmdb.fetch().id(movie_details.id).append_credits().execute();
-            if let Ok(movie) = with_credits {
-                if let Some(cre) = movie.credits {
-                    let mut directors = cre.crew;
-                    directors.retain(|x| x.job == "Director");
-                    for person in directors {
-                        movie_details.director = person.name;
-                    }
-                }
-            }
-        }
-        movie_list.push(movie_details);
-    }
-
-    // If nothing is found, skip
-    if movie_list.len() == 0 {
-        eprintln!("Could not find any entries matching {}!", filename);
-        return ("".to_string(), true);
-    }
-
-    // Choose from the possible entries
-    let mut menu = youchoose::Menu::new(movie_list.iter())
-        .preview(display)
-        .preview_label(file_base.to_string());
-    let choice = menu.show()[0];
-
-    let mut extension = metadata.extension().unwrap_or("").to_string();
-    // Handle the case for subtitle files
-    let mut is_subtitle = false;
-    if ["srt", "ssa"].contains(&extension.as_str()) {
-        let languages = Vec::from(["en", "hi", "bn", "de", "fr", "sp", "ja", "n/a"]);
-        let mut lang_menu = youchoose::Menu::new(languages.iter());
-        let lang_choice = lang_menu.show()[0];
-        if languages[lang_choice] != "none" {
-            extension = format!("{}.{}", languages[lang_choice], extension);
-        }
-        is_subtitle = true;
-    }
-
-    // Create the new name
-    let new_name_base = movie_list[choice].rename_format(pattern.to_string());
-    let mut new_name = String::from(new_name_base.clone());
-    if extension != "" {
-        new_name = format!("{}.{}", new_name, extension);
-    }
-    if parent != "".to_string() {
-        new_name = format!("{}/{}", parent, new_name);
-    }
-
-    // Process the renaming
-    if *filename == new_name {
-        println!("[file] {} already has correct name.", filename);
-    } else {
-        println!("[file] {} -> {}", file_base, new_name);
-        // Only do the rename of --dry-run isn't passed
-        if dry_run == false {
-            fs::rename(filename, new_name.as_str()).expect("Unable to rename file!");
-        }
-    }
-    (new_name_base, is_subtitle)
-}
-
-// Display function for preview in menu
-fn display(movie: &MovieEntry) -> String {
-    let mut buffer = String::new();
-    buffer.push_str(&format!("Title: {}\n", movie.title));
-    buffer.push_str(&format!("Release year: {}\n", movie.year));
-    buffer.push_str(&format!("Language: {}\n", movie.language));
-    buffer.push_str(&format!("Director: {}\n", movie.director));
-    buffer.push_str(&format!("TMDb ID: {}\n", movie.id));
-    buffer.push_str(&format!("Overview: {}\n", movie.overview));
-    buffer
-}
-
-// Function to process the passed arguments
-fn process_args(mut args: Vec<String>) -> (Vec<String>, HashMap<&'static str, bool>) {
-    // Remove the entry corresponding to the running process
-    args.remove(0);
-    let mut entries = Vec::new();
-    let mut settings = HashMap::from([("dry_run", false), ("directory", false)]);
-    for arg in args {
-        match arg.as_str() {
-            "--help" | "-h" => {
-                println!("  The expected syntax is:");
-                println!(
-                    "  movie_rename <filename(s)> [-n|--dry-run] [-d|--directory] [-v|--version]"
-                );
-                println!(
-                "  There needs to be a config file names movie_rename.conf in your $XDG_CONFIG_HOME."
-                );
-                println!("  It should consist of two lines. The first line should have your TMDb API key.");
-                println!(
-                    "  The second line should have a pattern, that will be used for the rename."
-                );
-                println!("  In the pattern, the variables need to be enclosed in {{}}, the supported variables are `title`, `year` and `director`.");
-                println!(
-                "  Default pattern is `{{title}} ({{year}}) - {{director}}`. Extension is always kept."
-                );
-                println!("Passing --directory assumes that the arguments are directory names, which contain exactly one movie and optionally subtitles.");
-                println!("  Pass --help to get this again.");
-                exit(0);
-            }
-            "--dry-run" | "-n" => {
-                println!("Doing a dry run...");
-                settings.entry("dry_run").and_modify(|x| *x = true);
-            }
-            "--directory" | "-d" => {
-                println!("Running in directory mode...");
-                settings.entry("directory").and_modify(|x| *x = true);
-            }
-            "--version" | "-v" => {
-                println!("movie_rename {}", VERSION);
-                exit(0);
-            }
-            other => {
-                if other.starts_with("-") {
-                    eprintln!("Unknown argument passed: {}", other);
-                } else {
-                    entries.push(arg);
-                }
-            }
-        }
-    }
-    (entries, settings)
-}
diff --git a/src/structs.rs b/src/structs.rs
new file mode 100644
index 0000000..e2d07fb
--- /dev/null
+++ b/src/structs.rs
@@ -0,0 +1,85 @@
+use std::fmt;
+use tmdb::model::*;
+
+// Struct for movie entries
+pub struct MovieEntry {
+    pub title: String,
+    pub id: u64,
+    pub director: String,
+    pub year: String,
+    pub language: String,
+    pub overview: String,
+}
+
+impl MovieEntry {
+    // Create movie entry from results
+    pub fn from(movie: SearchMovie) -> MovieEntry {
+        MovieEntry {
+            title: movie.title,
+            id: movie.id,
+            director: String::from("N/A"),
+            year: String::from(movie.release_date.split('-').next().unwrap_or("N/A")),
+            language: movie.original_language,
+            overview: movie.overview.unwrap_or(String::from("N/A")),
+        }
+    }
+
+    // Generate desired filename from movie entry
+    pub fn rename_format(&self, mut format: String) -> String {
+        format = format.replace("{title}", self.title.as_str());
+        if self.year.as_str() != "N/A" {
+            format = format.replace("{year}", self.year.as_str());
+        } else {
+            format = format.replace("{year}", "");
+        }
+        if self.director.as_str() != "N/A" {
+            format = format.replace("{director}", self.director.as_str());
+        } else {
+            format = format.replace("{director}", "");
+        }
+        format
+    }
+}
+
+// Implement display trait for movie entries
+impl fmt::Display for MovieEntry {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{} ({})", self.title, self.year)
+    }
+}
+
+pub struct Language {
+    pub short: String,
+    pub long: String,
+}
+
+impl Language {
+    // Create Language entries from &str pairs
+    fn from(short: &str, long: &str) -> Language {
+        Language {
+            short: short.to_string(),
+            long: long.to_string(),
+        }
+    }
+
+    // Generate a vector of Language entries of all supported languages
+    pub fn generate_list() -> Vec<Language> {
+        let mut list = Vec::new();
+        list.push(Language::from("en", "English"));
+        list.push(Language::from("hi", "Hindi"));
+        list.push(Language::from("bn", "Bengali"));
+        list.push(Language::from("fr", "French"));
+        list.push(Language::from("ja", "Japanese"));
+        list.push(Language::from("de", "German"));
+        list.push(Language::from("sp", "Spanish"));
+        list.push(Language::from("none", "None"));
+        list
+    }
+}
+
+// Implement display trait for Language
+impl fmt::Display for Language {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.long)
+    }
+}