<commit_before>// Copyright 2016 <NAME>, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(inclusive_range_syntax)]
#![feature(drop_types_in_const)]
#![allow(stable_features)] // lying about question_mark because 1.14.0 isn't released!

#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate alacritty;
extern crate cgmath;
extern crate copypasta;
extern crate errno;
extern crate font;
extern crate glutin;
extern crate libc;
extern crate mio;
extern crate notify;
extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;
extern crate vte;

#[macro_use]
extern crate bitflags;

use std::sync::{mpsc, Arc};
use std::sync::atomic::Ordering;

use parking_lot::{MutexGuard};

use alacritty::Flag;
use alacritty::Rgb;
use alacritty::config::{self, Config};
use alacritty::event;
use alacritty::gl;
use alacritty::input;
use alacritty::meter::Meter;
use alacritty::renderer::{QuadRenderer, GlyphCache};
use alacritty::sync::FairMutex;
use alacritty::term::{self, Term};
use alacritty::tty::{self, Pty, process_should_exit};
use alacritty::event_loop::EventLoop;

/// Channel used by resize handling on mac
static mut RESIZE_CALLBACK: Option<Box<Fn(u32, u32)>> = None;

/// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) {
    unsafe {
        RESIZE_CALLBACK.as_ref().map(|func| func(width, height));
    }
}

