mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-16 23:18:47 +00:00
assignment 1~5: fixes
- assignment05/pascal.mlw: lowered the difficulty (one more invariant given) - assignment02, 03: minor fixes & divide into sub-problems
This commit is contained in:
79
src/assignments/assignment03/custom_operators.rs
Normal file
79
src/assignments/assignment03/custom_operators.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
//! You will implement a number of custom operators.
|
||||
|
||||
/// Custom option type.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum MyOption<T> {
|
||||
/// Some value of type `T`.
|
||||
MySome(T),
|
||||
/// No value.
|
||||
MyNone,
|
||||
}
|
||||
|
||||
/// Maps an `MyOption<T>` to `MyOption<U>` by applying a function to a contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Converts an `MyOption<String>` into an `MyOption<usize>`, consuming the original:
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment03::{my_map, MyOption};
|
||||
///
|
||||
/// fn len(s: String) -> usize {
|
||||
/// s.len()
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(my_map(MyOption::MySome(String::from("Hello, World!")), len), MyOption::MySome(13));
|
||||
/// assert_eq!(my_map(MyOption::MyNone, len), MyOption::MyNone);
|
||||
/// ```
|
||||
pub fn my_map<T, U, F: FnOnce(T) -> U>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns `MyNone` if the option is `MyNone`, otherwise calls `f` with the wrapped value and returns the result.
|
||||
///
|
||||
/// Some languages call this operation flatmap.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment03::{MyOption, my_and_then};
|
||||
///
|
||||
/// fn pos_then_to_string(x: isize) -> MyOption<String> {
|
||||
/// if x > 0 {
|
||||
/// MyOption::MySome(x.to_string())
|
||||
/// } else {
|
||||
/// MyOption::MyNone
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(my_and_then(MyOption::MySome(2), pos_then_to_string), MyOption::MySome(2.to_string()));
|
||||
/// assert_eq!(my_and_then(MyOption::MySome(-3), pos_then_to_string), MyOption::MyNone);
|
||||
/// assert_eq!(my_and_then(MyOption::MyNone, pos_then_to_string), MyOption::MyNone);
|
||||
/// ```
|
||||
pub fn my_and_then<T, U, F: FnOnce(T) -> MyOption<U>>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Custom operator: `option_op_or(v1, v2, f)`
|
||||
/// If neither `v1` nor `v2` is `Some`, returns `None`.
|
||||
/// If exactly one is `Some`, returns the same `Some` value.
|
||||
/// If both are `Some`, apply the values inside `Some` to `f` and wrap the resulting value inside `Some`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// fn product(a: i32, b: i32) -> i32 {
|
||||
/// a * b
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(option_op_or(None, None, product), None);
|
||||
/// assert_eq!(option_op_or(Some(3), None, product), Some(3));
|
||||
/// assert_eq!(option_op_or(Some(3), Some(5), product), Some(15));
|
||||
/// ```
|
||||
pub fn my_option_op_or<T, F: FnOnce(T, T) -> T>(
|
||||
v1: MyOption<T>,
|
||||
v2: MyOption<T>,
|
||||
f: F,
|
||||
) -> MyOption<T> {
|
||||
todo!()
|
||||
}
|
||||
58
src/assignments/assignment03/custom_operators_grade.rs
Normal file
58
src/assignments/assignment03/custom_operators_grade.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment03::custom_operators::{MyOption::*, *};
|
||||
|
||||
#[test]
|
||||
fn test_my_map() {
|
||||
fn len(s: &str) -> usize {
|
||||
s.len()
|
||||
}
|
||||
|
||||
fn plus_one(x: isize) -> isize {
|
||||
x + 1
|
||||
}
|
||||
|
||||
fn is_positive(x: f64) -> bool {
|
||||
x > 0.0f64
|
||||
}
|
||||
|
||||
assert_eq!(my_map(MySome("Hello, World!"), len), MySome(13));
|
||||
assert_eq!(my_map(MyNone, len), MyNone);
|
||||
|
||||
assert_eq!(my_map(MySome(1), plus_one), MySome(2));
|
||||
assert_eq!(my_map(MyNone, plus_one), MyNone);
|
||||
|
||||
assert_eq!(my_map(MySome(5.0f64), is_positive), MySome(true));
|
||||
assert_eq!(my_map(MySome(-3.0f64), is_positive), MySome(false));
|
||||
assert_eq!(my_map(MyNone::<f64>, is_positive), MyNone);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_my_and_then() {
|
||||
fn plus_one(x: isize) -> MyOption<isize> {
|
||||
MySome(x + 1)
|
||||
}
|
||||
|
||||
fn none(_: isize) -> MyOption<isize> {
|
||||
MyNone
|
||||
}
|
||||
|
||||
assert_eq!(my_and_then(MySome(1), plus_one), MySome(2));
|
||||
assert_eq!(my_and_then(MySome(1), none), MyNone);
|
||||
|
||||
assert_eq!(my_and_then(MyNone, plus_one), MyNone);
|
||||
assert_eq!(my_and_then(MyNone, none), MyNone);
|
||||
}
|
||||
|
||||
fn product(a: i32, b: i32) -> i32 {
|
||||
a * b
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_my_option_op_or() {
|
||||
assert_eq!(my_option_op_or(MyNone, MyNone, product), MyNone);
|
||||
assert_eq!(my_option_op_or(MySome(3), MyNone, product), MySome(3));
|
||||
assert_eq!(my_option_op_or(MyNone, MySome(5), product), MySome(5));
|
||||
assert_eq!(my_option_op_or(MySome(3), MySome(5), product), MySome(15));
|
||||
}
|
||||
}
|
||||
13
src/assignments/assignment03/mod.rs
Normal file
13
src/assignments/assignment03/mod.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
//! Assignment 3: Mastering common programming concepts (2/2)
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-03.sh` works fine.
|
||||
//! See `*_grade.rs` and `/scripts/grade-03.sh` for the test script.
|
||||
|
||||
pub mod small_problems;
|
||||
mod small_problems_grade;
|
||||
|
||||
pub mod parse_shell;
|
||||
mod parse_shell_grade;
|
||||
|
||||
pub mod custom_operators;
|
||||
mod custom_operators_grade;
|
||||
28
src/assignments/assignment03/parse_shell.rs
Normal file
28
src/assignments/assignment03/parse_shell.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//! Parsing a shell command.
|
||||
//!
|
||||
//! Shell commands are text-based instructions that you can enter in a command-line interface (CLI)
|
||||
//! to interact with operating systems (e.g. Linux) and others.
|
||||
//! For example, you can use the `ls` command to list files in a directory.
|
||||
//!
|
||||
//! You will parse a given string consists of a small number of shell commands.
|
||||
|
||||
/// Parse the string as a shell command.
|
||||
///
|
||||
/// Usually, a shell command is whitespace-separated array of strings.
|
||||
/// ```text
|
||||
/// cat file --> ["cat", "file"]
|
||||
/// ```
|
||||
/// But sometimes, you may want to include whitespaces in each argument.
|
||||
/// In that case, you can use quotes.
|
||||
/// ```text
|
||||
/// ls 'VirtualBox VMs' --> ["ls", 'VirtualBox VMs']
|
||||
/// ls VirtualBox' 'VMs --> ["ls", 'VirtualBox VMs']
|
||||
/// ```
|
||||
///
|
||||
/// For simplicity, you may assume that the string only contains alphanumeric characters, spaces
|
||||
/// (" "), and single quotes ("'").
|
||||
///
|
||||
/// See `test_shell` for more examples.
|
||||
pub fn parse_shell_command(command: &str) -> Vec<String> {
|
||||
todo!()
|
||||
}
|
||||
38
src/assignments/assignment03/parse_shell_grade.rs
Normal file
38
src/assignments/assignment03/parse_shell_grade.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment03::parse_shell::*;
|
||||
|
||||
#[test]
|
||||
fn test_shell() {
|
||||
assert_eq!(
|
||||
parse_shell_command("cat file"),
|
||||
vec!["cat".to_string(), "file".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("ls 'VirtualBox VMs'"),
|
||||
vec!["ls".to_string(), "VirtualBox VMs".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("ls VirtualBox' 'VMs"),
|
||||
vec!["ls".to_string(), "VirtualBox VMs".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("echo once upon a midnight dreary"),
|
||||
vec![
|
||||
"echo".to_string(),
|
||||
"once".to_string(),
|
||||
"upon".to_string(),
|
||||
"a".to_string(),
|
||||
"midnight".to_string(),
|
||||
"dreary".to_string(),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("echo 'once upon a midnight dreary'"),
|
||||
vec![
|
||||
"echo".to_string(),
|
||||
"once upon a midnight dreary".to_string(),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
130
src/assignments/assignment03/small_problems.rs
Normal file
130
src/assignments/assignment03/small_problems.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
//! Small problems.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
||||
/// Day of week.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum DayOfWeek {
|
||||
/// Sunday.
|
||||
Sun,
|
||||
/// Monday.
|
||||
Mon,
|
||||
/// Tuesday.
|
||||
Tue,
|
||||
/// Wednesday.
|
||||
Wed,
|
||||
/// Thursday.
|
||||
Thu,
|
||||
/// Friday.
|
||||
Fri,
|
||||
/// Saturday.
|
||||
Sat,
|
||||
}
|
||||
|
||||
/// The next day of week.
|
||||
///
|
||||
/// `next_weekday(Thu)` is `Fri`; and `next_weekday(Fri)` is `Mon`.
|
||||
pub fn next_weekday(day: DayOfWeek) -> DayOfWeek {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Given a list of integers, returns its median (when sorted, the value in the middle position).
|
||||
///
|
||||
/// For a data set `x` of `n` elements, the median can be defined as follows:
|
||||
///
|
||||
/// - If `n` is odd, the median is `(n+1)/2`-th smallest element of `x`.
|
||||
/// - If `n` is even, the median is `(n/2)+1`-th smallest element of `x`.
|
||||
///
|
||||
/// For example, the following list of seven numbers,
|
||||
///
|
||||
/// ```ignore
|
||||
/// vec![1, 3, 3, 6, 7, 8, 9]
|
||||
/// ```
|
||||
///
|
||||
/// has the median of 6, which is the fourth value. And for this data set of eight numbers,
|
||||
///
|
||||
/// ```ignore
|
||||
/// vec![1, 2, 3, 4, 5, 6, 8, 9]
|
||||
/// ```
|
||||
///
|
||||
/// it has the median of 5, which is the fifth value.
|
||||
///
|
||||
/// Returns `None` if the list is empty.
|
||||
pub fn median(values: Vec<isize>) -> Option<isize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Given a list of integers, returns its smallest mode (the value that occurs most often; a hash map will be helpful here).
|
||||
///
|
||||
/// Returns `None` if the list is empty.
|
||||
pub fn mode(values: Vec<isize>) -> Option<isize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Converts the given string to Pig Latin. Use the rules below to translate normal English into Pig Latin.
|
||||
///
|
||||
/// 1. If a word starts with a consonant and a vowel, move the first letter of the word at the end of the word and add "ay".
|
||||
///
|
||||
/// Example: "happy" -> "appyh" + "ay" -> "appyhay"
|
||||
///
|
||||
/// 2. If a word starts with multiple consonants, move them to the end of the word and add "ay".
|
||||
///
|
||||
/// Example: "string" -> "ingstr" + "ay" -> "ingstray"
|
||||
///
|
||||
/// 3. If a word starts with a vowel, add the word "hay" at the end of the word.
|
||||
///
|
||||
/// Example: "explain" -> "explain" + "hay" -> "explainhay"
|
||||
///
|
||||
/// Keep in mind the details about UTF-8 encoding!
|
||||
///
|
||||
/// You may assume the string only contains lowercase alphabets, and it contains at least one vowel.
|
||||
pub fn piglatin(input: String) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Converts HR commands to the organization table.
|
||||
///
|
||||
/// If the commands are as follows:
|
||||
///
|
||||
/// ```ignore
|
||||
/// vec!["Add Amir to Engineering", "Add Sally to Sales", "Remove Jeehoon from Sales", "Move Amir from Engineering to Sales"]
|
||||
/// ```
|
||||
///
|
||||
/// The return value should be:
|
||||
///
|
||||
/// ```ignore
|
||||
/// ["Sales" -> ["Amir", "Sally"]]
|
||||
/// ```
|
||||
///
|
||||
/// - The result is a map from department to the list of its employees.
|
||||
/// - An empty department should not appear in the result.
|
||||
/// - There are three commands: "Add {person} to {department}", "Remove {person} from {department}", and "Move {person} from {department} to {department}".
|
||||
/// - If a command is not executable, then it's ignored.
|
||||
/// - There is no space in the name of the person and department.
|
||||
///
|
||||
/// See the test function for more details.
|
||||
pub fn organize(commands: Vec<String>) -> HashMap<String, HashSet<String>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Events in a text editor.
|
||||
#[derive(Debug)]
|
||||
pub enum TypeEvent {
|
||||
/// A character is typed.
|
||||
Type(char),
|
||||
/// The last character is removed.
|
||||
Backspace,
|
||||
/// The whole string is copied to the clipboard.
|
||||
Copy,
|
||||
/// The string in the clipboard is appended.
|
||||
Paste,
|
||||
}
|
||||
|
||||
/// Starting from an empty string and an empty clipboard,
|
||||
/// processes the given `events` in order and returns the resulting string.
|
||||
///
|
||||
/// See the test function `test_editor` for examples.
|
||||
pub fn use_editor(events: Vec<TypeEvent>) -> String {
|
||||
todo!()
|
||||
}
|
||||
179
src/assignments/assignment03/small_problems_grade.rs
Normal file
179
src/assignments/assignment03/small_problems_grade.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment03::small_problems::*;
|
||||
|
||||
#[test]
|
||||
fn test_next_weekday() {
|
||||
assert_eq!(next_weekday(DayOfWeek::Sun), DayOfWeek::Mon);
|
||||
assert_eq!(next_weekday(DayOfWeek::Mon), DayOfWeek::Tue);
|
||||
assert_eq!(next_weekday(DayOfWeek::Tue), DayOfWeek::Wed);
|
||||
assert_eq!(next_weekday(DayOfWeek::Wed), DayOfWeek::Thu);
|
||||
assert_eq!(next_weekday(DayOfWeek::Thu), DayOfWeek::Fri);
|
||||
assert_eq!(next_weekday(DayOfWeek::Fri), DayOfWeek::Mon);
|
||||
assert_eq!(next_weekday(DayOfWeek::Sat), DayOfWeek::Mon);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_median() {
|
||||
assert_eq!(median(vec![]), None);
|
||||
assert_eq!(median(vec![1]), Some(1));
|
||||
assert_eq!(median(vec![1, 2]), Some(2));
|
||||
assert_eq!(median(vec![2, 4, 5, 1, 3]), Some(3));
|
||||
assert_eq!(median(vec![2, 3, 5, 7, 11, 13]), Some(7));
|
||||
assert_eq!(median(vec![1, 3, 3, 6, 7, 8, 9]), Some(6));
|
||||
assert_eq!(median(vec![6, 7, 3, 1, 9, 3, 8]), Some(6));
|
||||
assert_eq!(median(vec![1, 2, 3, 4, 5, 6, 8, 9]), Some(5));
|
||||
assert_eq!(median(vec![3, 4, 8, 9, 1, 6, 5, 2]), Some(5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mode() {
|
||||
assert_eq!(mode(vec![]), None);
|
||||
assert_eq!(mode(vec![3]), Some(3));
|
||||
assert_eq!(mode(vec![2, 1, 2, 3]), Some(2));
|
||||
assert_eq!(mode(vec![2, 3, 1, 2, 2, 3, 3]), Some(2));
|
||||
assert_eq!(mode(vec![1, 1, 2, 2, 3, 3]), Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_piglatin() {
|
||||
assert_eq!(piglatin("pig".to_string()), "igpay".to_string());
|
||||
assert_eq!(piglatin("latin".to_string()), "atinlay".to_string());
|
||||
assert_eq!(piglatin("banana".to_string()), "ananabay".to_string());
|
||||
assert_eq!(piglatin("will".to_string()), "illway".to_string());
|
||||
assert_eq!(piglatin("butler".to_string()), "utlerbay".to_string());
|
||||
assert_eq!(piglatin("happy".to_string()), "appyhay".to_string());
|
||||
assert_eq!(piglatin("duck".to_string()), "uckday".to_string());
|
||||
assert_eq!(piglatin("me".to_string()), "emay".to_string());
|
||||
assert_eq!(piglatin("bagel".to_string()), "agelbay".to_string());
|
||||
assert_eq!(piglatin("history".to_string()), "istoryhay".to_string());
|
||||
|
||||
assert_eq!(piglatin("smile".to_string()), "ilesmay".to_string());
|
||||
assert_eq!(piglatin("string".to_string()), "ingstray".to_string());
|
||||
assert_eq!(piglatin("stupid".to_string()), "upidstay".to_string());
|
||||
assert_eq!(piglatin("glove".to_string()), "oveglay".to_string());
|
||||
assert_eq!(piglatin("trash".to_string()), "ashtray".to_string());
|
||||
assert_eq!(piglatin("floor".to_string()), "oorflay".to_string());
|
||||
assert_eq!(piglatin("store".to_string()), "orestay".to_string());
|
||||
|
||||
assert_eq!(piglatin("eat".to_string()), "eathay".to_string());
|
||||
assert_eq!(piglatin("omelet".to_string()), "omelethay".to_string());
|
||||
assert_eq!(piglatin("are".to_string()), "arehay".to_string());
|
||||
assert_eq!(piglatin("egg".to_string()), "egghay".to_string());
|
||||
assert_eq!(piglatin("explain".to_string()), "explainhay".to_string());
|
||||
assert_eq!(piglatin("ends".to_string()), "endshay".to_string());
|
||||
assert_eq!(piglatin("amulet".to_string()), "amulethay".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_organize() {
|
||||
assert_eq!(
|
||||
organize(vec![
|
||||
"Add Amir to Engineering".to_string(),
|
||||
"Add Sally to Sales".to_string(),
|
||||
"Remove Jeehoon from Sales".to_string(),
|
||||
"Move Amir from Engineering to Sales".to_string(),
|
||||
]),
|
||||
[(
|
||||
"Sales".to_string(),
|
||||
["Amir".to_string(), "Sally".to_string()].into()
|
||||
)]
|
||||
.into()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
organize(vec![
|
||||
"Add Jeehoon to Mathematics".to_string(),
|
||||
"Add Minseong to Mathematics".to_string(),
|
||||
"Add Seungmin to Computer-Science".to_string(),
|
||||
"Move Jeehoon from Mathematics to Computer-Science".to_string(),
|
||||
"Remove Minseong from Mathematics".to_string(),
|
||||
"Add Minseong to Computer-Science".to_string(),
|
||||
]),
|
||||
[(
|
||||
"Computer-Science".to_string(),
|
||||
[
|
||||
"Seungmin".to_string(),
|
||||
"Jeehoon".to_string(),
|
||||
"Minseong".to_string()
|
||||
]
|
||||
.into()
|
||||
)]
|
||||
.into()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
organize(vec![
|
||||
"Move P1 from D1 to D2".to_string(),
|
||||
"Remove P2 from D2".to_string(),
|
||||
"Add P3 to D3".to_string(),
|
||||
"Add P4 to D1".to_string(),
|
||||
"Add P3 to D4".to_string(),
|
||||
"Move P3 from D4 to D2".to_string(),
|
||||
]),
|
||||
[
|
||||
("D1".to_string(), ["P4".to_string()].into()),
|
||||
("D2".to_string(), ["P3".to_string()].into()),
|
||||
("D3".to_string(), ["P3".to_string()].into())
|
||||
]
|
||||
.into()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_editor() {
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Type('c')
|
||||
]),
|
||||
"bc"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Paste
|
||||
]),
|
||||
"aaabaaab"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Paste, // clipboard starts empty
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Type('n'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Backspace
|
||||
]),
|
||||
"banana"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace
|
||||
]),
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user