Include logging utilities form cargo-flash/embed into the cli utils as they are the same
diff --git a/probe-rs-cli-util/Cargo.toml b/probe-rs-cli-util/Cargo.toml
index 8382f5d..2bf1d38 100644
--- a/probe-rs-cli-util/Cargo.toml
+++ b/probe-rs-cli-util/Cargo.toml
@@ -17,7 +17,11 @@
 [dependencies]
 structopt = "0.3.16"
 anyhow = "1.0"
+indicatif = "0.15.0"
+env_logger = "0.8.1"
 log = "0.4.0"
+lazy_static = "1.4.0"
+colored = "2.0.0"
 probe-rs = { version = "0.9.0", path = "../probe-rs" }
 cargo_toml = "0.8.1"
 serde = { version = "1.0.115", features = [ "derive" ] }
diff --git a/probe-rs-cli-util/src/lib.rs b/probe-rs-cli-util/src/lib.rs
index 43a2296..6ff4559 100644
--- a/probe-rs-cli-util/src/lib.rs
+++ b/probe-rs-cli-util/src/lib.rs
@@ -1,3 +1,5 @@
+mod logging;
+
 use anyhow::{anyhow, Context, Result};
 use cargo_toml::Manifest;
 use serde::Deserialize;
diff --git a/probe-rs-cli-util/src/logging.rs b/probe-rs-cli-util/src/logging.rs
new file mode 100644
index 0000000..5a50632
--- /dev/null
+++ b/probe-rs-cli-util/src/logging.rs
@@ -0,0 +1,138 @@
+use colored::*;
+use env_logger::Builder;
+use indicatif::ProgressBar;
+use log::{Level, LevelFilter};
+use std::{
+    fmt,
+    sync::{
+        atomic::{AtomicUsize, Ordering},
+        Arc, RwLock,
+    },
+};
+
+static MAX_WINDOW_WIDTH: AtomicUsize = AtomicUsize::new(0);
+
+lazy_static::lazy_static! {
+    /// Stores the progress bar for the logging facility.
+    static ref PROGRESS_BAR: RwLock<Option<Arc<ProgressBar>>> = RwLock::new(None);
+}
+
+struct Padded<T> {
+    value: T,
+    width: usize,
+}
+
+impl<T: fmt::Display> fmt::Display for Padded<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{: <width$}", self.value, width = self.width)
+    }
+}
+
+fn max_target_width(target: &str) -> usize {
+    let max_width = MAX_WINDOW_WIDTH.load(Ordering::Relaxed);
+    if max_width < target.len() {
+        MAX_WINDOW_WIDTH.store(target.len(), Ordering::Relaxed);
+        target.len()
+    } else {
+        max_width
+    }
+}
+
+fn colored_level(level: Level) -> ColoredString {
+    match level {
+        Level::Trace => "TRACE".magenta().bold(),
+        Level::Debug => "DEBUG".blue().bold(),
+        Level::Info => " INFO".green().bold(),
+        Level::Warn => " WARN".yellow().bold(),
+        Level::Error => "ERROR".red().bold(),
+    }
+}
+
+/// Initialize the logger.
+///
+/// There are two sources of log level configuration:
+///
+/// - The config file can define the default log level through `general.log_level`.
+/// - The user can set the `RUST_LOG` env var, which overrides the log level from the config.
+///
+/// The config file only accepts a log level, while the `RUST_LOG` variable
+/// supports the full `env_logger` syntax, including filtering by crate and
+/// module.
+pub fn init(level: Option<Level>) {
+    let mut builder = Builder::new();
+
+    // First, apply log level from the config
+    if let Some(level) = level {
+        builder.filter_level(level.to_level_filter());
+    } else {
+        builder.filter_level(LevelFilter::Warn);
+    }
+
+    // Then override that with the `RUST_LOG` env var, if set
+    if let Ok(s) = ::std::env::var("RUST_LOG") {
+        builder.parse_filters(&s);
+    }
+
+    // Custom log format
+    builder.format(move |f, record| {
+        let target = record.target();
+        let max_width = max_target_width(target);
+
+        let level = colored_level(record.level());
+
+        let mut style = f.style();
+        let target = style.set_bold(true).value(Padded {
+            value: target,
+            width: max_width,
+        });
+
+        let guard = PROGRESS_BAR.write().unwrap();
+        if let Some(pb) = &*guard {
+            pb.println(format!("       {} {} > {}", level, target, record.args()));
+        } else {
+            println!("       {} {} > {}", level, target, record.args());
+        }
+
+        Ok(())
+    });
+
+    builder.init();
+}
+
+/// Sets the current progress bar in store for the logging facility.
+pub fn set_progress_bar(progress: Arc<ProgressBar>) {
+    let mut guard = PROGRESS_BAR.write().unwrap();
+    *guard = Some(progress);
+}
+
+/// Clears current progress bar in store for the logging facility.
+pub fn clear_progress_bar() {
+    let mut guard = PROGRESS_BAR.write().unwrap();
+    *guard = None;
+}
+
+/// Writes an error to the log.
+/// This can be used for unwraps/eprintlns/etc.
+pub fn eprintln(message: impl AsRef<str>) {
+    let guard = PROGRESS_BAR.write().unwrap();
+
+    match guard.as_ref() {
+        Some(pb) if !pb.is_finished() => {
+            pb.println(message.as_ref());
+        }
+        _ => {
+            eprintln!("{}", message.as_ref());
+        }
+    }
+}
+
+/// Writes an error to the log.
+/// This can be used for unwraps/eprintlns/etc.
+pub fn println(message: impl AsRef<str>) {
+    let guard = PROGRESS_BAR.write().unwrap();
+    if let Some(pb) = &*guard {
+        pb.println(message.as_ref());
+    } else {
+        println!("{}", message.as_ref());
+    }
+}