set number # set set nonumber # unset set number! # toggle
set numberwidth=3 # key=value set number numberwidth=3 # Multiple setting at once
Saving session
1
mksession my-work-session.vim
Auto complete
Press Ctrl+n in insert mode.
File Explorer
Give ::Explore command
Repeating commands
Press qX where X=any letter to start recording.
Use some commands
Press @X where X=previously used letter.
You can use @@ after using @X once.
Bookmarks
mX where X=a-z for setting local bookmarks(In same file).
mX where X=A-Z for setting global bookmarks(In any file).
‘X where X=a-zA-Z to go to the bookmarks.
:marks to show all the bookmarks.
Searching Text
Type / in normal mode, then insert keyword and press enter. Cursor will go to the first occurrence of the keyword. Press n to go to the next occurrence or N to go to previous occurrence.
Pressing * will search the current word under cursor.
Char type: ‘x’. 4 bytes, so unicode char is also supported. let x: char = 'x'.
Compound Types
Tuples:
Fixed size in compile time.
Can contain different types.
Use vaiable_name.INDEX to specify individual elements: INDEX starts from 0.
1 2 3 4 5 6 7 8
lettup = (500, 'x', 10.5); let (x, y, z) = tup; // Destructuring
println!("2nd value is {y}");
// You can also index specific elements letsecond_value = tup.1; println!("2nd value is {second_value}");
Array:
Contains elements of fixed types.
1 2 3
leta = [1, 2, 3, 4, 5]; leta: [i32; 5] = [1, 2, 3, 4, 5]; // With size and type annotated leta = [3; 5]; // 5 elements as 3
Functions
1 2 3 4 5 6 7 8 9
fnmain() { letx = plus_one(5);
println!("The value of x is: {x}"); }
fnplus_one(x: i32) ->i32 { x + 1 }
Statements vs Expressions
Expressions evaluate to values.
Expressions doesn’t end with semicolon.
Expressions can be converted to statements by using semicolon at the end.
Function return is specified using expressions in rust.
Control Flow
if/else
Condition must be boolean
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { letnumber = 6;
if number % 4 == 0 { println!("number is divisible by 4"); } elseif number % 3 == 0 { println!("number is divisible by 3"); } elseif number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } }
If is an expression so can be used in let statement
When the owner goes out of scope, the value will be dropped.
In rust the memory is automatically returned once the variable that owns it goes out of scope. When a variable goes out of scope rust calls a special method drop(). This is implemented on the specific type. This function is responsible for cleaning up memory for that type.
Variables and Data Interacting with Move
Rust always do shallow copy.
1 2 3 4 5 6 7 8
lets1 = String::from("hello"); // s1 and s2 are pointing to the same data // as data isn't copied. // // s1's ownership is moved to s2. s1 no longer valid lets2 = s1;
println!("{}, world!", s1); // Won't compile s1 not valid
Variables and Data Interacting with Clone
It is possible to do deep copy with clone() method.
fnmain() { lets = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function... // ... and so is no longer valid here
letx = 5; // x comes into scope
makes_copy(x); // x would move into the function, // but i32 is Copy, so it's okay to still // use x afterward
// This won't compile as ownership is moved println!("String {s}");
} // Here, x goes out of scope, then s. But because s's value was moved, nothing // special happens.
fntakes_ownership(some_string: String) { // some_string comes into scope println!("{}", some_string); } // Here, some_string goes out of scope and `drop` is called. The backing // memory is freed.
fnmakes_copy(some_integer: i32) { // some_integer comes into scope println!("{}", some_integer); } // Here, some_integer goes out of scope. Nothing special happens.
fnmain() { lets1 = gives_ownership(); // gives_ownership moves its return // value into s1
lets2 = String::from("hello"); // s2 comes into scope
lets3 = takes_and_gives_back(s2); // s2 is moved into // takes_and_gives_back, which also // moves its return value into s3 } // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing // happens. s1 goes out of scope and is dropped.
fngives_ownership() ->String { // gives_ownership will move its // return value into the function // that calls it
letsome_string = String::from("yours"); // some_string comes into scope
some_string // some_string is returned and // moves out to the calling // function }
// This function takes a String and returns one fntakes_and_gives_back(a_string: String) ->String { // a_string comes into // scope
a_string // a_string is returned and moves out to the calling function }
Reference and Borrowing
To use functions with parameters you need to give ownership of the parameters to the function and then return it back:
1 2 3 4 5 6 7 8 9 10 11 12 13
fnmain() { lets1 = String::from("hello");
let (s2, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s2, len); }
fncalculate_length(s: String) -> (String, usize) { letlength = s.len(); // len() returns the length of a String
(s, length) }
To remove this hassle one can use references to refer to some value without taking ownership. This is called borrowing in rust terminology.
To change the value of the variable that a reference is pointing to, the reference also need to be mutable. For example following code won’t compile:
1 2 3 4 5 6 7 8 9 10 11 12
fnmain() { lets = String::from("hello");
change(&s); }
// The reference some_string isn't mutable // so it won't compile as it is changing // the value of the variable it is poiting to. fnchange(some_string: &String) { some_string.push_str(", world"); }
fnmain() { // All the fields are mutable now letmut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, };
letuser2 = User { email: String::from("another@example.com"), ..user1 }; }
Update syntax uses move semantics. So if any of the fields uses move semantic then the ownership will be moved. For example user1 will be invalid after using the update syntaxt on user2. as email and username field ownership will be moved
Using Tuple Structs without Named Fields to Create Different Types
Works like reduced match. Only handle one case and ignore all the other case.
Consider following code:
1 2 3 4 5 6 7 8 9
fnmain() { letconfig_max = Some(3u8); // if config_max has value then print it // if it is None do nothing match config_max { Some(max) => println!("The maximum is configured to be {}", max), _ => (), } }
This can be expressed more consciously with if/let combo:
You must annotate the type while creating a new vector.
1
letv: Vec<i32> = Vec::new();
If initial values are provided rust will infer the type.
1
letv = vec![1, 2, 3];
Updating a vecotr:
1 2 3 4 5 6 7 8
fnmain() { letmut v = Vec::new();
v.push(5); v.push(6); v.push(7); v.push(8); }
There are two ways to reference a value stored in a vector: via indexing or using the get method. If get method is used Option<&T> is returned.
1 2 3 4 5 6 7 8 9 10 11 12
fnmain() { letv = vec![1, 2, 3, 4, 5];
letthird: &i32 = &v[2]; println!("The third element is {third}");
letthird: Option<&i32> = v.get(2); match third { Some(third) => println!("The third element is {third}"), None => println!("There is no third element."), } }
Ownership and borrowing rules are applicable for references to a vector. Following code won’t compile:
Mutable reference: To change the value that the mutable reference refers to, we have to use the * dereference operator to get to the value .
1 2 3 4 5 6
fnmain() { letmut v = vec![100, 32, 57]; foriin &mut v { *i += 50; } }
Using Enum to store multiple types: Vectors can only store values that are the same type. Enums can be used as workaround for this. With enum definitions different types can coexists in a vector.
Accesing values in a hashmap: Values can be accesed with get method. Get method returns Options<&T>. copied method can be used to convert to Options<T>. In the following example unwrap_or is used to convert the value to 0 if returned value is None (If no such key).
Hashmap and ownership: For types that implement the Copy trait, like i32, the values are copied into the hash map. For owned values like String, the values will be moved and the hash map will be the owner of those values
letmut map = HashMap::new(); map.insert(field_name, field_value); // field_name and field_value are invalid at this point, try using them and // see what compiler error you get! }
Inserting a value for the same key will overwrite it’s value
Adding a Key and Value Only If a Key Isn’t Present: entry method returns an enum Entry that represents a value that might or might not exist. The or_insert method on Entry is defined to return a mutable reference to the value for the corresponding Entry key if that key exists, and if not, inserts the parameter as the new value for this key and returns a mutable reference to the new value.
The unwrap method is a shortcut method implemented just like the match expression. If the Result value is the Ok variant, unwrap will return the value inside the Ok. If the Result is the Err variant, unwrap will call the panic! macro
The ? placed after a Result value is defined to work in almost the same way as the match expressions is defined to handle the Result values. If the value of the Result is an Ok, the value inside the Ok will get returned from this expression, and the program will continue. If the value is an Err, the Err will be returned from the whole function as if the return keyword is used so that the error value gets propagated to the calling code.
There is a difference between what the match expression does and what the ? operator does: error values that have the ? operator called on them go through the from function, defined in the From trait in the standard library, which is used to convert values from one type into another. When the ? operator calls the from function, the error type received is converted into the error type defined in the return type of the current function. This is useful when a function returns one error type to represent all the ways a function might fail, even if parts might fail for many different reasons.
1 2 3 4 5 6 7 8 9 10 11 12
#![allow(unused)] fnmain() { use std::fs::File; use std::io::{self, Read};
The ? operator can only be used in functions whose return type is compatible with the value the ? is used on. This operator can be used in a function that returns Result, Option, or another type that implements FromResidual.
? operator can be used on a Result in a function that returns Result, and you can be use on an Option in a function that returns Option.
To use ? in main() return type of main needs to be Result<(), E>:
letresult = largest(&number_list); println!("The largest number is {}", result);
letchar_list = vec!['y', 'm', 'a', 'q'];
letresult = largest(&char_list); println!("The largest char is {}", result); }
In Struct Definitions
Example 1:
1 2 3 4 5 6 7 8 9 10 11
structPoint<T> { x: T, y: T, }
fnmain() { // Both x and y have to be same type // as the struct definition has same // type T for both fields letwont_work = Point { x: 5, y: 4.0 }; }
Example 2:
1 2 3 4 5 6 7 8 9 10
structPoint<T, U> { x: T, y: U, }
fnmain() { letboth_integer = Point { x: 5, y: 10 }; letboth_float = Point { x: 1.0, y: 4.0 }; letinteger_and_float = Point { x: 5, y: 4.0 }; }
It is possible to implement method on a concrete type. This will restrict the method for that specific type. If a method is implemented on P<f64> that method will only be implemented for P<f64>. Other P<T> won’t have that method.
A trait can be implemented on a type if at least one of the trait or the type it local to the crate. For example, we can implement standard library traits like Display on a custom type like Tweet as part of our aggregator crate functionality, because the type Tweet is local to our aggregator crate. We can also implement Summary on Vec in our aggregator crate, because the trait Summary is local to our aggregator crate. But we can’t implement the Display trait on Vec within our aggregator crate, as both are external to our aggregator crate.
Default Implementations
If implementation is provided for a trait method, then it is not required to implement that method for a type. If a type doesn’t implement it the default implementation of the function will be used.
// This functions can return either NewsArticle or Tweet fnreturns_summarizable(switch: bool) ->implSummary { if switch { NewsArticle { headline: String::from( "Penguins win the Stanley Cup Championship!", ), location: String::from("Pittsburgh, PA, USA"), author: String::from("Iceburgh"), content: String::from( "The Pittsburgh Penguins once again are the best \ hockey team in the NHL.", ), } } else { Tweet { username: String::from("horse_ebooks"), content: String::from( "of course, as you probably already know, people", ), reply: false, retweet: false, } } }
Using Trait Bounds to Conditionally Implement Methods
// new() method is implemented for // all inner type T impl<T> Pair<T> { fnnew(x: T, y: T) ->Self { Self { x, y } } }
// cmp_display() method is only // implemented for inner types // that implements Display and PartialOrd impl<T: Display + PartialOrd> Pair<T> { fncmp_display(&self) { ifself.x >= self.y { println!("The largest member is x = {}", self.x); } else { println!("The largest member is y = {}", self.y); } } }
We can also conditionally implement a trait for any type that implements another trait. Implementations of a trait on any type that satisfies the trait bounds are called blanket implementations.
1 2 3
impl<T: Display> ToStringforT {
}
Lifetime
Lifetimes ensure that references are valid as long as we need them to be.
Most of the cases lifetime is automatically inferred.
we must annotate lifetimes when the lifetimes of references could be related in a few different ways. Rust requires us to annotate the relationships using generic lifetime parameters to ensure the actual references used at runtime will definitely be valid.
The main aim of lifetimes is to prevent dangling references, which cause a program to reference data other than the data it’s intended to reference.
The Borrow Checker
The Rust compiler has a borrow checker that compares scopes to determine whether all borrows are valid.
Following program will be rejected because the borrow checker will see that x’s lifetime ‘b is shorter than r’s lifetime ‘a which is referencing x.
&i32// a reference &'ai32// a reference with an explicit lifetime &'amuti32// a mutable reference with an explicit lifetime
Lifetime Annotations in Function Signatures
Following function signature tells Rust that for some lifetime ‘a, the function takes two parameters, both of which are string slices that live at least as long as lifetime ‘a. The function signature also tells Rust that the string slice returned from the function will live at least as long as lifetime ‘a.
fnlongest<'a>(x: &'astr, y: &'astr) -> &'astr { if x.len() > y.len() { x } else { y } }
When returning a reference from a function, the lifetime parameter for the return type needs to match the lifetime parameter for one of the parameters.
Lifetime Annotations in Struct Definitions
We can define structs to hold references, but in that case we would need to add a lifetime annotation on every reference in the struct’s definition.
1 2 3 4 5 6 7 8 9 10 11
structImportantExcerpt<'a> { part: &'astr, }
fnmain() { letnovel = String::from("Call me Ishmael. Some years ago..."); letfirst_sentence = novel.split('.').next().expect("Could not find a '.'"); leti = ImportantExcerpt { part: first_sentence, }; }
This annotation means an instance of ImportantExcerpt can’t outlive the reference it holds in its part field.
Lifetime Elision
The compiler uses three rules to figure out the lifetimes of the references when there aren’t explicit annotations. The first rule applies to input lifetimes, and the second and third rules apply to output lifetimes. If the compiler gets to the end of the three rules and there are still references for which it can’t figure out lifetimes, the compiler will stop with an error. These rules apply to fn definitions as well as impl blocks.
The first rule is that the compiler assigns a lifetime parameter to each parameter that’s a reference. In other words, a function with one parameter gets one lifetime parameter: fn foo<'a>(x: &'a i32); a function with two parameters gets two separate lifetime parameters: fn foo<'a, 'b>(x: &'a i32, y: &'b i32); and so on.
The second rule is that, if there is exactly one input lifetime parameter, that lifetime is assigned to all output lifetime parameters: fn foo<'a>(x: &'a i32) -> &'a i32.
The third rule is that, if there are multiple input lifetime parameters, but one of them is &self or &mut self because this is a method, the lifetime of self is assigned to all output lifetime parameters.
fnmain() { letnovel = String::from("Call me Ishmael. Some years ago..."); letfirst_sentence = novel.split('.').next().expect("Could not find a '.'"); leti = ImportantExcerpt { part: first_sentence, }; }
The Static Lifetime
'static lifetime denotes that the affected reference can live for the entire duration of the program.
All string literals have the 'static lifetime
Generic Type Parameters, Trait Bounds, and Lifetimes Together
letresult = longest_with_an_announcement( string1.as_str(), string2, "Today is someone's birthday!", ); println!("The longest string is {}", result); }
use std::fmt::Display;
fnlongest_with_an_announcement<'a, T>( x: &'astr, y: &'astr, ann: T, ) -> &'astr where T: Display, { println!("Announcement! {}", ann); if x.len() > y.len() { x } else { y } }
Closures: Anonymous Functions that Capture Their Environment
Capturing the Environment with Closures
The unwrap_or_else() method on Option<T> is defined by the standard library. It takes one argument: a closure without any arguments that returns a value T (the same type stored in the Some variant of the Option<T>)
fnadd_one_v1 (x: u32) ->u32 { x + 1 } letadd_one_v2 = |x: u32| ->u32 { x + 1 }; letadd_one_v3 = |x| { x + 1 }; letadd_one_v4 = |x| x + 1 ;
If type isn’t annotated compiler infers closure’s type.
1 2 3 4 5 6 7 8 9 10 11 12
fnmain() { letexample_closure = |x| x;
// Compiler infers x as String and return type as String // and locks this inference. lets = example_closure(String::from("hello"));
// This will produce a compiler error // as the compiler expects the parameter to be // a string letn = example_closure(5); }
Capturing References or Moving Ownership
Closures can capture values from their environment in three ways, which directly map to the three ways a function can take a parameter: borrowing immutably, borrowing mutably, and taking ownership. The closure will decide which of these to use based on what the body of the function does with the captured values.
Between the closure definition and the closure call, an immutable borrow to print isn’t allowed because no other borrows are allowed when there’s a mutable borrow.
To force the closure to take ownership of the values it uses in the environment even though the body of the closure doesn’t strictly need ownership, you can use the move keyword before the parameter list. This technique is mostly useful when passing a closure to a new thread to move the data so that it’s owned by the new thread.
Moving Captured Values Out of Closures and the Fn Traits
Once a closure has captured a reference or captured ownership of a value from the environment where the closure is defined (thus affecting what, if anything, is moved into the closure), the code in the body of the closure defines what happens to the references or values when the closure is evaluated later (thus affecting what, if anything, is moved out of the closure). A closure body can do any of the following: move a captured value out of the closure, mutate the captured value, neither move nor mutate the value, or capture nothing from the environment to begin with.
The way a closure captures and handles values from the environment affects which traits the closure implements, and traits are how functions and structs can specify what kinds of closures they can use. Closures will automatically implement one, two, or all three of these Fn traits, in an additive fashion, depending on how the closure’s body handles the values:
FnOnce applies to closures that can be called once. All closures implement at least this trait, because all closures can be called. A closure that moves captured values out of its body will only implement FnOnce and none of the other Fn traits, because it can only be called once.
FnMut applies to closures that don’t move captured values out of their body, but that might mutate the captured values. These closures can be called more than once.
Fn applies to closures that don’t move captured values out of their body and that don’t mutate captured values, as well as closures that capture nothing from their environment. These closures can be called more than once without mutating their environment, which is important in cases such as calling a closure multiple times concurrently.
Definition of unwrap_or_else(): Implements FnOnce
1 2 3 4 5 6 7 8 9 10 11
impl<T> Option<T> { pubfnunwrap_or_else<F>(self, f: F) -> T where F: FnOnce() -> T { matchself { Some(x) => x, None => f(), } } }
// this closure is called multiple times list.sort_by_key(|r| r.width); println!("{:#?}", list); }
Iterators
Processing a Series of Items with Iterators
Example:
1 2 3 4 5 6 7 8 9
fnmain() { letv1 = vec![1, 2, 3];
letv1_iter = v1.iter();
forvalin v1_iter { println!("Got: {}", val); } }
The Iterator Trait and the next Method
All iterators implement a trait named Iterator that is defined in the standard library. The definition of the trait looks like this:
1 2 3 4 5 6 7
pubtraitIterator { typeItem;
fnnext(&mutself) ->Option<Self::Item>;
// methods with default implementations elided }
To use iterator for a custom type it has to implement Iterator trait. To implement Iterator define an Item type, and use this Item type in the return type of the next method.
values we get from the calls to next are immutable references to the values in the vector. The iter method produces an iterator over immutable references. If we want to create an iterator that takes ownership of v1 and returns owned values, we can call into_iter instead of iter. Similarly, if we want to iterate over mutable references, we can call iter_mut instead of iter.
Methods that Consume the Iterator
Methods that call next are called consuming adaptors, because calling them uses up the iterator.
Example: sum method, which takes ownership of the iterator and iterates through the items by repeatedly calling next, thus consuming the iterator.
Iterator adaptors are methods defined on the Iterator trait that don’t consume the iterator. Instead, they produce different iterators by changing some aspect of the original iterator.
1 2 3 4 5 6 7
fnmain() { letv1: Vec<i32> = vec![1, 2, 3];
letv2: Vec<_> = v1.iter().map(|x| x + 1).collect();
Implicit Deref Coercions with Functions and Methods
Deref coercion converts a reference to a type that implements the Deref trait into a reference to another type.
Deref coercion is a convenience Rust performs on arguments to functions and methods, and works only on types that implement the Deref trait.
It happens automatically when we pass a reference to a particular type’s value as an argument to a function or method that doesn’t match the parameter type in the function or method definition
It is not possible to disable drop functionality or call drop method on a type directly but memory can be freed earlier using the std::mem::drop function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
structCustomSmartPointer { data: String, }
implDropforCustomSmartPointer { fndrop(&mutself) { println!("Dropping CustomSmartPointer with data `{}`!", self.data); } }
fnmain() { letc = CustomSmartPointer { data: String::from("some data"), }; println!("CustomSmartPointer created."); drop(c); println!("CustomSmartPointer dropped before the end of main."); }
Rc<T>, the Reference Counted Smart Pointer
Share ownership among multiple owners.
Only applicable for single threaded case. (Arc for multi threade).
Rc<T> is useful to allocate data from the heap for multiple parts of a program to read and it is not possible to determine at compile time which part will finish using the data last
Keeps a reference count of the owners. Will free the object when count goes to zero.
Convention is to use Rc::clone(&T) instead of T.clone(). As in most cases T.clone() does deep copy. Though in this case it will do a referance count instead of deep copy. But by using Rc::clone(&T) it possible to visually tell that it is doing reference counting.
fnmain() { leta = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); println!("count after creating a = {}", Rc::strong_count(&a)); letb = Cons(3, Rc::clone(&a)); println!("count after creating b = {}", Rc::strong_count(&a)); { letc = Cons(4, Rc::clone(&a)); println!("count after creating c = {}", Rc::strong_count(&a)); } println!("count after c goes out of scope = {}", Rc::strong_count(&a)); }
RefCell<T> and the Interior Mutability Pattern
Interior mutability: Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data. To mutate data, the pattern uses unsafe code inside a data structure to bend Rust’s usual rules that govern mutation and borrowing.
With references and Box<T> borrowing rules are enforced at compile time but with RefCell<T> borrowing rules are enforced at runtime.
Can only be used in single threaded scenario.
Interior mutability is possible with RefCell<T>.
To get interior mutability enclose the type in RefCell<T>, then call borrow_mut() method on the object to get mutable reference and borrow() method to get immutable reference.
borrow() method returns Ref<T> and borrow_mut() returns RefMut<T>.
Same borrowing rules applied for RefCell<T> but enforced at runtime.
if percentage_of_max >= 1.0 { self.messenger.send("Error: You are over your quota!"); } elseif percentage_of_max >= 0.9 { self.messenger .send("Urgent warning: You've used up over 90% of your quota!"); } elseif percentage_of_max >= 0.75 { self.messenger .send("Warning: You've used up over 75% of your quota!"); } } }
#[cfg(test)] mod tests { use super::*; use std::cell::RefCell;
structMockMessenger { // With RefCell<T> it isn't // possible to mutate this in // send() method of Messanger trait sent_messages: RefCell<Vec<String>>, }
\{m\} - Matches if pattern repeats exactly m times.
\{m,n} - Matches if the pattern repeats m to n times.
\{,n} - Matches if the pattern repeats less or equal n times.
\{m,} - Matches if the pattern repeats more or equal to m times.
\<[tT]he\> - Matches exactly the/The.
\(a\)\1 - (PATTERN) remembers the pattern and the pattern can be used again by \n where n=[1,9]. So total nine patterns can be remembered and backreferenced. Another example: \([a-z]\)\([a-z]\)[a-z]\2\1 matches with any 5 letter palindrome.
int number = 10; QString string = "This a cute string"; QString show = QString("My number is: %1 and my string is: %2\n").arg(number).arg(string); qDebug() << show;
QTextStream
1 2 3 4 5 6 7 8 9 10 11 12 13 14
QString qstr; QTextStream cout(stdout); /* stream text to stdout */ QTextStream cin(stdin); /* take input from stdin */ QTextStream toStringObject(&qstr); /* store in a Qstring */
cout << "Hello, world!\n" cout << QString("First prime number is: %1\n").arg(2);
TEMPLATE = app # Type. Can be lib, subdir etc TARGET = simple # Executable name
QT += core
INCLUDEPATH += . HEADERS = SOURCES = main.cpp
Making a basic QT class with signals and slots
We will create our own string class based on QString. Our class name will be MyString. All QT classes inherits QObject class as base class. Q_OBJECT macro will be used for signals and slots. Slots are just regular member functions. They are called when a signal is emitted. signals are only function prototypes. Their arguments must match with the slots, they are emitted. Slots can be called as regular member function too. In the constructor QObject argument is taken as parent so that others can make QObject as parent for safe memory deallocation.
resource file is used to keep track of the resources used in the application. For resource file root is the project folder. Lets say we have kept new.png, cut.png and close.png int the images folder under project folder. We will add these to qt resource file. resource file’s file extension is qrc.
voidMyWindow::setupActions(){ actionNew = newQAction(tr("New"), this); actionNew->setShortcut(tr("Ctrl+N")); actionNew->setStatusTip(tr("Open a new document"));
Make a custom class inherited from QThread. Override Thread::run() method which will do the heavy works. Each thread is started with Thread::start() method.
voidMyThread::run(){ for(int i = 0; i <= 100; i++){ qDebug() << this->name << ":" << i; } }
Serial Ports in QT
QSerialPortInfo
QList<QSerialPortInfo> QSerialPortInfo::availablePorts() - availablePorst() static function returns a list of available devices. Available devices are returned as QSerialPortInfo object
Functions:
QString portName() - Return device port name. E.g ttyACM0, ttyUSB0 QString systemLocation() - Returns port path / location. E.g /dev/ttyACM0 QString description - Returns device description. QString manufacturer - Returns device manufacturer. QString serialNumber() - Return device serial number. bool hasProductIdentifier() - True if the device has valid product identifier number. quint16 productIdentifier() - Returns product identifier number. bool hasVendorIdentifier() - Returns true if the device has valid product number. quint16 vendorIdentifier() - Returns vendor identifier number. bool isBusy() - returns True if the serial port is busy.
Individual character can be indexed from a string. Index can be negative. Negative index will return chars backword.
1 2 3 4 5 6
>>> printstr[0] H >>> printstr[-1] d >>> printstr[-2] l
Slicing
Extract a section of a string in one step. str[m:n] will produce ‘str[m]str[n-1]’. Default value of m is 0 and n is the length of the string.
1 2 3 4 5 6 7 8 9 10 11
>>> printstr[7:10] # Slice from 7 to 10(non-inclusive) 'Wor'
>>> str[:] # Slice from start to end */ 'Hello, World'
>>> str[:4] # Slice from start upto 4 'Hell'
>>> str[:-1] # Slice from start upto last item 'Hello, Worl'
General format of slicing is x[i:j:k]. Where k is the step size from i upto j. k can be negative, in that case slice will occur from i upto j in reverse order. Default value of k is 1.
1 2 3 4 5 6 7 8
>>> "12345678"[1:6:2] # From index 1 upto index 6 and step size 2 '246'
"hello"[::2] # Entire string, step size 2 'hlo'
"hello"[::-1] # Entire string. Step size 1. But as the step 'olleh'# size is negetive, slicing will be done in reverse order
Strings can be concatenated using + sign and repeated using * sign.
1 2 3 4 5 6
>>> foo = "I am little bunny foo foo" >>> bar = " and bar is with me" >>> foo + bar 'I am little bunny foo foo and bar is with me' >>> foo * 3 'I am little bunny foo fooI am little bunny foo fooI am little bunny foo foo'
Every operation we have performed on string can be performed other sequence objects like lists and tupples
Some methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14
>>> string = "foo bar" >>> string.find('o') 1 >>> string.replace('oo', 'uu') 'fuu bar' >>> string 'foo bar'# String itself unchanged as immutable >>> bands = "Warfaze, Black, Artcell, Bangla" >>> bands.split(',') # Split according to the argument and return as list ['Warfaze', ' Black', ' Artcell', ' Bangla'] string = "Hello, how are you\n\n\n" >>> string = string.rstrip() # Remove whitespaces from the rigth most side >>> string 'Hello, how are you'
ord() function returns ASCII value of a character.
1 2
>>> ord('A') 65
chr() function converts ASCII value to character.
1 2
>>> chr(65) 'A'
\0 or null terminator doesn’t end python strings
1 2 3 4 5 6 7
>>> s = 'A\0B\0C' >>> s 'A\x00B\x00C' >>> print s ABC >>> len(s) 5
Multiline strings can be specified using three “ or ‘.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
>>> str = """ ... When this form is used ... all the lines are concatenated togather ... and end-of-the line characters are added ... where line breaks appear ... """ >>> str '\nWhen this form is used\nall the lines are concatenated togather\n\tand end-of-the line characters are added\nwhere line breaks appear\n' >>> printstr
When this form is used all the lines are concatenated togather and end-of-the line characters are added where line breaks appear
Lists
List object is sequence object. They are mutable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
>>> list = [1, 2.3, 'foo'] # Creating list object >>> len(list) # Finding length 3 >>> list[0] # Can be indexed 1 >>> list[-1] 'foo' >>> list[1:3] # Slicing [2.3, 'foo'] >>> list + ['bar'] # Concatenation [1, 2.3, 'foo', 'bar'] >>> list = list + ['bar'] # Mutability >>> list [1, 2.3, 'foo', 'bar']
Type specific operations
Can hold different types of object
No fixed size
Mutable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
>>> list = [1, 'foo'] >>> list.append('bar') # Add an item at the end of the list >>> list [1, 'foo', 'bar'] >>> list.insert(1, 'baz') # Insert an item at a specific index >>> list [1, 'baz', 'foo', 'bar'] >>> list.pop(1) # return and remove an item from a specific 'baz'# index >>> list [1, 'foo', 'bar'] >>> list.remove('bar') # remove first occurance of an item found >>> list# in the list [1, 'foo']
As list is a mutable object there are methods that can change a list object in place.
1 2 3 4 5 6 7
>>> list = ['heaven', 'and', 'hell'] >>> list.sort() # Sort List >>> list ['and', 'heaven', 'hell'] >>> list.reverse() # Reverse sort List >>> list ['hell', 'heaven', 'and']
List comprehension is a way to build a new list running an expression on each item in a sequence, once at a time.
1 2 3 4 5 6 7 8 9
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> col2 = [row[1] for row in matrix] >>> col2 [2, 5, 8] >>> list = [var for var inrange(0, 11)] >>> list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [num for num inrange(0, 11) if num % 3 == 0] # Filtering [0, 3, 6, 9]
Dictionary
Dictionaries are used to store value in a key value pair.
Mutable
Values are stored in a key value pair
Stores any type of objects
Can be nested
1 2 3 4 5 6 7 8
band = {'name':'Bangla', 'albums':2} # Creation >>> band {'albums': 2, 'name': 'Bangla'} >>> band['name'] # Indexing by key 'Bangla' >>> band['started'] = 1999# Mutable >>> band {'started': 1999, 'albums': 2, 'name': 'Bangla'}
Type Specific Methods:
1 2 3 4 5
>>> dic = {'c':1, 'a':2, 'b':3} >>> dic {'a': 2, 'c': 1, 'b': 3} >>> dic.keys() # Returns List of the keys ['a', 'c', 'b']
Iterating over a Dictionary:
1 2 3 4 5 6 7 8 9
>>> dic = {'c':1, 'a':2, 'b':3} >>> dic {'a': 2, 'c': 1, 'b': 3} >>> for key in dic.keys(): ... print"key: %s\tValue: %s" % (key, dic[key]) ... key: a Value: 2 key: c Value: 1 key: b Value: 3
Tuples
Python tuples are list like sequence object. But they are immutable.
1 2 3 4 5 6 7 8 9 10 11
>>> T = (1, 2, 3, 4) >>> T (1, 2, 3, 4) >>> T[0] 1 >>> len(T) 4 >>> T[1] = 10 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple'object does not support item assignment
Sets
Collection of unique elements. Supports usual mathematical set operations.
1 2 3 4 5 6 7 8 9 10 11 12
>>> x = set('hello') >>> x set(['h', 'e', 'l', 'o']) >>> y = set(['w', 'o', 'r', 'l', 'd']) >>> y set(['d', 'r', 'o', 'w', 'l']) >>> x & y set(['l', 'o']) >>> x | y set(['e', 'd', 'h', 'l', 'o', 'r', 'w']) >>> x - y set(['h', 'e'])
Python Data Types In Details
Numbers
Numeric Display Formats
repr() display numbers as in code. str() Convert numbers into string. oct() converts decimal into octal hex() converts decimal into hexadecimal int(string, base) - converts strings into numbers. float() - Coverts strings into floating point number. bin() - Converts integer to binary
Block of strings: “””string block”””, ‘’’String Block’’’
Raw strings: r’\thello, world\n’. Take each characters leterally, omits escape sequences. e.g. r”C:\new\values”. But raw string won’t work for a string ended with backslash. r”…"; This is invalid.
Byte Strings: b’spam’ (Python 3)
Unicode strings: u’\u0986\u09AE\u09BE\u09B0’ (in 2.6 only)
In python 3 there are three string types. str is used for unicode text(ASCII and others). bytes is used for bynary data. bytearray is mutable variant of bytes.
>>> print'he said, "hello"'# Python 2.6 he said, "hello"
>>> print ('he said, "hello"') # Have to use brackets in python 3 he said, "hello"
>>> print"Robin's book" Robin's book >>> print """Once upon a time ... there was a man ... one day""" Once upon a time there was a man one day >>> print r'\thello, world\n' \thello, world\n >>> print u'\u0986\u09AE\u09BE\u09B0' আমার
Character Code Conversions
ord('char') convert char into ints ASCII value.
chr(value) convert from ASCII to character.
eval(str) - convert a string into python executable code.
1 2 3 4 5 6 7 8 9
>>> list = [1, 2, 3]
>>> str = '%s' % list# List is converted into a string
>>> str '[1, 2, 3]'
>>> eval(str) # String is converted back to list [1, 2, 3]
>>> list = [1, 'foo', 2, 'bar'] >>> list[3] = 'baz'# Changing in place using indexing >>> list [1, 'foo', 2, 'baz'] >>> list[1:3] = [2, 3] # Changing in place using slicing >>> list [1, 2, 3, 'baz'] >>> >>> dellist[0] # Delete one item from list >>> list [2, 3, 'baz'] >>> >>> dellist[1:] # Delete a section from list >>> list [2] >>> >>> list = [1, 2, 3, 4] >>> list[1:3] = [] # Another way of deleting a section >>> list [1, 4]
List Methods
list.append(item) - To append item at the end of the list.
list.extend(argList) - Append multiple items at the end of the list at once.
list.insert(index, item) - To insert item at index index of the list.
list.pop([index]) - Remove item from list at index index. If index isn’t specified default is the last item.
list.remove(item) - Remove first occurence of the item from the list.
file.readlines() - Returns a list of all lines from a file.
1 2 3 4 5 6
>>> fin = open('myfile') >>> fin.read() 'hello, world!\nI am foo.\nI am bar.' >>> fin.seek(0) >>> fin.readlines() ['hello, world!\n', 'I am foo.\n', 'I am bar.']
file.truncate(bytes) - File will be truncated to specified bytes. All previous data will be lost. Specified byte space will be zero filled.
Some important file operations
Check if a file/path exists
1 2 3
from os.path import exists
print(exists("/home/username/myfile.txt"))
Python Pickles
Tool to store python object in a file directly with no to-or-from string conversion.
>>> spam = 'hello, world'# Basic form >>> spam 'hello, world' >>> spam, ham = 'hello', 'world'# Tupple assignment(Positional) >>> spam, ham ('hello', 'world') >>> [spam, ham] = ['hello', 'world'] # List assignment(Positional) >>> spam, ham ('hello', 'world') >>> >>> a, b, c, d = 'spam'# Sequence assignment >>> a, b, c, d ('s', 'p', 'a', 'm') >>> >>> a, *b = 'spam'# Extended sequence unpacking >>> a 's' >>> b ['p', 'a', 'm'] >>> spam = ham = 'launch'# Multiple assignment >>> spam, ham ('launch', 'launch')
In case of multiple assignment all the variables point to the same object(same piece of memory)
1 2 3 4 5 6 7 8 9 10
>>> spam = ham = [1, 2, 3] # spam & ham are pointing to same object >>> spam [1, 2, 3] >>> ham [1, 2, 3] >>> spam[1] = 4# spam changed >>> spam [1, 4, 3] >>> ham # ham changed too as they are pointing to same object [1, 4, 3]
Concatenation VS In-place assignment:
In case of concatenation must create a new object, copy it in the object on the left, then copy it on the right. So it is slower. On the other hand in case of in-place assignment new item is just added at the end of the memory block.
1 2 3 4 5 6 7 8
>>> L = [1, 2] >>> L = L + [3, 4] # Concatenation: Slower >>> L [1, 2, 3, 4] >>> L.extend([5, 6]) # In-place assignment: Faster >>> L [1, 2, 3, 4, 5, 6] >>> L += [7, 8] # Python automaticaly use the faster method
>>> L = [1, 2] >>> M = L # M & L are shared object >>> M [1, 2] >>> L [1, 2] >>> >>> L = L + [3] # Concatenation >>> L [1, 2, 3] # L changed >>> M [1, 2] # But M isn't as concatenation creates new object >>> >>> M = L # M is pointing to L >>> M [1, 2, 3] >>> >>> L += [4] # In-place assignment >>> L [1, 2, 3, 4] # L is changed >>> M [1, 2, 3, 4] # M is changed too as augmented assignmets are in-place
Python variable naming convension
Names that begin with single underscore(_X) are not imported by from module import * statement
Names that begin with two leading and trailing underscore(__X__) are system defined and have special meaning to interpreter.
Names that begin with two leading underscore(__X) are localized to enclosing classes
Class names usually starts with uppercase letters.
if X and Y: # True if X and Y both True # Do something
Return Value: and didn’t return True or False. Returns first object which is false(zero or empty) from left to right. If expression is true returns right most object.
1 2 3 4 5 6
>>> 1and2 2 >>> [] and2 [] >>> 1and [] and2 []
or operator:
1 2
if X or Y: # True if X or Y is True # Do something
Return value: or didn’t return True or False. Returns first object which is true (non-zero / non-empty) from left to right.
while <test1>: <statement1> if <test2>: break # Exit loop now. Skip else part if <test3>: continue # Continue to test1
else: # Execute only if loop is exited without break <statement2>
pass: Do nothing. Just an empty statement place holder.
Python For Loop
For loop’s general format
1 2 3 4 5 6
for <target> in <object>/<sequence>: <statements> if <test>: break if <test>: continue else: <statements>
Any sequence works in for loop
1 2 3 4 5 6 7 8 9 10 11 12 13
>>> for i in [1, 2, 3]: ... print(i, end = '\t') ... else: ... print("") ... 123 >>> >>> for ch in"abc": ... print(ch, end = '\t') ... else: ... print("") ... a b c
Tupple assignment / Sequence Unpacking in for loop
1 2 3 4 5
>>> for (a, b) in [(1, 2), (3, 4)]: ... print("%d, %d" % (a, b)) ... 1, 2 3, 4
Some sequence unpacking example
1 2 3 4 5 6 7 8 9 10
>>> for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]: ... print(a, b, c) ... 123 456 >>> for ((x, y), z) in [((1, 2), 3), ("XY", 'Z')]: ... print(x, y, z) ... 123 X Y Z
Using for loop for iterating through dictionary
1 2 3 4 5 6 7 8 9 10 11 12 13 14
>>> dict = {1: 'a', 2: 'b', 3: 'c'} >>> for key indict.keys(): ... print("Key: %d\tValue: %c" % (key, dict[key])) ... Key: 1 Value: a Key: 2 Value: b Key: 3 Value: c >>> >>> for key, value inlist(dict.items()): ... print(key, value) ... 1 a 2 b 3 c
Range
range(FROM, UPTO, STEP) - Create a list of numbers FROM to UPTO in python 2.0. In python 3.0 it’s an iterator.
>>> X = "abcdefgh" >>> for i inrange(0, len(X), 2): ... print(X[i], end = '') ... else: ... print() ... aceg
# Alternative good solution is with sclicing
>>> X 'abcdefgh' >>> for ch in X[::2]: ... print(ch, end = '') ... else: ... print() ... aceg
Zip
zip(seq1, seq2, ...) takes one or more sequence as argument and creates a list of Tuples from them. zip creates an iterable object. Which can be converted to list or other sequence object.
1 2 3 4 5
>>> l = [1, 2, 3] >>> m = [4, 5, 6] >>> n = [7, 8, 9] >>> list(zip(l, m, n)) [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
zip() truncates if the size of the sequences mismatches.
>>> S = "hello" >>> index = 0 >>> >>> for value in S: ... print(index, value) ... index += 1 ... 0 h 1 e 2 l 3 l 4 o
# enumerate way
>>> S = "hello" >>> >>> for index, value inenumerate(S): ... print(index, value) ... 0 h 1 e 2 l 3 l 4 o
Iterators & Comprehension
An object is called iterable if it’s a sequence or an object that produce one result at a time. Any object that supports iteration has __next__() method. It raises StopIteration exception at the end of the series of results.
File Iterator
1 2 3
# Manual method
List Comprehension
General Structure:[expression for target1 in iterable1 if condition1 for target2 in iterable 2 if condition2 ...]
List Comprehension:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
>>> L = [1, 2, 3] >>> L = [x ** 2for x in L] >>> L [1, 4, 9] >>>
Docstrings are used for documenting python module, class, class methods, functions etc. Docstrings are placed as the first statement of the module, class, methods, functions.
A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.
All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have docstrings. A package may be documented in the module docstring of the __init__.py file in the package directory.
Example:
1 2 3 4 5 6 7 8 9 10
def add(x, y): """Add two numbers
Args: x : first number y : second number Returns: addition of the two number """ return x + y
PyDoc and help()
Python help() function gives the documentation of an object that are created by docstrings
Functions
Example:
1 2 3 4 5 6 7
>>> defsum(x, y): ... return x + y ... >>> sum(10, 5) 15 >>> sum(10, 10) 20
>>> x = 10 >>> >>> deffunc1(): ... x = 20 ... deffunc2(): ... print(x) # func2() knows about x # as enclosing function ... func2() ... >>> >>> func1() 20# 20 not 10 because LEGB rule
# However this code doesn't work # in previous versions. As searches only local scope # before global scope. Work around:
# Supposed to make a list of functions # With different values of i.
>>> defactionMaker(): ... acts = [] ... for i inrange(0, 5): ... acts.append(lambda x: i ** x) ... return acts ... >>> >>> f = actionMaker() >>> >>> f[0](2) # Should print 0 16# prints 16 instead >>> >>> f[1](2) # Should print 1 16# prints 16 insead
# This doesn't work because eclosing namespace is looked up when # the nested function is called. so i is looked up when # f[]() is called. But after actionMaker() call i is 4 # Work around: ctionMaker(): ... acts = [] ... for i inrange(0, 5): ... acts.append(lambda x, i = i: i ** x) ... return acts ... >>> >>> f = actionMaker() >>> f[0](2) 0 >>> f[1](2) 1 >>> f[2](2) 4
Forward Reference
1 2 3 4 5 6 7 8 9 10
>>> deffunc1(): ... x = 10 ... func2(x) # OK as long as def for func2() is # executed before func1() is called ... >>> deffunc2(x): ... print(x) ... >>> func1() 10
Factory Functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
>>> defmaker(x): ... defaction(y): ... return x ** y ... return action ... >>> >>> f = maker(2) >>> f <function maker.<locals>.action at 0x7f69aa6e99d8> >>> print(f(5)) # Nested function is remembering 2 32 >>> print(f(6)) 64 >>> >>> g = maker(3) # Changing state >>> >>> print(g(5)) # Each function got its own state. g got its own state 243
>>> deffunc(**dargs): # Dictionary based. Can take variable numer of arguments ... print(dargs) ... >>> func(a = 1, b = 2) # But argumets have to be passed in key = value # pair {'b': 2, 'a': 1} >>> func(a = 1, b = 2, c = 3) {'c': 3, 'b': 2, 'a': 1}
# in function defination every argumet afte * are keyword only # argumets. They have to be passed using key = value format in the # function
>>> deffunc(a, *b, c): # c is keyword only argumet ... print(a, b, c) ... >>> func(1, 2, c = 3) # c is passed using key = value format 1 (2,) 3 >>> func(1, 2, 3) # Raise error as c is keyword only Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: func() missing 1 required keyword-only argument: 'c' >>> >>> deffunc(a, *, c): # without variable argumet, only two argumet ... print(a, c) ... >>> func(1, c = 3) 13 >>> func(1, 2, c = 3) # Raise error as 3 argumet passed instead of two Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: func() takes 1 positional argument but 2 positional arguments (and1 keyword-only argument) were given
>>> defgen(n): ... for i inrange(n): ... x = yield i ... print(x) ... >>> >>> g = gen(10) >>> next(g) 0 >>> next(g) None 1 >>> next(g) None 2 >>> next(g) None 3 >>> g.send(80) 80 4
1 2 3 4 5 6 7
>>> G = (x ** 2for x inrange(10)) >>> G.__next__() 0 >>> G.__next__() 1 >>> G.__next__() 4
Both generator function and expression are their own iterators. So they can have only one active iterator. I multiple iterator is assign, they all will point to same iteration point.
1 2 3 4 5 6 7 8 9 10 11
>>> G = (x ** 2for x inrange(10)) >>> G isiter(G) True >>> it1 = iter(G) >>> next(it1) 0 >>> next(it1) 1 >>> it2 = iter(G) >>> next(it2) 4
Decorators
Decorators are used to change any callable objects behaviour like function or class etc. There are two type of decorators. Function decorator and class decorator. One is work for function and another is work for classes. But both work in same way.
Consider this senario where a function func_decorator is changing other functions behaviour. This function takes other functions as argument and change is behaviour using a wrapper function. Then this wrapper function is assigned to the original function to change original functions behaviour.
classPoint: """ Point class - Creates a point in 2D space """
def__init__(self, x = 0, y = 0): """ Initiate a point object with x and y Args: x : x coordinate y : y coordinate Returns: None """ self.x = x self.y = y
# Getter for x @property defx(self): """ Returns value of x coordinate""" returnself.__x
# Setter for x @x.setter defx(self, x): """ Set the value of x coordinate""" self.__x = x
# Getter for y @property defy(self): """Returns value of y coordinate""" returnself.__y
# Setter for y @y.setter defy(self, y): """ Set the value of y coordinate """ self.__y = y
Name | 0 | Sex Bob | 43 | Male | Married? 1 Alice | 19 | Female | Married? 0
Operator Overloading and Magic Methods
There are special methods in python with double underscore at the begining and end like __add__ which can be used for operator overloading. Following example shows overloading __str__ method, which will be called when printing the object or str(object):
classMoney(object): """ This class represents money """ def__init__(self, value, unit = "USD", rate = 1): """ Initialize Money object Args: value : Money value unit : Unit of the money. e.g: USD, BDT rate : Exchange rate in USD Returns: None """ self.value = value self.unit = unit self.rate = rate
classEURO(Money): "This class represents Euro" def__init__(self, value, rate = 1.17): super().__init__(value, "EURO", rate) def__add__(self, other): """ overloaded __add__ method for EURO convert into dollar then add them returns the result in EURO """
55 BDT 12 BDT Traceback (most recent call last): File "./radd.py", line 19, in <module> print(3 + BDT(13)) TypeError: unsupported operand type(s) for +: 'int' and 'BDT'
This problem can be solved using reverse method. Python first search the overloaded method within the class, then the corresponding reverse method in the class. Then search the method in the parent class.
details of an object’s methods or attributes can be found using help() function.
>>> help(s.join)
Help on built-in function join:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
raw() and cbreak() - Normally the terminal driver buffers the characters a user types until a new line or carriage return is encountered. But most programs require that the characters be available as soon as the user types them. The above two functions are used to disable line buffering. The difference between these two functions is in the way control characters like suspend (CTRL-Z), interrupt and quit (CTRL-C) are passed to the program. In the raw() mode these characters are directly passed to the program without generating a signal. In the cbreak() mode these control characters are interpreted as any other character by the terminal driver.
echo() and noecho() - if noecho() is used key press will not echoed in the screen. other do the oposite.
keypad(stdscr, TRUE) - To get special inputs like F1, F2, Arrow keys etc.
Input / Output Functions
For each input/output functions there are four types of function.
Normal : printw(string) - print in the current position of the cursor in the standard screen(stdscr).
w less mv type: mvprintw(y, x, string) - move cursor to x, y then print in that position in the stdscr.
w type : wprintw(window, string) - print string in the current cursor position of the specified window.
w ed mv type : mvwprintw(window, y, x, string) - move to x, y and then print string in the specified window.
Output Functions
printw(string) - print string.
addch(ch, attributes) - print single character.
addstr(string) - print string.
NB: Each function has corresponding mv, w, mvw functions.
Input Functions
ch = getch() - to get a character from keyboard.
scanw() - scanf() like function.
getstr(str) - to get a string.
NB: Each function has corresponding mv, w, mvw functions.
Attributes
Attributes are used to set different text properties. Like Bold, Underlined, Italic etc.
attron(attribute1 | attrubute2 | ...) - To set some attribute on.
attroff(attr1 | attr2 | ...) - to set some attribute off.
attrset(attr1 | attr2 | ...) - Remove any prevoius attributes and set specified attributes.
Here is a list of some attributes:
Attribute
Effect
A_NORMAL
Normal Output
A_STANDOUT
Best highlighting mode of the terminal
A_UNDERLINE
Underlined
A_REVERSE
Reverse video
A_BLINK
Blinking
A_DIM
Half bright
A_BOLD
Extra bright or bold
A_PROTECT
Protected mode
A_INVIS
Invisible or blank mode
A_ALTCHARSET
Alternate character set
A_CHARTEXT
Bit-mask to extract a character
COLOR_PAIR(n)
Color-pair number n
NB: There is also corresponding w functions like wattron() which work on specific window.
chgat(nChar, attribute, color_pair_token, null) - This function set an attribute on texts without changing cursor position. nChar is the number of char on which attribute will be set. Negative nChar means end of the line. color_pair_token is for color pair. last is always null.
mvchgat(y, x, nChar, attribute, color_pair_token, null) - chgat() from x, y position.
Managing Windows
WINDOW *newwin(height, width, starty, startx) - To create a new window. It takes height and width of the window as argument. Also takes x, y position of the window. Returns a WINDOW pointer.
delwin(WINDOW *win) - To remove a window.
box(window, vchar, hchar) - vchar & hchar is ther char which will be used to draw boxes vertical and horizontal lines.
wborder(window, ls, rs, ts, bt, tl, tr, bl, br) - 2 - 8 arguments are character for drawing ls(left side), rs(right side) of the box.
Using imageMagick. Image format is guessed from the extension. You can also specify new image height and width.
1
$ convert FROM_IMG TO_IMAGE
Using inkscape. Gives better result than imageMagic for SVG image formats
1
$ inkscape -z -e TO_IMAGE FROM_IMAGE
Taking Screenshots
Using imagemagick. Issuing this command will change the cusrsor to select a rectagular area. If clicked rather than selecting area entire active window will be captured. Image format will be guessed from the extension provided with the image name.