fn main() {
    // Load configuration
    let (config, config_path) = match Config::load() {
        Err(err) => match err {
            // Use default config when not found
            config::Error::NotFound => (Config::default(), None),
            // Exit when there's a problem with it
            _ => die!("{}", err),
        },
        Ok((config, path)) => (config, Some(path)),
    };

    let mut ref_test = false;
    let mut columns = 80;
    let mut lines = 24;

    let mut args_iter = ::std::env::args();
    while let Some(arg) = args_iter.next() {
        match &arg[..] {
            // Generate ref test
            "--ref-test" => ref_test = true,
            // Set dimensions
            "-d" | "--dimensions" => {
                args_iter.next()
                    .map(|w| w.parse().map(|w| columns = w));
                args_iter.next()
                    .map(|h| h.parse().map(|h| lines = h));
            },
            // ignore unexpected
            _ => (),
        }
    }

    let font = config.font();
    let dpi = config.dpi();
    let render_timer = config.render_timer();

    let mut window = glutin::WindowBuilder::new()
                                           .with_vsync()
                                           .with_title("Alacritty")
                                           .build().unwrap();

    window.set_window_resize_callback(Some(window_resize_handler as fn(u32, u32)));

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    let (width, height) = window.get_inner_size_pixels().unwrap();
    let dpr = window.hidpi_factor();

    println!("device_pixel_ratio: {}", dpr);

    let _ = unsafe { window.make_current() };
    unsafe {
        // gl::Viewport(0, 0, width as i32, height as i32);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);

    // Create renderer
    let mut renderer = QuadRenderer::new(&config, width, height);

    // Initialize glyph cache
    let glyph_cache = {
        println!("Initializing glyph cache");
        let init_start = ::std::time::Instant::now();

        let cache = renderer.with_loader(|mut api| {
            GlyphCache::new(rasterizer, &config, &mut api)
        });

        let stop = init_start.elapsed();
        let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
        println!("Finished initializing glyph cache in {}", stop_f);

        cache
    };

    let metrics = glyph_cache.font_metrics();
    let cell_width = (metrics.average_advance + font.offset().x() as f64) as u32;
    let cell_height = (metrics.line_height + font.offset().y() as f64) as u32;

    // Resize window to be 80 col x 24 lines
    let width = cell_width * columns + 4;
    let height = cell_height * lines + 4;
    println!("set_inner_size: {} x {}", width, height);
    // Is this in points?
    let width_pts = (width as f32 / dpr) as u32;
    let height_pts = (height as f32 / dpr) as u32;
    println!("set_inner_size: {} x {}; pts: {} x {}", width, height, width_pts, height_pts);
    window.set_inner_size(width_pts, height_pts);
    renderer.resize(width as _, height as _);

    println!("Cell Size: ({} x {})", cell_width, cell_height);

    let size = term::SizeInfo {
        width: width as f32,
        height: height as f32,
        cell_width: cell_width as f32,
        cell_height: cell_height as f32
    };

    let terminal = Term::new(size);
    let pty = tty::new(size.lines(), size.cols());
    pty.resize(size.lines(), size.cols(), size.width as usize, size.height as usize);
    let pty_io = pty.reader();

    let (tx, rx) = mpsc::channel();

    let signal_flag = Flag::new(false);

    let terminal = Arc::new(FairMutex::new(terminal));

    // Setup the rsize callback for osx
    let terminal_ref = terminal.clone();
    let signal_flag_ref = signal_flag.clone();
    let proxy = window.create_window_proxy();
    let tx2 = tx.clone();
    unsafe {
        RESIZE_CALLBACK = Some(Box::new(move |width: u32, height: u32| {
            let _ = tx2.send((width, height));
            if !signal_flag_ref.0.swap(true, Ordering::AcqRel) {
               // We raised the signal flag
                let mut terminal = terminal_ref.lock();
                terminal.dirty = true;
                proxy.wakeup_event_loop();
            }
        }));
    }

    let event_loop = EventLoop::new(
        terminal.clone(),
        window.create_window_proxy(),
        signal_flag.clone(),
        pty_io,
        ref_test,
    );

    let loop_tx = event_loop.channel();
    let event_loop_handle = event_loop.spawn(None);

    // Wraps a renderer and gives simple draw() api.
    let mut display = Display::new(
        &window,
        renderer,
        glyph_cache,
        render_timer,
        rx,
        pty
    );

    // Event processor
    let mut processor = event::Processor::new(
        input::LoopNotifier(loop_tx),
        terminal.clone(),
        tx,
        &config,
        ref_test,
    );

    let (config_tx, config_rx) = mpsc::channel();

    // create a config watcher when config is loaded from disk
    let _config_reloader = config_path.map(|config_path| {
        config::Watcher::new(config_path, ConfigHandler {
            tx: config_tx,
            window: window.create_window_proxy(),
        })
    });

    // Main loop
    loop {
        // Wait for something to happen
        processor.process_events(&window);

        if let Ok(config) = config_rx.try_recv() {
            display.update_config(&config);
            processor.update_config(&config);
        }

        // Maybe draw the terminal
        let terminal = terminal.lock();
        signal_flag.set(false);
        if terminal.dirty {
            display.draw(terminal, &config);
        }

        if process_should_exit() {
            break;
        }
    }

    // FIXME need file watcher to work with custom delegates before
    //       joining config reloader is possible
    // config_reloader.join().ok();

    // shutdown
    event_loop_handle.join().ok();
    println!("Goodbye");
}

struct ConfigHandler {
    tx: mpsc::Sender<config::Config>,
    window: ::glutin::WindowProxy,<commit_msg>Add comments in main loop<commit_after>// Copyright 2016 <NAME>, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(inclusive_range_syntax)]
#![feature(drop_types_in_const)]
#![allow(stable_features)] // lying about question_mark because 1.14.0 isn't released!

#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate alacritty;
extern crate cgmath;
extern crate copypasta;
extern crate errno;
extern crate font;
extern crate glutin;
extern crate libc;
extern crate mio;
extern crate notify;
extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;
extern crate vte;

#[macro_use]
extern crate bitflags;

use std::sync::{mpsc, Arc};
use std::sync::atomic::Ordering;

use parking_lot::{MutexGuard};

use alacritty::Flag;
use alacritty::Rgb;
use alacritty::config::{self, Config};
use alacritty::event;
use alacritty::gl;
use alacritty::input;
use alacritty::meter::Meter;
use alacritty::renderer::{QuadRenderer, GlyphCache};
use alacritty::sync::FairMutex;
use alacritty::term::{self, Term};
use alacritty::tty::{self, Pty, process_should_exit};
use alacritty::event_loop::EventLoop;

/// Channel used by resize handling on mac
static mut RESIZE_CALLBACK: Option<Box<Fn(u32, u32)>> = None;

/// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) {
    unsafe {
        RESIZE_CALLBACK.as_ref().map(|func| func(width, height));
    }
}

fn main() {
    // Load configuration
    let (config, config_path) = match Config::load() {
        Err(err) => match err {
            // Use default config when not found
            config::Error::NotFound => (Config::default(), None),
            // Exit when there's a problem with it
            _ => die!("{}", err),
        },
        Ok((config, path)) => (config, Some(path)),
    };

    let mut ref_test = false;
    let mut columns = 80;
    let mut lines = 24;

    let mut args_iter = ::std::env::args();
    while let Some(arg) = args_iter.next() {
        match &arg[..] {
            // Generate ref test
            "--ref-test" => ref_test = true,
            // Set dimensions
            "-d" | "--dimensions" => {
                args_iter.next()
                    .map(|w| w.parse().map(|w| columns = w));
                args_iter.next()
                    .map(|h| h.parse().map(|h| lines = h));
            },
            // ignore unexpected
            _ => (),
        }
    }

    let font = config.font();
    let dpi = config.dpi();
    let render_timer = config.render_timer();

    let mut window = glutin::WindowBuilder::new()
                                           .with_vsync()
                                           .with_title("Alacritty")
                                           .build().unwrap();

    window.set_window_resize_callback(Some(window_resize_handler as fn(u32, u32)));

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    let (width, height) = window.get_inner_size_pixels().unwrap();
    let dpr = window.hidpi_factor();

    println!("device_pixel_ratio: {}", dpr);

    let _ = unsafe { window.make_current() };
    unsafe {
        // gl::Viewport(0, 0, width as i32, height as i32);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);

    // Create renderer
    let mut renderer = QuadRenderer::new(&config, width, height);

    // Initialize glyph cache
    let glyph_cache = {
        println!("Initializing glyph cache");
        let init_start = ::std::time::Instant::now();

        let cache = renderer.with_loader(|mut api| {
            GlyphCache::new(rasterizer, &config, &mut api)
        });

        let stop = init_start.elapsed();
        let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
        println!("Finished initializing glyph cache in {}", stop_f);

        cache
    };

    let metrics = glyph_cache.font_metrics();
    let cell_width = (metrics.average_advance + font.offset().x() as f64) as u32;
    let cell_height = (metrics.line_height + font.offset().y() as f64) as u32;

    // Resize window to be 80 col x 24 lines
    let width = cell_width * columns + 4;
    let height = cell_height * lines + 4;
    println!("set_inner_size: {} x {}", width, height);
    // Is this in points?
    let width_pts = (width as f32 / dpr) as u32;
    let height_pts = (height as f32 / dpr) as u32;
    println!("set_inner_size: {} x {}; pts: {} x {}", width, height, width_pts, height_pts);
    window.set_inner_size(width_pts, height_pts);
    renderer.resize(width as _, height as _);

    println!("Cell Size: ({} x {})", cell_width, cell_height);

    let size = term::SizeInfo {
        width: width as f32,
        height: height as f32,
        cell_width: cell_width as f32,
        cell_height: cell_height as f32
    };

    let terminal = Term::new(size);
    let pty = tty::new(size.lines(), size.cols());
    pty.resize(size.lines(), size.cols(), size.width as usize, size.height as usize);
    let pty_io = pty.reader();

    let (tx, rx) = mpsc::channel();

    let signal_flag = Flag::new(false);

    let terminal = Arc::new(FairMutex::new(terminal));

    // Setup the rsize callback for osx
    let terminal_ref = terminal.clone();
    let signal_flag_ref = signal_flag.clone();
    let proxy = window.create_window_proxy();
    let tx2 = tx.clone();
    unsafe {
        RESIZE_CALLBACK = Some(Box::new(move |width: u32, height: u32| {
            let _ = tx2.send((width, height));
            if !signal_flag_ref.0.swap(true, Ordering::AcqRel) {
               // We raised the signal flag
                let mut terminal = terminal_ref.lock();
                terminal.dirty = true;
                proxy.wakeup_event_loop();
            }
        }));
    }

    let event_loop = EventLoop::new(
        terminal.clone(),
        window.create_window_proxy(),
        signal_flag.clone(),
        pty_io,
        ref_test,
    );

    let loop_tx = event_loop.channel();
    let event_loop_handle = event_loop.spawn(None);

    // Wraps a renderer and gives simple draw() api.
    let mut display = Display::new(
        &window,
        renderer,
        glyph_cache,
        render_timer,
        rx,
        pty
    );

    // Event processor
    let mut processor = event::Processor::new(
        input::LoopNotifier(loop_tx),
        terminal.clone(),
        tx,
        &config,
        ref_test,
    );

    let (config_tx, config_rx) = mpsc::channel();

    // create a config watcher when config is loaded from disk
    let _config_reloader = config_path.map(|config_path| {
        config::Watcher::new(config_path, ConfigHandler {
            tx: config_tx,
            window: window.create_window_proxy(),
        })
    });

    // Main loop
    loop {
        // Wait for something to happen
        processor.process_events(&window);

        // Handle config reloads
        if let Ok(config) = config_rx.try_recv() {
            display.update_config(&config);
            processor.update_config(&config);
        }

        // Maybe draw the terminal
        let terminal = terminal.lock();
        signal_flag.set(false);
        if terminal.dirty {
            display.draw(terminal, &config);
        }

        // Begin shutdown if the flag was raised.
        if process_should_exit() {
            break;
        }
    }

    // FIXME need file watcher to work with custom delegates before
    //       joining config reloader is possible
    // config_reloader.join().ok();

    // shutdown
    event_loop_handle.join().ok();
    println!("Goodbye");
}

struct ConfigHandler {
    tx: mpsc::Sender<config::Config>,
    window: ::glutin::WindowProxy,
{'fraction_non_alphanumeric': 0.1297582991864125, 'fraction_numerical': 0.010570698972623077, 'mean_word_length': 2.502495840266223, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3566240', 'n_tokens_mistral': 5344, 'n_tokens_neox': 5106, 'n_words': 1385}