This commit is contained in:
Artur Gurgul 2025-08-03 16:27:25 +02:00
commit acc61e858b
18 changed files with 5068 additions and 0 deletions

7
.sajt/config.yaml Normal file
View file

@ -0,0 +1,7 @@
site:
title: Artur Gurgul - {{article.title}}
remote:
type: ssh
user: debian
host: artur.gurgul.pro
path: /var/www/artur.gurgul.pro

126
go/notes.md Normal file
View file

@ -0,0 +1,126 @@
---
layout: default
title: Golang notes
categories: programming
---
```go
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
```
```go
type Base struct {
ID int
}
type User struct {
Base
Name string
}
u := User{Base: Base{ID: 1}, Name: "John"}
fmt.Println(u.ID, u.Name)
```
```go
ch := make(chan int)
go func() {
ch <- 42
}()
fmt.Println(<-ch)
```
Custom String Representations:
• Implement the Stringer interface for custom string representations of your types
```go
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s is %d years old", p.Name, p.Age)
}
p := Person{Name: "Alice", Age: 30}
fmt.Println(p)
```
Use init Function for Initialization:
• The init function is called before the main function and is useful for setup tasks.
```go
var config Config
func init() {
config = loadConfig()
}
func main() {
fmt.Println(config)
}
```
```go
func add(a, b int) int {
return a + b
}
func TestAdd(t *testing.T) {
result := add(2, 3)
if result != 5 {
t.Errorf("expected 5, got %d", result)
}
}
```
Use context for Cancellation and Timeouts:
• Use the context package to handle cancellation and timeouts in concurrent operations.
```go
func doWork(ctx context.Context) {
select {
case <-time.After(2 * time.Second):
fmt.Println("Work done")
case <-ctx.Done():
fmt.Println("Canceled")
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
go doWork(ctx)
time.Sleep(2 * time.Second)
}
```
```go
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
func (d Weekday) String() string {
return [...]string{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}[d]
}
fmt.Println(Monday) // Output: Monday
```

28
index.md Normal file
View file

@ -0,0 +1,28 @@
---
layout: default
hidden: true
---
## Welcome to my website!
This site was generated using **`sajt`**, a project Im currently developing and looking for contributors to help improve.
- **Sajt**: [https://github.com/artur-gurgul-pro/sajt](https://github.com/artur-gurgul-pro/sajt)
- **This website's source**: [https://github.com/artur-gurgul-pro/notes](https://github.com/artur-gurgul-pro/notes)
### Currently Supported
- Pug
- Markdown
- HTML
### Experimental Support
- YAML
### Planned Features
- Audio and video file support
The idea behind **sajt** is simple: turn your notes and content into a website with zero hassle. Just drop your files into a folder, run a command, and youve got a website ready to be uploaded to your hosting provider.
Feel free to share ideas, report bugs, or make suggestions by opening an issue:
[https://github.com/artur-gurgul-pro/notes/issues](https://github.com/artur-gurgul-pro/notes/issues)

View file

@ -0,0 +1,658 @@
---
layout: default
title: iOS Architecture Patterns
categories: swift
---
### Remove story board dependency
1. Remove `Main.storyboard` file
1. Remove storyboard reference from `Info.plist` &rarr; In Scene Configuration find `Storyboard Name` and delete it
1. Go to build settings and remove `UIKit MainStoryboard File Base Name` field
1. Create a window in Scene Delegate
```swift
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: scene)
window.rootViewController = ViewController()
window.makeKeyAndVisible()
self.window = window
}
```
## Dependency injection
<!-- https://www.swiftbysundell.com/tips/testing-code-that-uses-static-apis/ -->
[Explanation of the code under this link](https://www.avanderlee.com/swift/dependency-injection/)
```swift
public protocol InjectionKey {
associatedtype Value
static var currentValue: Self.Value { get set }
}
```
```swift
struct InjectedValues {
private static var current = InjectedValues()
static subscript<K>(key: K.Type) -> K.Value where K : InjectionKey {
get { key.currentValue }
set { key.currentValue = newValue }
}
static subscript<T>(_ keyPath: WritableKeyPath<InjectedValues, T>) -> T {
get { current[keyPath: keyPath] }
set { current[keyPath: keyPath] = newValue }
}
}
```
```swift
@propertyWrapper
struct Injected<T> {
private let keyPath: WritableKeyPath<InjectedValues, T>
var wrappedValue: T {
get { InjectedValues[keyPath] }
set { InjectedValues[keyPath] = newValue }
}
init(_ keyPath: WritableKeyPath<InjectedValues, T>) {
self.keyPath = keyPath
}
}
```
#### Define dependency
```swift
private struct UsersRepositoryKey: InjectionKey {
static var currentValue: AnyUsersRepository = UsersRepository()
}
extension InjectedValues {
var usersRepository: AnyUsersRepository {
get { Self[UsersRepositoryKey.self] }
set { Self[UsersRepositoryKey.self] = newValue }
}
}
protocol AnyUsersRepository {
func getUsers(_ result: @escaping (Result<[User], Error>)->Void)
}
class UsersRepository: AnyUsersRepository {
func getUsers(_ result: @escaping (Result<[User], Error>)->Void) {
<#Implementation#>
}
}
```
```swift
@Injected(\.usersRepository) var usersRepository: AnyUsersRepository
```
```swift
InjectedValues[\.usersRepository] = MockedUsersRepository()
```
## Model-View-Controller
#### Clasic version
- `View` and `Model` are linked together, so reusability is reduced.
- Note: Views in iOS apps are quite often reusable.
<p>
{% svg ../svgs/classic-mvc.svg class="center-image" %}
</p>
#### Apple version
<p>
{% svg ../svgs/apple-mvc.svg class="center-image" %}
</p>
**Model** responsibilities:
- Business logic
- Accessing and manipulating data
- Persistence
- Communication/Networking
- Parsing
- Extensions and helper classes
- Communication with models
Note: The `Model` must not communicate directly with the `View`. The `Controller` is the link between those
**View** responsibilities:
- Animations, drawings (`UIView`, `CoreAnimation`, `CoreGraphics`)
- Show data that controller sends
- Might receive user input
**Controller** responsibilities:
- Exchange data between `View` and `Model`
- Receive user actions and interruptions or signals from the outside the app
- Handles the view life cycle
#### Advantages
- Simple and usually less code
- Fast development for simple apps
#### Disadvantages
- Controllers coupled views
- Massive `ViewController`s
#### Communication between components
- [Delegation](https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/TargetAction.html) pattern
- [Target-Action](https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/TargetAction.html) pattern
- [Observer](https://developer.apple.com/documentation/foundation/nsnotificationcenter) pattern with `NSNotificationCenter`
- [Observer](https://developer.apple.com/documentation/swift/using-key-value-observing-in-swift) pattern with `KVO`
## Model-View-Presenter
In this design pattern View is implemented with classes `UIView` and `UIViewController`. The `UIViewController` has less responsibilities which are limited to:
- Routing/Coordination
- Navigation
- Passing informations via a delegation pattern
#### View
```swift
class ExampleController: UIViewController {
private let exampleView = ExampleView()
override func loadView() {
super.loadView()
setup()
}
private func setup() {
let presenter = ExamplePresenter(exampleView)
exampleView.presenter = presenter
exampleView.setupView()
self.view = exampleView
}
}
```
#### Presenter
```swift
protocol ExampleViewDelegate {
func updateView()
}
class ExamplePresenter {
private weak var exampleView: ExampleViewDelegate?
init(_ exampleView: ExampleViewDelegate) {
self.exampleView = exampleView
}
}
```
#### Advantages
- Easier to test business logic
- Better separation of responsibilities
#### Disadvantages
- Usually not a better choice for smaller projects
- Presenters might become massive
- Controllers still handle navigation. Possible solutions &rarr; extend the pattern with Router or Coordinator.
#### Common layers
- Data access layer: `CRUD` operations facilitated with `CoreData` `Realm` etc.
- Services: Classes that interacts with database entities, like retrieve data, transform them into objects.
- Extensions/utils
## Model-View-ViewModel
`ViewModel` has no references to the view.
<p>
{% svg ../svgs/mvvm.svg class="center-image" %}
</p>
Binding is done using: `Combine Framework`, `RxSwift`, `Bond` or `KVO` or using delegation pattern
* **`Model`** does same things as in `MVP` and `MVC`.
* **`View`** also is similar, but binds with `ViewModel`
* **`ViewModel`** keeps updated state of the view, and process data for i
#### Advantages
- Better reparation of responsibilities
- Better testability, without needing to take into account the views
#### Disadvantages
- Might be slower and introduce dependency on external libraries
- Harder to learn and can become complex
#### **Extension with Coordinator MVVM-C**
Role of `Coordinator` is to manage navigation flow.
```swift
protocol Coordinator {
var navigationController: UINavigationController { get set }
func start()
}
```
and an example implementation
```swift
class ExampleCoordinator: Coordinator {
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = UINavigationController
}
func start() {
let viewModel = ExampleViewModel(someService: SomeService(),
coordinator: self)
navigationController.pushViewController(ExampleController(viewModel),
animated: true)
}
func showList(_ list: ExampleListModel) {
let listCoordinator = ListCoordinator(navigationController: navigationController
list: list)
listCoordinator.start()
}
}
```
In the book I am reading the author created an `ExampleCoordinatorProtocol` with a `func showList(_ list: ExampleListModel)` where the `ExampleCoordinator` implemented it. I think it does not make any sense, however if we might want to inject the coordinator then we might want to relay on an abstraction.
```swift
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: scene)
let navigationController = UINavigationController()
exampleCoordinator = ExampleCoordinator(navigationController: navigationController)
exampleCoordinator?.start()
window.rootViewController = navigationController
window.makeKeyAndVisible()
self.window = window
}
```
## VIPER
<p>
{% svg ../svgs/viper-ownership.svg class="center-image" %}
</p>
#### View
It includes `UIViewController`
- Made only to preserve elements like Buttons Labels
- It sends informations to presenters, and receive messages what to show and knows how
#### Interactor
- Receives informations form databases, servers etc.
- The book says that the Interactor receive actions from presenter, and returns the result via Delegation Pattern.
- The interactor never sends entities to the Presenter
#### Presenter
- Is in the centre and serves as a link
- Process events from the view and requests data from the Interctor. It receives that as primitives, never Entities.
- it handles navigation to the other screens using the Router
#### Entity
- Simple models usually data structures
- They can only be used by the Interactor
#### Router
- Creates screens
- Handles navigation, but itself does not know where to go to.
- _The book says it is the owner of the `UINavigationController` and UIViewController, but it is contrary to other parts of the book, so I do not know_
- Similar to `Coordinator` form MVVM-C
<!--
https://github.com/ochococo/Design-Patterns-In-Swift
https://nalexn.github.io/clean-architecture-swiftui/
https://medium.com/@vladislavshkodich/architectures-comparing-for-swiftui-6351f1fb3605
-->
**`Entity.swift`**
```swift
struct User: Codable {
let name: String
}
```
**`Interactor.swift`**
```swift
enum FetchError: Error {
case failed
}
protocol AnyInteractor {
var presenter: AnyPresenter? { get set }
func getUsers()
}
class UserInteractor: AnyInteractor {
@Injected(\.usersRepository) var usersRepository: AnyUsersRepository
var presenter: AnyPresenter?
func getUsers() {
usersRepository.getUsers { [weak self] in self?.presenter?.interactorDidFetchUsers(with: $0) }
}
}
```
**`Presenter.swift`**
```swift
protocol AnyPresenter {
var router: AnyRouter? { get set }
var interactor: AnyInteractor? { get set }
var view: AnyView? { get set }
func interactorDidFetchUsers(with result: Result<[User], Error>)
}
class UserPresenter: AnyPresenter {
func interactorDidFetchUsers(with result: Result<[User], Error>) {
switch result {
case let .success(users):
view?.update(with: users)
case let .failure(error):
view?.update(with: error.localizedDescription)
}
}
var router: AnyRouter?
var interactor: AnyInteractor? {
didSet {
interactor?.getUsers()
}
}
var view: AnyView?
}
```
**`Router.swift`**
```swift
typealias EntryPoint = AnyView & UIViewController
protocol AnyRouter {
var entry: EntryPoint? { get }
static func start() -> AnyRouter
}
class UserRouter: AnyRouter {
var entry: EntryPoint?
static func start() -> AnyRouter {
let router = UserRouter()
var view: AnyView = UserViewController()
var presenter: AnyPresenter = UserPresenter()
var interactor: AnyInteractor = UserInteractor()
view.presenter = presenter
interactor.presenter = presenter
presenter.router = router
presenter.view = view
presenter.interactor = interactor
router.entry = view as? EntryPoint
return router
}
}
//There are a few retain cycles with view, presenter, router and interactor. One option you can do is to make those protocols conforms to AnyObject, and mark these references as "weak":
//1. router's ref to presenter
//2. router's ref to view
//3. presenter's ref to view
//4. interactor's ref to presenter
```
**`View.swift`**
```swift
protocol AnyView {
var presenter: AnyPresenter? { get set }
func update(with users: [User])
func update(with error: String)
}
class UserViewController: UIViewController, AnyView {
var presenter: AnyPresenter?
private let tableView: UITableView = {
let tableView = UITableView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.isHidden = true
return tableView
}()
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = view.bounds
}
func update(with users: [User]) {
DispatchQueue.main.async {
self.users = users
self.tableView.reloadData()
self.tableView.isHidden = false
}
}
func update(with error: String) {
}
}
extension UserViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = users[indexPath.row].name
return cell
}
}
```
<!--
RIBs
https://github.com/uber/RIBs
https://medium.com/swlh/ios-architecture-exploring-ribs-3db765284fd8
https://github.com/uber/RIBs/wiki
-->
<!--
redux
https://medium.com/mackmobile/getting-started-with-redux-in-swift-54e00f323e2b
-->
<!--
# Factory
```swift
protocol ImageReader {
func getDecodeImage() -> DecodedImage
}
class DecodedImage {
private var image: String
init(image: String) {
self.image = image
}
var description: String {
"\(image): is decoded"
}
}
class GifReader: ImageReader {
private var decodedImage: DecodedImage
init(image: String) {
self.decodedImage = DecodedImage(image: image)
}
func getDecodeImage() -> DecodedImage {
decodedImage
}
}
class JpegReader: ImageReader {
private var decodedImage: DecodedImage
init(image: String) {
decodedImage = DecodedImage(image: image)
}
func getDecodeImage() -> DecodedImage {
decodedImage
}
}
func runFactoryExample() {
let reader: ImageReader
let format = "gif"
let image = "example image"
switch format {
case "gif":
reader = GifReader(image: image)
default:
reader = JpegReader(image: image)
}
let decodedImage = reader.getDecodeImage()
print(decodedImage.description)
}
```
```swift
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers: [(T) -> Void] = []
mutating func attach<O: Observer>(observer: O) where O.ValueType == T {
observers.append { observer.update(value: $0) }
}
func notyfi(value: T) {
for observer in observers {
observer(value)
}
}
}
class ConcreteObserver: Observer {
func update(value: String) {
print("received: \(value)")
}
}
func runObserverExample() {
var subject = Subject<String>()
let observer1 = ConcreteObserver()
subject.attach(observer: observer1)
let observer2 = ConcreteObserver()
subject.attach(observer: observer2)
subject.notyfi(value: "some string")
}
// Version with more modern syntax
/*
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers = Array<any Observer<T>>()
mutating func attach(observer: any Observer<T>) {
observers.append(observer)
}
func notify(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}
*/
```
-->

30
ios/modularization.md Normal file
View file

@ -0,0 +1,30 @@
---
layout: default
title: Modularization of an iOS app
categories: swift
---
### Creating shared product
1. add submodule to your product `git submodule add git@github.com:artur-gurgul-pro/sharepack.git Sharepack`
1. Extract shared code to multi-module package. See `Sharepack`
2. Add local package
TBD
Initialisation of a library
```bash
mkdir MyDeps && cd MyDeps
swift package init --type library
```
```bash
swift package generate-xcodeproj
```
```bash
xcodebuild -resolvePackageDependencies
```

571
ios/notes.md Normal file
View file

@ -0,0 +1,571 @@
---
layout: default
title: Swift - notes
categories: swift
---
#### Autoclosure
Lazy evaluation of the function's arguments. Instead of eager calculation of values, the clousure is passed, and executed only when needed.
```swift
func test(_ closure: @autoclosure() -> Bool) {
<#Code#>
}
test(8==9)
```
#### Destructuring Assignment
```swift
let (name, surname) = ("Artur", "Gurgul")
```
#### Checking if value is in range
```swift
let i = 101
if case 100...101 = i {
<#Code#>
}
if (100...101).contains(i) {
<#Code#>
}
```
#### Accessing tuple values
```swift
("value1", "value2").0
```
#### Pattern matching
```swift
enum Example {
case first(String)
case secund(String)
}
let example: Example = .first("test")
```
```swift
switch example {
case .first(let value), .secund(let value):
print(value)
}
if case let .first(value) = example {
print(value)
}
```
_print odd numbers_
```swift
for i in 1...100 where i%2 != 0 {
}
```
#### Blurable view in UIKit
```swift
extension Blurable where Self: UIView {
    func addBlur(_ alpha: CGFloat = 0.5) {
        let effect = UIBlurEffect(style: .prominent)
        let effectView = UIVisualEffectView(effect: effect)
        effectView.frame = self.bounds
        effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        effectView.alpha = alpha
        self.addSubview(effectView)
    }
}
```
```swift
extension BackgroundView: Blurable {}
```
## Difference between `@ObservedObject`, `@State`, and `@EnvironmentObject`
[https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference-between-observedobject-state-and-environmentobject](https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference-between-observedobject-state-and-environmentobject)
>- Use `@State` for simple properties that belong to a single view. They should usually be marked `private`.
>- Use `@ObservedObject` for complex properties that might belong to several views. Most times youre using a reference type you should be using `@ObservedObject` for it.
>- Use `@StateObject` once for each observable object you use, in whichever part of your code is responsible for creating it.
>- Use `@EnvironmentObject` for properties that were created elsewhere in the app, such as shared data.
### Cold vs hot observables
From: Anton Moiseev's Book [“Angular Development with Typescript, Second Edition.”](https://www.manning.com/books/angular-development-with-typescript-second-edition) :
> **Hot and cold observables**
>
> There are **two** types of **observables**: hot and cold. The main difference is that a **cold observable** **creates** a **data producer** for **each subscriber**, whereas a **hot observable creates** a **data producer first**, and **each subscriber** gets the **data** from **one producer**, **starting** from **the moment of** **subscription**.
>
> Lets compare watching a **movie** on **Netflix** to going into a **movie theater**. Think of yourself as an **observer**. Anyone who decides to watch Mission: Impossible on Netflix will get the entire movie, regardless of when they hit the play button. Netflix creates a new **producer** to stream a movie just for you. This is a **cold observable**.
>
> If you go to a movie theater and the showtime is 4 p.m., the producer is created at 4 p.m., and the streaming begins. If some people (**subscribers**) are late to the show, they miss the beginning of the movie and can only watch it starting from the moment of arrival. This is a **hot observable**.
>
> A **cold observable** starts producing data when some code invokes a **subscribe()** function on it. For example, your app may declare an observable providing a URL on the server to get certain products. The request will be made only when you subscribe to it. If another script makes the same request to the server, itll get the same set of data.
>
> A **hot observable** produces data even if no subscribers are interested in the data. For example, an accelerometer in your smartphone produces data about the position of your device, even if no app subscribes to this data. A server can produce the latest stock prices even if no user is interested in this stock.
# Interesting snippets
<!-- https://swiftbysundell.com/articles/swiftui-views-versus-modifiers/ -->
# View modifier
The notification we'll send when a shake gesture happens.
```swift
extension UIDevice {
static let deviceDidShakeNotification = Notification
.Name(rawValue: "deviceDidShakeNotification")
}
```
Override the default behavior of shake gestures to send our notification instead.
```swift
extension UIWindow {
open override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
NotificationCenter
.default
.post(name: UIDevice.deviceDidShakeNotification, object: nil)
}
}
}
```
A view modifier that detects shaking and calls a function of our choosing.
```swift
struct DeviceShakeViewModifier: ViewModifier {
let action: () -> Void
func body(content: Content) -> some View {
content
.onAppear()
.onReceive(NotificationCenter
.default
.publisher(for: UIDevice.deviceDidShakeNotification)) { _ in
action()
}
}
}
```
A View extension to make the modifier easier to use.
```swift
extension View {
func onShake(perform action: @escaping () -> Void) -> some View {
self.modifier(DeviceShakeViewModifier(action: action))
}
}
```
An example view that responds to being shaken
```swift
struct ContentView: View {
var body: some View {
Text("Shake me!")
.onShake {
print("Device shaken!")
}
}
}
```
# Swizzling
```swift
extension UIViewController {
@objc dynamic func newViewDidAppear(animated: Bool) {
viewDidAppear(animated)
print("View appeared")
}
}
private let swizzling: Void = {
let originalMethod = class_getInstanceMethod(UIViewController.self,
#selector(UIViewController.viewDidLoad))
let swizzledMethod = class_getInstanceMethod(UIViewController.self,
#selector(UIViewController.newViewDidAppear))
if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}()
```
# class vs static values
```swift
class Car {
static var start: Int {
return 100
}
class var stop: Int {
return 0
}
}
```
```swift
class Student: Person {
// Not allowed
// override static var start: Int {
// return 150
// }
override class var stop: Int {
return 5
}
}
```
# Always Publisher example
```swift
public struct Always<Output>: Publisher {
public typealias Failure = Never
public let output: Output
public init(_ output: Output) {
self.output = output
}
public func receive<S: Subscriber>(subscriber: S)
where S.Input == Output, S.Failure == Failure {
let subscription = Subscription(output: output,
subscriber: subscriber)
subscriber.receive(subscription: subscription)
}
}
```
```swift
private extension Always {
final class Subscription<S: Subscriber>
where S.Input == Output, S.Failure == Failure {
private let output: Output
private var subscriber: S?
init(output: Output, subscriber: S) {
self.output = output
self.subscriber = subscriber
}
}
}
```
```swift
extension Always.Subscription: Cancellable {
func cancel() {
subscriber = nil
}
}
```
```swift
extension Always.Subscription: Subscription {
func request(_ demand: Subscribers.Demand) {
var demand = demand
while let subscriber = subscriber, demand > 0 {
demand -= 1
demand += subscriber.receive(output)
}
}
}
```
# Buffered publisher
```swift
let publisher = PassthroughSubject<Int, Never>()
publisher.send(1)
let buffered = publisher.buffer(size: 4, prefetch: .keepFull, whenFull: .dropOldest)
```
# Combine publishers
```swift
let publisher1 = [1,2].publisher
let publisher2 = [3,4].publisher
```
Emits first and then second
```swift
let combinedPublisher = Publishers
.Concatenate(prefix: publisher1.eraseToAnyPublisher(),
suffix: publisher2.eraseToAnyPublisher())
```
Combine without ordering
```swift
let combinedPublisher = Publishers.Merge(publisher1.eraseToAnyPublisher(),
publisher2.eraseToAnyPublisher())
```
**_Other operators worth to look at_**
- `Zip` - pair the emitted object, like a zip in the jacket
- [`CombineLatest`](https://developer.apple.com/documentation/combine/publisher/combinelatest%28_:%29) - When `publisher1` and `publisher2` emitted some event then the latest values from each are taken and reemitted. From now on each change from either publisher is passed down.
#### Example of zip
```swift
let numbers = [1, 2, 3, 4].publisher
let twos = sequence(first: 2,
next: {_ in 2}).publisher
numbers
.zip(twos)
.map { pow(Decimal($0), $1) }
.sink(receiveValue: { p in
print(p)
}).store(in: &cancellables)
```
#### Cancelling a publisher
```swift
let timer = Timer
.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
```
```swift
var counter = 0
subscriber = timer
.map { _ in counter += 1 }
.sink { _ in
if counter >= 5 {
timer.upstream.connect().cancel()
}
}
```
It will work similar to this
```swift
subscriber = timer.prefix(5)
```
#### Assign
```swift
class Dog {
var name: String = ""
}
let dog = Dog()
let publisher = Just("Snow")
publisher.assign(to:/.name, on: dog)
```
```swift
class MyModel: ObservableObject {
@Published var lastUpdated: Date = Date()
init() {
Timer
.publish(every: 1.0, on: .main, in: .common)
.autoconnect()
.assign(to: &$lastUpdated)
}
}
```
```swift
class MyModel: ObservableObject {
@Published var id: Int = 0
}
let model = MyModel()
Just(100).assign(to: &model.$id)
```
Here's an example of using the `@dynamicMemberLookup` attribute in Swift:
```swift
@dynamicMemberLookup
struct DynamicStruct {
subscript(dynamicMember member: String) -> String {
return "You accessed dynamic member '\(member)'"
}
}
let dynamicStruct = DynamicStruct()
let result = dynamicStruct.someDynamicMember
print(result) // Output: "You accessed dynamic member 'someDynamicMember'"
```
Key Value Coding
```swift
class SomeClass: NSObject {
@objc dynamic var name = "Name"
}
```
```swift
object.value(forKey: "name") as String
```
```swift
object.setValue("New name", forKey: "name")
```
### Create map
```Swift
extension Sequence {
func dictionay<T>(keyPath: KeyPath<Element, T>) -> [T: Element] {
var dictionary = [T: Element]()
for elemement in self {
let key = elemement[keyPath: keyPath]
dictionary[key] = elemement
}
return dictionary
}
}
```
### Compact
```swift
extension Array {
public func compact<T>() -> [T] where Element == Optional<T> {
compactMap { $0 }
}
}
```
### Swift - currying
[https://thoughtbot.com/blog/introduction-to-function-currying-in-swift](https://thoughtbot.com/blog/introduction-to-function-currying-in-swift)
```swift
func curry<A, B, C, D>(_ f: @escaping (A, B, C) -> D) -> (A) -> (B) -> (C) -> D {
{ a in { b in { c in f(a, b, c) } } }
}
func curry<A, B, C>(_ f: @escaping (A, B) -> C) -> (A) -> (B) -> C {
{ a in { b in f(a, b) } }
}
func uncurry<A, B, C>(_ f: @escaping (A) -> (B) -> C) -> (A, B) -> C {
{ f($0)($1) }
}
func uncurry<A, B, C, D>(_ f: @escaping (A) -> (B) -> (C) -> D) -> (A, B, C) -> D {
{ f($0)($1)($2) }
}
func currying<A, B, C>(_ a: A, _ f: @escaping (A, B) -> C) -> (B) -> C {
{ (curry(f))(a)($0) }
}
func currying<A, B, C, D>(_ a: A, _ f: @escaping (A, B, C) -> D) -> (B, C) -> D {
{ (curry(f))(a)($0)($1) }
}
```
#### Example of usage
```swift
func add(a: Int, b: Int, c: Int) -> Int {
a + b + c
}
```
```swift
let adding = curry(add)
let adding5 = uncurry(adding(5))
```
or
```swift
let adding5 = currying(5, add)
```
then
```swift
print(adding5(6, 7))
```
## Check availability
[https://www.avanderlee.com/swift/available-deprecated-renamed/](https://www.avanderlee.com/swift/available-deprecated-renamed/)
```swift
if #available(iOS 15, *) {
print("This code only runs on iOS 15 and up")
} else {
print("This code only runs on iOS 14 and lower")
}
```
```swift
guard #available(iOS 15, *) else {
print("Returning if iOS 14 or lower")
return
}
print("This code only runs on iOS 15 and up")
```
```swift
@available(iOS 14, *)
final class NewAppIntroduction {
// ..
}
```
```swift
@available(iOS, deprecated: 12, obsoleted: 13, message: "We no longer show an app introduction on iOS 14 and up")
@available(*, unavailable, renamed: "launchOnboarding")
```
Mapping
```swift
func maping<T>(keyPath: KeyPath<Element, T>) -> [T: Element] {
var dictionary = [T: Element]()
for elemement in self {
let key = elemement[keyPath: keyPath]
dictionary[key] = elemement
}
return dictionary
}
```
### Type aliases
```swift
public typealias Point<T: Numeric> = (x: T, y: T)
public typealias MyResult<T> = Result<T, Error>
```
async/await

68
ios/recipies.md Normal file
View file

@ -0,0 +1,68 @@
---
layout: default
title: Recipies
categories: swift
---
```swift
extension UIFont {
var bold: UIFont {
guard let newDescriptor = fontDescriptor.withSymbolicTraits(.traitBold) else {
return self
}
return UIFont(descriptor: newDescriptor, size: pointSize)
}
}
```
```swift
public struct FontStyle: ViewModifier {
let isBold: Bool
private let font: Font
public init(isBold: Bool = false) {
self.isBold = isBold
self.font = self.font.bold
}
public func body(content: Self.Content) -> some View {
content.font(font)
}
}
extension View {
public func fontStyle(isBold: Bool = false) -> some View {
modifier(FontStyle(isBold: isBold))
}
}
```
## Testing
```swift
class ExampleXCTestCase: XCTestCase {
let app = XCUIApplication()
override func tearDown() {
app.terminate()
}
override func tearDownWithError() throws {
app.terminate()
}
}
```
In tests (it has to be called before `app.launch()`)
```swift
launchEnvironment["key"] = "value"
```
in the app:
```swift
ProcessInfo.processInfo.environment["key"]
```

418
ios/threading.md Normal file
View file

@ -0,0 +1,418 @@
---
layout: default
title: Threading
categories: swift
---
Chunk of jobs that can be performed on the separate thread are arranged into:
- `Closures` or `Functions`/`Methods` and send to `DispatchQueue`
- Classes and send as objects to `OperationQueue`. The queue can perform `Closure` as well
#### Kinds of jobs
* Computation intensive jobs: When the thread uses entire processing capability of `CPU`. The reasonable maximum number of the threads is the number of CPU cores.
* I/O intensive jobs: In that case we can trigger more threads than we have CPU cores. An optimal of threads is `Threads` = `Cores` / (1-`Blocking Factor`).
# [GCD](https://github.com/apple/swift-corelibs-libdispatch) (Grand Central Dispatch)
Creating queue. Note without parameter `attributes` we will get serial queue
```swift
let queue = DispatchQueue(label: "important.job",
qos: .default,
attributes: .concurrent)
```
#### Examples of sending jobs to queues:
Send to the queue and proceed with the execution in the current context
```swift
queue.async {
<#Code of the job#>
}
```
Same as above, but on main thread where UI operations should be done
```swift
DispatchQueue.main.async {
<#Code of the job#>
}
```
Perform on the global queue
```swift
DispatchQueue.global(qos: .background).async {
<#Code of the job#>
}
```
Send block that will be executed when all jobs sent at this point are completed. Stop current thread will the queue is done with the sent block.
```swift
queue.sync(flags: [.barrier]) {
<#Code of the job#>
}
```
Perform job in the time interval
```swift
queue.schedule(after: .init(.now()), interval: .seconds(3)) {
<#Code of the job#>
}
```
Getting the label of the queue
```swift
extension DispatchQueue {
static var label: String {
return String(cString: __dispatch_queue_get_label(nil),
encoding: .utf8) ?? ""
}
}
```
### `DispatchGroup`
```swift
extension Sequence {
public func threadedMap<T>(_ mapper: @escaping (Element) -> T) -> [T] {
var output = [T]()
let group = DispatchGroup()
let queue = DispatchQueue(label: "queue-for--map-result", qos: .background)
for obj in self {
queue.async(group:group) {
output.append(mapper(obj))
}
}
group.wait()
return output
}
}
```
### Mutex
Performing max 3 tasks at the time
```swift
let semaphore = DispatchSemaphore(value: 3)
for _ in 0..<15 {
queue.async(qos: .background) {
semaphore.wait()
<#Code of the job#>
semaphore.signal()
}
}
```
### Locking and unlocking the thread
**NSLock**
Example of usage. The concurrent queue becomes sort of serial. One job at the time, but execution in random order.
```swift
let lock = NSLock()
for _ in 1...6 {
queue.async {
lock.lock()
<#Code of the job#>
lock.unlock()
}
}
```
**Mutex**
Same thing using `pthread` API
```swift
var mutex = pthread_mutex_t()
pthread_mutex_init(&mutex, nil)
for i in 1...6 {
queue.async {
pthread_mutex_lock(&mutex)
<#Code of the job#>
pthread_mutex_unlock(&mutex)
}
}
```
When you are done with the lock, you need to release it
```swift
pthread_mutex_destroy(&mutex)
```
# `NSOperationQueue`
```swift
let queue = OperationQueue()
queue.name = "Queue Name"
queue.maxConcurrentOperationCount = 1
```
```swift
class MyVeryImportantOperation: Operation {
override func main() {
if isCancelled { return }
// Some chunk of time consuming task
if isCancelled { return }
// Some another chunk of time consuming task
// and so on...
}
}
```
Sending jobs to the queue
```swift
let myOperation = MyVeryExpensiveOperation()
queue.addOperation(myOperation)
```
```swift
queue.addOperation {
<#Code of the job#>
}
```
Notes `NSOperationQueue` fit better when requires canceling, suspending a block and/or dependency management
# NSThread
```swift
let thread = Thread {
<#code#>
}  
```
```swift
let thread = Thread(target: self,
selector: #selector(jobMethod:),
object: argumentObject)
```
```swift
thread.start()
```
Async method
```swift
func doStuff() async {
<#code#>
}
```
# Span a thread in `NSObject` context
```swift
perform(#selector(job), on: .main, with: nil, waitUntilDone: false)
```
# async/await
Available from `Swift 5.5`. More info at [docs.swift.org](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/)
#### Await the task group
```swift
let movies = await withTaskGroup(of: Movie.self) { group in
var movies = [Movie]()
movies.reserveCapacity(2)
for no in 1...2 {
group.addTask {
return await apiClient.download(movie: no)
}
}
for await movie in group {
movies.append(movie)
}
return movies
}
```
**Order of execution**
```swift
print("Before task group")
await withTaskGroup(of: Void.self) { group in
for item in list {
group.addTask {
await doSomething()
print("Task completed")
}
}
print("For loop completed")
}
print("After task group")
```
```plain
 1 => print("Before task group")
 2 => print("For loop completed")
 3 => print("Task completed")
 4 => print("Task completed")
 5 => print("Task completed")
 6 => print("After task group")
```
#### `Actor`s
- Do not support inheritance
```swift
actor TestActor {
var property = 1
func update(no: Int) {
sleep(UInt32.random(in: 1...3))
property = no
}
}
```
```swift
let actor = TestActor()
await actor.update(no: 5)
```
#### Call synchronously and parallel
```swift
let firstMovie = await apiClient.download(movie: 1)
let secondMovie = await apiClient.download(movie: 2)
let movies = [firstMovie, secondMovie]
```
```swift
async let firstMovie = apiClient.download(movie: 1)
async let secondMovie = apiClient.download(movie: 2)
let photos = await [firstMovie, secondMovie]
```
#### Call the main thread
```swift
let t = Task { @MainActor in
print ("update UI")
return 5
}
await print(t.value)
```
#### Call `async` function from a regular method
```swift
func job(no: Int) async -> Int {
sleep(UInt32.random(in: 1...3))
return no
}
```
```swift
let result = Task {
await job(no: 5)
}
Task {
await print(result.value)
}
```
# pthread
This is an object that will be sent to the thread
```swift
class ThreadParameter {
let paramater = 1
}
```
This is a function that will be spanned on the background thread
```swift
func threadedFunction(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
var threadParameter = pointer.load(as: ThreadParameter.self)
<#Code of the job#>
return nil
}
```
Creating a `pthread`
```swift
var myThread: pthread_t? = nil
let threadParameter = ThreadParameter()
var pThreadParameter = UnsafeMutablePointer<ThreadParameter>.allocate(capacity:1)
pThreadParameter.pointee = threadParameter
let result = pthread_create(&myThread, nil, threadedFunction, pThreadParameter)
```
waiting for finishing the thread
```swift
if result == 0, let myThread {
pthread_join(myThread,nil)
}
```
# Span threads using `Combine` framework
**`subscribe(on:)`**
Quotes from: [https://trycombine.com/posts/subscribe-on-receive-on/](https://trycombine.com/posts/subscribe-on-receive-on/)
> `subscribe(on:)` sets the scheduler on which youd like the current subscription to be “managed” on. This operator sets the scheduler to use for creating the subscription, cancelling, and requesting input.
>
> ... `subscribe(on:)` sets the scheduler to subscribe the upstream on.
>
> A side effect of subscribing on the given scheduler is that `subscribe(on:)` also changes the scheduler for its downstream ....
Subscription is done once and calling second time the `subscribe(on: )` have no effect.
`subscribe(on: DispatchQueue.global(qos: .background))` queues on this call &rarr; `func request(_ demand: Subscribers.Demand)`
**`receive(on:)`**
> The correct operator to use to change the scheduler where downstream output is delivered is `receive(on:)`.
>
> On other words `receive(on:)` sets the scheduler where the downstream receives output on.
>
> You can use `receive(on:)` similarly to `subscribe(on:)`. You can use multiple `receive(on:)` operators and that will always change the downstream scheduler
# Usage of `RunLoop`
<!-- Diffrence between queue and runloop https://www.avanderlee.com/combine/runloop-main-vs-dispatchqueue-main/ -->
Doncumentation on [RunLoop](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html)
> The purpose of a run loop is to keep your thread busy when there is work to do and put your thread to sleep when there is non. - Apple
# Measure a performance time
```swift
let startTime = CFAbsoluteTimeGetCurrent()
<#Code of the job#>
let endTime = CFAbsoluteTimeGetCurrent()
print("Duration:\(endTime - startTime) seconds")
```
#### Stop thread for some time
```swift
sleep(2)
```
```swift
try await Task.sleep(until: .now + .seconds(2), clock: .continuous)
```

350
js/notes.md Normal file
View file

@ -0,0 +1,350 @@
---
layout: default
title: Javascript - notes
categories: programming
path: js/notes
---
Useful tool: Why did you render
https://react.dev/learn/react-developer-tools
### Currying - JavaScript
```js
function currying(fn, ...args) {
return (..._arg) => {
return fn(...args, ..._arg);
}
}
```
```js
function sum(a,b,c) {
return a + b + c
}
let add = currying(sum,10);
```
#### Advanced implementation
```js
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args)
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2))
}
}
}
}
```
Usage
```js
function sum(a, b, c) {
return a + b + c;
}
let curriedSum = curry(sum);
// Callable normally
curriedSum(1, 2, 3)
// Currying of 1st argument
curriedSum(1)(2,3)
// Currying all arguments
curriedSum(1)(2)(3)
```
### Closures
```javascript
var NextClosure = function() {
var a = 0;
return function next() {
a++
return a
}
}
```
```javascript
var next = NextClosure()
console.log(next())
console.log(next())
console.log(next())
```
### Manipulating SVG
```html
<svg id="display" width="50" height="50" style="background-color: aqua;"></svg>
```
```javascript
let element = document.createElementNS("http://www.w3.org/2000/svg", 'rect')
element.setAttribute("x", 25)
element.setAttribute("y", 25)
element.setAttribute("width", 25)
element.setAttribute("height",25)
element.setAttribute("fill", "black")
let display = document.getElementById("display")
display.appendChild(element)
```
### Operations on arrays
```js
let test = [1,2,3,4,5,6,7]
console.log(test.splice(-5, 5)) // [ 3, 4, 5, 6, 7 ]
console.log(test) // [ 1, 2 ]
```
- `test.splice(-5, 5)` counting from the end
- `test.splice(5)` from 5th to the end of the array
```js
// Take just first element
console.log(process.argv.shift()
```
## Call function in place
```js
(function waitForAsync() {
if (end) {
console.log("Synchronous operation can proceed now")
} else {
setImmediate(waitForAsync)
}
})()
```
## Spawn process
```js
const { spawn } = require('child_process')
const child = spawn(command, params, {cwd: process.cwd()});
//for text chunks
child.stdout.setEncoding('utf8')
child.stdout.on('data', (chunk) => {
//process.stdout.write(chunk)
})
// since these are streams, you can pipe them elsewhere
// child.stderr.pipe(dest);
child.on('close', (code) => {
console.log(`ENDED: ${command} ${params.join(" ")} $ => ${code}`);
});
```
## Handling working directory
```js
function dir(wd, commands) {
let saveWD = process.cwd()
process.chdir(wd)
commands()
process.chdir(saveWD)
}
```
## Execute script loaded from string
```js
const util = require('util')
const vm = require('vm')
const sandbox = {
animal: 'cat',
count: 2
}
const script = new vm.Script('count += 1; name = "kitty"')
const context = new vm.createContext(sandbox)
for (let i = 0; i < 10; ++i) {
script.runInContext(context)
}
console.log(util.inspect(sandbox))
```
or
```js
primes = [ 2, 3, 5, 7, 11 ]
subset = eval('primes.filter(each => each > 5)')
console.log(subset)
```
```js
(async () => {
let file = await readSource()
})()
```
mjs => node module, allows to use await/async at the top level
```json
{
"name": "om",
"version": "1.0.0",
"main": "dist/index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "ts-node src/index.ts",
"build": "tsc && cp src/om dist/om",
"run": "node dist/index.js",
"watch": "nodemon --watch 'src/**' --ext 'ts,json' --ignore 'src/**/*.spec.ts' --exec 'tsc || true'"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"commander": "^12.0.0",
"pg": "^8.11.5"
},
"devDependencies": {
"nodemon": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
```
## Make executable
```js
#!/usr/bin/env node
require(".")
```
### Get all function argments
```js
function func(1,2 3) {
console.log(arguments)
}
```
## String literals and parentheses-less calls
```javascript
const showstring = (str, ...values) => {
console.log(str);
console.log(values)
}
const name = 'John'
showstring`Hello World ${name} ${name} ${1 + 2} and more`;
```
```javascript
// str
[
"Hello World ",
" ",
" ",
" and more"
]
// values
[
"John",
"John",
3
]
```
## Generators
```javascript
function* zip(...arrays){
const maxLength = arrays.reduce((max, curIterable) => curIterable.length > max ? curIterable.length: max, 0);
for (let i = 0; i < maxLength; i++) {
yield arrays.map(array => array[i]);
}
}
```
## `this` and inheritance
```js
function sum(b) {
return this.a + b;
}
sum.call({a: 4}, 5) // 9
const newSum = sum.bind({a: 4})
newSum(3) // 7
```
```js
function User() {
this.id = 5
this.test1 = () => {
console.log(this.id)
}
this.test2 = function() {
console.log(this.id)
}
}
User.prototype = {
show: function () {
console.log(`user id = ${this.id}`)
}
}
let user = new User()
user.show() // user id = 5
user.test1() // 5
user.test2() // 5
user.__proto__ = {
show: function() {
console.log(`user: ${this.name}`)
}
}
user.name = "Artur"
user.show() // user: Artur
user.__proto__ = {
show: () => {
console.log(`user: ${this.name}`)
}
}
user.show() // user:
```

567
linux/installation.md Normal file
View file

@ -0,0 +1,567 @@
---
layout: default
title: Linux installation
categories: linux
---
In case of installation on VM make the disk image
```
qemu-img create -f qcow2 debian.qcow2 16G
```
Other format option
```
qemu-img create -f raw debian.raw 16G
-drive file=disk.raw,format=raw
```
Start the VM with [bios](https://github.com/clearlinux/common/raw/master/OVMF.fd)
```bash
qemu-system-x86_64 -bios OVMF.fd -m 1G -drive file=debian.qcow2,format=qcow2 \
-cdrom debian-12.2.0-amd64-netinst.iso
```
Go through the installation process and then power off the VM
Start VM with command
```bash
qemu-system-x86_64 -bios OVMF.fd -m 1G -smp 6 \
-net user,hostfwd=tcp::2222-:22 -net nic \
-drive file=debian.qcow2,format=qcow2
```
## Prepare install media on macOS
Insert and unmount an USB stick
```bash
diskutil unmount /dev/disk2s1
```
Here is how we can list all the disks attached to the system
```bash
diskutil list
```
Writing image to the USB device (notice that we do not write to a partition)
```bash
sudo dd if=archlinux-2021.01.01-x86_64.iso of=/dev/disk2
```
then flush the data by ejecting the drive
```bash
sudo sync
diskutil eject /dev/disk2
```
# Debian sid
This is the Debian setup where most of the examples shown on the website should work.
Download links:
<!-- https://www.debian.org/CD/live/ -->
- [amd64 - Install disc](https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.2.0-amd64-netinst.iso)
- [amd64 - Live disc](https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/)
During installation select SSH server, standard system utilities and no desktop
#### Allowing login root user from the network
This is our testing installation, so we do not care about security, but easiness and convenience.
```bash
nano /etc/ssh/sshd_config
```
`Ctrl-o` `Ctrl-x`
Put this line in the file
```plain
PermitRootLogin yes
```
and then
```bash
systemctl restart sshd
```
From now on you can log in to the VM using ssh connection
```
ssh -p 2222 user@localhost
```
### Making it the sid
/etc/apt/sources.list
```
deb https://deb.debian.org/debian/ sid main contrib non-free non-free-firmware
deb-src https://deb.debian.org/debian/ sid main contrib non-free non-free-firmware
```
```bash
apt update
apt upgrade
apt dist-upgrade
apt autoremove
apt install firmware-linux-nonfree
```
### Tools
```sh
apt install neovim clang
```
**Swift**
Dependencies
```sh
apt install build-essential libcurl4-openssl-dev binutils git gnupg2 libc6-dev \
libedit2 libsqlite3-0 libxml2-dev libz3-dev pkg-config tzdata \
tzdata unzip zlib1g-dev libgcc-9-dev libncurses-dev \
libstdc++-9-dev
```
Missing dependencies for Debian sid
```text
libpython3.8
```
Installed instead
```plain
apt install libpython3.10-dev python3-clang python3-lldb
```
Downloading and installing
```
wget https://download.swift.org/swift-5.9.1-release/ubuntu2204/swift-5.9.1-RELEASE/swift-5.9.1-RELEASE-ubuntu22.04.tar.gz
tar -xf swift-5.9.1-RELEASE-ubuntu22.04.tar.gz
mv swift-5.9.1-RELEASE-ubuntu22.04 /opt/swift-5.9.1
```
add this line to `/etc/profile` so the path will be added for all the users
```plain
export PATH="$PATH:/opt/swift-5.9.1/usr/bin"
```
# Archlinux
Links:
- [torrents with ISO files](https://archlinux.org/releng/releases/)
- [latest ISO version from HTTP mirror](https://geo.mirror.pkgbuild.com/iso/latest/)
- [Offline: Most recent installation guide](https://wiki.archlinux.org/index.php/Offline_installation)
- [UEFI: Most recent installation guide](https://wiki.archlinux.org/title/installation_guideI)
# Installation
Note: in case case it is Mac mini. Hold alt (option) button on boot up and select the install disk.
Here are commands to check what discs are attached to the system
```bash
cat /proc/partitions
ls /dev/[s|x|v]d*
lsblk
fdisk l
ls /dev | grep ^[s|v|x][v|d]$*
```
<!--
The install disk has free space which we can use (for example to create install scripts in case we use the install disk several times)
cfdisk /dev/sdb
Select thf freespace and hit `[New]` and `Enter` => `[Write]` => `enter` => `yes` =>`Enter` => `[Quit]`
Now we have unformatted partition. To screate FAT32 execute this commend
Mount it as home folder
mount /dev/sdb4 /root
# and go to the new home root
cd
# this command was given by arch wiki but do not work for me
# https://wiki.archlinux.org/index.php/FAT
Now I realized I can edit system, so the partition that I have just created I can mount on start. There are steps I took.
- On the USB stick there is prtition named Gap1. I remove it becouse it seems to not be needed. I use `gparted` for that.
- Shrink vfat partition to 8000 MiB and place it at the and.
- Crate partitions to look like this: `[1: 628.97MiB]` `[2: 2.2 GiB]` `[3: 59 MiB]` `[4: 4000 MiB]` `[5: 8000MiB]`
1. `ARCH202101`: It is the oryginal partition ISO9660 I had after writing image
2. Freespace that will might be used when I edit the first partition
3. The UEFI partition where is placed bootloader that starts sysyem that is located on the first partition. This partition comes form the orygunal image.
4. `CHROOT`: This parition will contains files of the installer system. They are placed on Ext4 partition, so we can edit files and regenerate ISO file from it.
5. Home folder for root user, so when we can write scripts, store files so we can use them in other instalation process.
Now we copy read only files from read only system to writable partition
sudo mount -o loop /media/artur/ARCH202101/arch/x86_64/airfs.sfs /mnt
sudo cp -T /mnt /media/artur/CHROOT
-->
Update packages manager
```bash
pacman -Sy
```
Make a partition table
```bash
parted -s /dev/sda mktable GPT
```
### Create partitions
In this case:
- 300MB &rarr; UEFI
- 16GB &rarr; Swap
- Rest &rarr; System
List all types of partitions
```bash
sfdisk -T
```
#### First way: Using `sfdisk`
```bash
sfdisk /dev/sda << EOF
,300,ef
,16000,S,h
;
EOF
```
or pipe to the program like
```bash
echo ',,c;' | sfdisk /dev/sdd
```
#### Secund way: Using `fdisk`
```bash
fdisk /dev/sda << FDISK_CMDS
g
n
1
+300MiB
t
1
n
2
+16GiB
t
2
19
n
3
t
3
20
w
FDISK_CMDS
```
#### Therd way
```bash
cfdisk /dev/sda
```
Formatting
```bash
mkfs.fat -F32 /dev/sda1
mkswap /dev/sda2
mkfs.ext4 /dev/sda3
```
Mounting partitions
```bash
mount /dev/sda3 /mnt
swapon /dev/sda2
```
Installing base packages
```bash
pacstrap /mnt base base-devel linux linux-firmware
```
Chrooting
```bash
arch-chroot /mnt << CHROOT
#commands
CHROOT
```
or just `arch-chroot /mnt` and then commands
```bash
echo "archlinux" > /etc/hostname
sed -i "s/#en_US/en_US/g" /etc/locale.gen
locale-gen
echo LANG=en_US.UTF-8 > /etc/locale.conf
export LANG=en_US.UTF-8
ln -s /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
hwclock --systohc --utc
```
#### Run 32bit apps
open &rarr; `/etc/pacman.conf` and uncomment `[multilib]` section
Installing additional software
```bash
pacman -Syu
pacman -S zsh --noconfirm
```
#### Setup users
Set password for root
```bash
passwd
```
Create user
```bash
useradd -mg users -G wheel,storage,power -s /usr/bin/zsh user
```
```bash
passwd user
```
You can force user to change password
```bash
chage -d 0 user
```
sudoers
```bash
visudo
```
or
```bash
cat >> /etc/sudoers <<EOL
%wheel ALL=(ALL) NOPASSWD: ALL
EOL
```
### Setting up bootloader
```bash
pacman -S grub efibootmgr dosfstools os-prober mtools --noconfirm
mkdir /boot/EFI
mount /dev/sda1 /boot/EFI
grub-install --target=x86_64-efi --efi-directory=/boot/EFI --bootloader-id=grub_uefi --recheck
grub-mkconfig -o /boot/grub/grub.cfg
```
then `exit` and
Generate `fstab`
```bash
genfstab -U -p /mnt >> /mnt/etc/fstab
```
- `umount -a`
- `poweroff`
## Install any Linux out from VM
Create OS archive locally using rsync
```bash
rsync -aAXHSv /* /root/winux --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/root/*,/media/*,/lost+found,/home/*/.gvfs}
tar -cvjSf winux.tar.bz2 winux
```
or
```bash
tar -cvjSf winux.tar.bz2 / --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/root/*,/media/*,/lost+found,/home/*/.gvfs}
```
Create archive and move it to the host
```
ssh -p 2222 root@localhost 'tar -cvjS / --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/root/*,/media/*,/lost+found,/home/*/.gvfs} --to-stdout' > winux.tar.bz2
```
#### Extract files to the destination drive
```bash
tar -xvjf winux.tar.bz2 -C /mnt/sys
```
https://wiki.archlinux.org/title/Moving_an_existing_install_into_(or_out_of)_a_virtual_machine
Then generate fstab
```bash
genfstab -U /mnt/sys > /mnt/sys/etc/fstab
```
<!--
## More customisation
#### DHCP
```
pacman -S dhcpcd --noconfirm
```
```s
systemctl enable dhcpcd
systemctl start dhcpcd
```
```bash
dhcpcd enp3s0f0
```
```
ip a
ping -c2 google.com
```
## Sway
```bash
pacman -S git meson wlroots wayland wayland-protocols \
pcre2 json-c pango cairo gdk-pixbuf2
```
```bash
git clone https://github.com/swaywm/sway.git
```
building
```bash
git checkout v1.8
```
Disable waring as errors in `meson.build` 10 line `'werror=false'`
```bash
meson build/
ninja -C build/
sudo ninja -C build/ install
```
# Interesting software
- zathura - PDF reader
- poppler => gives pdftotext
# Building own environment (inside QEMU) - Archlinux
```bash
pacman -S qemu-guest-agent
systemctl enable --now qemu-guest-agent
```
### install software to build and run
```bash
pacman -S egl-wayland meson wlroots wayland wayland-protocols pcre2 json-c pango cairo gdk-pixbuf2 scdoc cmake less xorg-xwayland xdg-desktop-portal-wlr xdg-desktop-portal-gtk ttf-bitstream-vera gnu-free-fonts noto-fonts ttf-croscore ttf-dejavu ttf-droid ttf-ibm-plex ttf-liberation xorg
```
```bash
git clone https://github.com/swaywm/sway.git
cd sway/
git checkout v1.8
meson build/
ninja -C build/
sudo ninja -C build/ install
```
# Building own environment (inside QEMU) - Debian
```
apt install -y libnvidia-egl-wayland-dev meson libwlroots-dev wayland-utils wayland-protocols libpcre2-dev libjson-c-dev \
libpango-1.0-0 libpangocairo-1.0-0 libcairo2-dev libpango1.0-dev libgdk-pixbuf2.0-dev scdoc cmake xwayland bochs bochs-sdl bochs-term bochs-wx bochs-x \
vgabios xscreensaver-gl xscreensaver-gl-extra mesa-vulkan-drivers mesa-utils-bin mesa-utils mesa-drm-shim mesa-common-dev \
libglx-mesa0 libglw1-mesa-dev libgl1-mesa-dri libglapi-mesa libgl1-mesa-dri libgbm-dev weston libweston-12-dev curl htop \
openssh-server neovim zsh ruby python3 cmake rust-all ruby-dev ruby-full build-essential npm r-base r-base-dev fzf rclone \
rtorrent htop bundler neomutt golang ghc cabal-install gulp npm neovim mc tree cmake scala maven imagemagick hexedit erlang \
nasm binutils nim tmux wget httpie yarn meson util-linux ninja-build git fakeroot build-essential ncurses-dev xz-utils \
libssl-dev bc flex libelf-dev bison python3-pip libisl-dev texinfo libmpfr-dev libmpc-dev libgmp3-dev genisoimage clang \
libboost-tools-dev libboost-dev libboost-system-dev gcc g++ make pkg-config libgtk-3-dev libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev cmake ninja-build coreutils libxml2-dev libsqlite3-dev libicu-dev libxslt-dev libjpeg-dev \
libpng-dev libwebp-dev libsecret-1-dev binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libsqlite3-0 libstdc++-9-dev \
libxml2 libz3-dev pkg-config tzdata zlib1g-dev python3 apt-file libwayland-server++1 libwayland-server0 freerdp2-dev \
freerdp2-wayland libpam-freerdp2-dev libavutil-dev libavcodec-dev libavutil-dev libavformat-dev fossil krusader texlive-full \
openssh-server neovim zsh ruby python3 cmake binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libsqlite3-0 \
libstdc++-9-dev libxml2 libz3-dev pkg-config tzdata zlib1g-dev python3 rust-all ruby-dev ruby-full build-essential npm \
r-base r-base-dev fzf rclone rtorrent htop bundler neomutt golang ghc cabal-install gulp npm neovim mc tree cmake scala \
maven imagemagick hexedit erlang nasm binutils nim tmux wget httpie yarn meson util-linux ninja-build python3-pip libisl-dev \
texinfo libmpfr-dev libmpc-dev libgmp3-dev genisoimage clang libboost-tools-dev libboost-dev libboost-system-dev git fakeroot \
build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison gcc g++ make pkg-config cmake ninja-build \
coreutils libgtk-3-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libxml2-dev libsqlite3-dev libicu-dev libxslt-dev \
libjpeg-dev libpng-dev libwebp-dev libsecret-1-dev
```
-->

31
linux/systemd.md Normal file
View file

@ -0,0 +1,31 @@
---
title: Systemd
layout: default
---
Example with `kodi` : `/lib/systemd/system/kodi.service`
```ini
[Unit]
Description = Kodi Media Center
After = remote-fs.target network-online.target
Wants = network-online.target
[Service]
User = pi
Group = pi
Type = simple
ExecStart = /usr/bin/kodi-standalone
; ExecStart = /usr/bin/su %i /usr/bin/kodi-standalone
Restart = on-abort
RestartSec = 5
[Install]
WantedBy = multi-user.target
```
```
systemctl enable kodi
systemctl start kodi
```

211
programming/bridging.md Normal file
View file

@ -0,0 +1,211 @@
---
layout: default
title: Bridging between languages
categories: programming
---
We can cross call functions from languages that:
- Both are compilable &rarr; Strategy: Create a binary library and call function from it.
- Library in `interpreted` and the project in `compiled` &rarr; Strategy: Create an interpreter context, then load the files and execute them.
- Library in `compiled` and the project in `interpreted` &rarr; Strategy: Use `FFI`.
- Both are interpreted
- Probably give up. Bridging will be possible, but messy and complicated
- Create two programs and exchange data between them using pipe, sockets, message quesues, databses etc.
### Creating shared and static library in Go
An example code that is shared [`example.go`](https://github.com/artur-gurgul/codebook):
``` go
package main
import "C"
import "fmt"
//export SayHello
func SayHello(hello *C.char) {
fmt.Print(C.GoString(hello))
}
func main() {}
```
- The `main` function is neccecery to include into library, because the final product has to have for example the GC rutines.
- The comment starting from `//export {function name}` tells the comiler that this the function will be called from the outside.
#### Creating static library
```
go build -o example.a -buildmode=c-archive example.go
```
#### Creating dynamic library
```
go build -o example.dylib -buildmode=c-shared example.go
```
### Creating shared and static library in Swift
`point.swift`
```swift point.swift
public struct Point {
public let x: Int
public let y: Int
public init(x: Int, y: Int) {
self.x = x
self.y = y
}
}
```
and compile with command (module name is optional)
```sh
swiftc point.swift -emit-module  -module-name Point -emit-library -static
```
**Using**
```swift
import Point
let p = Point(x: 4, y: 20)
print("Hello library!", p.x, p.y)
```
compile with
```sh
swiftc main.swift -L ./lib/ -I ./lib/ -lpoint
```
#### Dynamic library in Swift
```
swiftc point.swift -emit-module -emit-library
```
it produces
- `libpoint.a`
- `point.swiftdoc`
- `point.swiftmodule`
- `point.swiftsourceinfo`
Compile main program the same way as it has been down with the static one
Library searching paths `/usr/lib/`, `/usr/local/lib/` 
**_Create package that emits library_**
```swift
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "MyLibrary",
products: [
/// type: automatic, based on the environment
.library(name: "MyLibrary",
// type: .dynamic, .static
targets: ["MyLibrary"]
),
],
targets: [
.target(name: "MyLibrary", dependencies: []),
]
)
```
### Calling function from library in Go
First off we will create C++ library that we will use in out Go program.
File `example.cxx`:
```c++
#include <stdio.h>
extern "C" {
void PrintHello(const char* u) {
printf("Hello: %s\n", u);
}
}
```
And `example.hxx`:
```c++
#pragma once
void PrintHello(const char* u)
```
`extern "C" {}` informs the compiler that we want the function names to be preserved. That is, to not "mangle" the names as is done for C++ code:
#### Creating static library
```bash
clang++ -c -Wall -o lib.o ./example.cxx
ar rc ./libexample.a ./lib.o
```
#### Creating dynamic library
```bash
clang++ -dynamiclib -o libexample.dylib example.cxx
```
## Statically linking an example library in Go
```go
package main
// #cgo CFLAGS: -I.
// #cgo LDFLAGS: -L. -lexample
//
// #include <example.hxx>
import "C"
func main() {
C.PrintHello(C.CString("Hello Golang"))
}
```
The program is linked staticaly with libexample when you build it.
#### Example of using library with FFI in Ruby
```shell
gem install ffi
```
```ruby
require 'ffi'
module Example
extend FFI::Library
ffi_lib './example.dylib'
attach_function :SayHello, [:string]
end
```
```ruby
Example.SayHello("Hello")
```
More informations about FFI: [https://en.wikipedia.org/wiki/Foreign_function_interface](https://en.wikipedia.org/wiki/Foreign_function_interface)
#### Call shared library from Python
```python
import ctypes
libc = ctypes.CDLL('./example.dylib')
libc.SayHello("Hello")
```
## Interesting websites
- [https://blog.filippo.io/building-python-modules-with-go-1-5/](https://blog.filippo.io/building-python-modules-with-go-1-5/)
- [https://id-rsa.pub/post/go15-calling-go-shared-libs-from-firefox-addon/](https://id-rsa.pub/post/go15-calling-go-shared-libs-from-firefox-addon/)

25
programming/solid.md Normal file
View file

@ -0,0 +1,25 @@
---
layout: default
title: SOLID principles
categories: programming
---
### Single responsibility principle
This mean if the one thing in specification is changed you only need to change the code in the single place or class
### Open/closed principle
Software should be open for extension, but closed for modification.
### Liskov substitution principle
Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
### Interface segregation principle
The interfaces should be small and provide as little methods as possible.
### Dependency inversion principle
The lower module must not depends on higher module. In order to achieve this the code must to relay on abstractions (in other words the code has to use interfaces/protocols)

62
utils/git-squash.md Normal file
View file

@ -0,0 +1,62 @@
---
layout: default
title: Git - notes
categories: software
---
Squash the last three commits
```bash
git rebase -i HEAD~3
```
You will see something like this
```plain
pick f392171 Added new feature X
pick ba9dd9a Added new elements to page design
pick df71a27 Updated CSS for new elements
```
- `pick` `p` the commit will be taken
- `squash` `s`, the commit will be blended with the above.
Edit to something like this
```plain
pick f392171 New message for this three commit!
squash ba9dd9a
squash df71a27
```
Now you can accept the change by continuing the rebase:
```bash
git rebase --continue
```
After that you need to force override the history using this command:
```bash
git push origin master --force
```
## Squash merge
```bash
git checkout master
git merge --squash bugfix
git commit
```
### Checkout bare repository
```
git clone --bare https://github.com/nextcloud/server.git /var/www/nextcloud.git --recursive
cd nextcloud.git; git worktree add /var/www/nextcloud
cd /var/www/nextcloud; checkout -f v27.1.4
git --work-tree=/var/www/nextcloud --git dir=/home/artur/pub/drive/repos/nextcloud.git checkout -f v27.1.4 --recursive
```

591
utils/recepies.yml Normal file
View file

@ -0,0 +1,591 @@
layout: default
title: Recipes
type: recipes
recipes:
Read a DNS records:
^: dns networking
$: dig artgur.net +nostats +nocomments +nocmd
I/O Stats:
$: iostat
Checking type of executable files:
$: otool -hv test.so
Gzip of image:
^: compression, zip
$: dd if=/dev/sdb | gzip > ~/backup.img.gz
Progress with `dd`:
$:
- sudo dd if=2024-11-19-raspios-bookworm-armhf.img of=/dev/disk27 status=progress
- sudo dd if=/dev/sdb | pv -s 5.29G | dd of=DriveCopy1.dd bs=4096
- sudo pv ubuntu-24.04.1-desktop-amd64.iso | sudo dd of=/dev/disk27
Get directory size:
$: du -sh MacOSBackup
Print all sizes in directory:
$:
- du -sh *
- du -shc *
Compare two files:
$:
- vim -d file1 file2
- mcdiff file1 file2
Disk manager:
$: cfdisk /dev/sda
List of disks:
$: parted -l
Informations about disk:
$: fdisk -l /dev/sda
Power off the disk:
$: udisksctl power-off -b /dev/sdX
Generate random password:
$:
- pwgen -s -1 32
- openssl rand -hex 12
List block devices:
$: lsblk
Linux headers:
-
$: uname -r
-
$: apt search linux-headers-$(uname -r)
Show all disks with json format:
$: lsblk -J
List disk with uuid's:
$: lsbkl -f
vfat file system:
- : Create a file systyem
$: mkfs.vfat -F 32 /dev/sdb4
- : Mount the file system
$: mount -i -t vfat -oumask=0000,iocharset=utf8 /dev/sdb4 /root
See what processes are using the drive:
$: lsof /where/drive/is/mounted
See what process opens the port:
$:
- lsof -p 6919
- lsof -i :6919
See the stats of IO:
$:
- apt install sysstat iotop
- iostat -dh 2
- iotop -o
- sar -p -d -b 1
- vmstat -d 1
- vmstat -p /dev/sda2 1
Rsync:
$: rsync -ah --progress /Volumes/Data /Volumes/Data\ 1/Junk/1TB\ Drive
reloading local DNS:
$: sudo /etc/init.d/dns-clean start
Print all processes in json format:
$: |
ps aux | awk -v OFS=, '{print $1, $2}' | jq -R 'split(",") | {user: .[0], pid: .[1]}'
Split files:
$: split -b 70M deno
Search and execute command from the history:
$: eval `history | fzf | cut -s -d " " -f4-`
file: .zshrc
content: |
export HISTSIZE=100000000
alias hexec='eval `history | fzf | cut -s -d " " -f4-`'
Editing command with editor:
file: ~/.zshrc
content: bindkey '^e' edit-command-line
Copy public ssh key:
- cat ~/.ssh/id_rsa.pub | pbcopy
change password that was saved in a variable:
$: echo "$archpass" | passwd "$archuser" --stdin
Git diff between branches:
$: git diff release-1.2.0..release-1.2.1
MacOS info aliases in `.zhrc`:
file: .zhrc
content: |
alias cpu='sysctl -n machdep.cpu.brand_string'
alias cpu-temp='sudo powermetrics --samplers smc | grep -i "CPU die temperature"'
alias gpu-temp='sudo powermetrics --samplers smc | grep -i "GPU die temperature"'
alias lsusb='sudo ioreg -p IOUSB'
alias allusb='ioreg -p IOUSB -w0 -l'
Power metrics:
$: sudo powermetrics --samplers all
Install pods from non standard localisations:
$: |
pod 'WASHD', :git => 'https://github.com/vatlib/EasyUITextFields.git'
pod 'WASHD', :path => '/Users/artur/projs/easyuitextfields'
SQLite select and search results with FZF:
$: echo "select * from bookmarks" | sqlite3 bookmarks.db | fzf
Open file with FZF:
$: nvim -o `fzf`
Set default shell. ZSH in this case:
$: sudo chsh --shell /usr/bin/zsh user
Show Git object:
$: pigz -d < .git/objects/02/f2cc93fee0b3cb7c9b75f49e4ded3f9b1480eb
list of wireless cards:
$: lspci -knn | grep Net -A2
Scan networks:
$: iwlist scan
Shutdown:
$: shutdown -h now
Connect to the network:
$: nmcli dev wifi connect TP-Link_5828 password my-secret-pass
You can forward port `80` to `8090`:
$: iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8090
Allow accepting connections on `8090`:
$: iptables -I INPUT -m tcp -p tcp --dport 8090 -j ACCEPT
Search files that contains particular string:
$: grep -rnw "." -e "Search key"
Remove garbage files:
$: find ./ -name ".DS_Store" -depth -exec rm {} \;
Find files, directories and symbolic links using regex:
$: find ./ -iname `fo*` and `F??` -type f,d,l
Make text from pipe uppercased:
$:
- cat file.txt | tr [:lower:] [:upper:]
- cat file.txt | tr [a-z] [A-Z]
- tr [a-z] [A-Z] < linux.txt > output.txt
Installing packages in python for an user:
$: pip3 install --user meson
Calling module through interpreter:
$: python3 -m pip install six
Remove spaces:
$: cat file.txt | tr -d ' '
Remove duplicate characters:
input-file: domains.txt
content: |
www.google.....com
www.linkedin.com
www.linuxsay.com
$: cat domains.txt | tr -s '.'
output: |
www.google.com
www.linkedin.com
Extract digit:
$:
- echo "My UID is $UID" | tr -cd "[:digit:]\n"
- echo "My UID is $UID" | tr -d "a-zA-Z"
Translate single character:
$: echo "My UID is $UID" | tr " " "\n"
Get path by number:
$: echo $PATH | cut -d ":" -f 1
list search path line by line:
$: echo $PATH | tr ":" "\n"
Screen capture:
$:
- ffmpeg -f x11grab -video_size 1280x800 -framerate 25 -i $DISPLAY -c:v ffvhuff screen.mkv
- ffmpeg -video_size 1280x800 -framerate 25 -f x11grab -i :0.0 -f pulse -ac 2. \
-i default -vcodec vp8 -acodec libvorbis myvideo_$(date +%d_%B_%Y_%H:%M).webm
Take a screenshot:
$:
- xwd -root -out screenshot.xwd
- maim -s -u | xclip -selection clipboard -t image/png -i
- imlib2_grab screenshot.png
Install Python package for the user:
$: python3 -m pip install --user pyelftools
Erase free space:
$: sudo diskutil secureErase freespace 1 /Volumes/Data\ Drive
Format disk:
$: sudo diskutil eraseDisk ExFAT data /dev/disk26
Search for commit:
$: alias gf='git log --all --oneline | fzf'
Converts all files in current directory revursevely:
install: brew install imagemagick
tags: convert image-magic
$: alias rmalfa='find . -name “*.png” -exec convert “{}” -alpha off “{}” \;'
Weather alias:
$: alias weather='curl wttr.in'
Starting an electron app on wayland:
- : Start chromium using wayland
$: chromium --enable-features=UseOzonePlatform --ozone-platform=wayland
- : The same for electron-based apps
$: |
`app-executable` --enable-features=UseOzonePlatform \
--ozone-platform=wayland
Save website As PDF:
file: .zshrc
content: |
function aspdf {
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --print-to-pdf="./$1.pdf" $2
}
$: aspdf "filename" "https://domain.com/example.pdf"
Export Markdown as PDF:
$:
- pandoc README.md -o README.pdf
- pandoc --from=gfm --to=pdf -o README.pdf README.md
Gem path:
content: |
export GEM_HOME=$HOME/.gem
path=("$GEM_HOME/bin" $path)
QEMU - port forwarding:
$: |
qemu-system-i386 -net nic,model=rtl8139 \
-net user,hostfwd=tcp::3389-:3389,hostfwd=tcp::443-:443,hostfwd=tcp::992-:992
SQL using regex:
description: Add a check constraint to the `id` column to enforce alphanumeric strings of exactly 5 characters long
$: ALTER TABLE short_urls ADD CONSTRAINT id CHECK (id ~ '^[a-zA-Z0-9]{5}$');
Console font size:
description: Edit file &rarr; `/etc/default/console-setup`
$: dpkg-reconfigure -plow console-setup
Redirect errors to null device:
$: find / 2>/dev/null
Installing nonfree firmware from repository:
description: |
I.e: Firmware for nonfree driver for Intel's WIFI cards.
https://packages.debian.org/sid/firmware-iwlwifi
$: apt-get update && apt-get install firmware-linux-nonfree
Installing nonfree firmware from manufacturer:
- : Search for binary. An example
link: https://www.intel.com/content/www/us/en/support/articles/000005511/wireless.html
- : Extract and copy like
$: cp iwlwifi-cc-a0-46.ucode /lib/firmware
Linux - RAM disk:
description: This might be useful for spead up programs that heavily use disk
$: mount -t TYPE -o size=SIZE FSTYPE MOUNTPOINT
info: |
* `TYPE` &rarr; either `tmpfs` or `ramfs`.
* `SIZE` &rarr; ie. `512m`
* `FSTYPE` &rarr; File system type, either `tmpfs`, `ramfs`, `ext4`, etc.
file: /etc/fstab
content: tmpfs /mnt/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size=1024M 0 0
fstab:
: Use 'blkid' to print the universally unique identifiers, and can be used in fstab file like
file: /etc/fstab
content: |
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=1a38b8ca-e1f5-45e6-bbe8-3abd2775b3a6 / ext4 errors=remount-ro 0 1
/swapfile none swap sw 0 0
/dev/disk/by-uuid/4D3C-4E36 /mnt/4D3C-4E36 auto nosuid,nodev,nofail,x-gvfs-show 0 0
UUID=e21eebe4-471a-4375-8c4c-618b3733a940 /home ext4 nodev,nosuid 0 2
Linux - Mount disk from `qcow2` image:
- : Step 1 - Enable NBD on the Host
$: modprobe nbd max_part=8
- : Step 2 - Connect the QCOW2 as network block device
$: qemu-nbd --connect=/dev/nbd0 /var/lib/vz/images/100/vm-100-disk-1.qcow2
- : Step 3 - Find The Virtual Machine Partitions
$: fdisk /dev/nbd0 -l
- : Step 4 - Mount the partition from the VM
$: mount /dev/nbd0p1 /mnt/somepoint/
- : Step 5 - After you done, unmount and disconnect
$:
- umount /mnt/somepoint/
- qemu-nbd --disconnect /dev/nbd0
- rmmod nbd
Ubuntu - Power management - make Ubuntu do nothing when laptop lid is closed:
- : Open the `/etc/systemd/logind.conf` file in a text editor as root, for example
$: sudo -H gedit /etc/systemd/logind.conf
- : If `HandleLidSwitch` is not set to ignore then change it
$: HandleLidSwitch=ignore
note: |
Other settings that the action can be ignored: `HandleLidSwitchExternalPower`, `HandleLidSwitchDocked`, `IdleAction`.
- : Restart the systemd daemon (be aware that this command will log you out)
$:
- sudo systemctl restart systemd-logind
- sudo service systemd-logind restart
Chroot environment of Debian sid:
- : Install Bootstrap
$: sudo apt install debootstrap
- : Create a directory that you want to use for the base system (_chroot-debian_ in this case)
$: mkdir chroot-debian
- : Create a base system
$: sudo debootstrap sid chroot-debian http://deb.debian.org/debian
note: Valid names `sid`, `stable` or any debian code name
- : Mount filesystems
$:
- sudo mount -o bind /dev chroot-debian/dev
- sudo mount -t sysfs none chroot-debian/sys
- sudo mount -o bind /proc chroot-debian/proc
- : Optionally, copy DNS resolver configuration.
$: sudo cp /etc/resolv.conf /path/to/chroot-env/etc/resolv.conf
- : Start chrooting
$: sudo chroot chroot-debian /bin/bash
- : Once done, exit the session and unmount
$: sudo umount chroot-debian/dev chroot-debian/proc
Pass variables to chrooted environment:
$: chroot ./ env -i PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Allowing user to run a command as root:
$: sudo visudo
content: artur ALL=(ALL) chroot /path/to/chroot-env
Nginx - serving files setup DAV:
- : Full version with 3rd party extensions
$: apt install nginx-full nginx-extras
-
content: |
location / {
index nonextistent;
autoindex on;
autoindex_format json;
}
location /restricted {
fancyindex on;
fancyindex_exact_size off;
auth_basic "Restricted";
auth_basic_user_file "/etc/nginx/.htpasswd";
}
location /dropbox {
index nonextistent;
autoindex on;
autoindex_format json;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
dav_access user:rw group:r all:r;
# client_max_body_size 0;
create_full_put_path on;
client_body_temp_path /tmp/;
limit_except GET PROPFIND OPTIONS HEAD {
auth_basic "Restricted";
auth_basic_user_file "/etc/nginx/.htpasswd";
}
# auth_pam "Restricted";
# auth_pam_service_name "common-auth";
}
- : Create password
$:
- echo -n 'sammy:' >> /etc/nginx/.htpasswd
- openssl passwd -apr1 >> /etc/nginx/.htpasswd
- : Another method to set the password
$:
- htpasswd -c /etc/nginx/.htpasswd sammy
- htpasswd /etc/nginx/.htpasswd another_user
note: UI Client `Cyberduck`
Backing up the entire OS:
$: sudo rsync -aAXHv / --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /mnt
Python:
$: apt install python3-full
Check battery:
- $:
- upower -i /org/freedesktop/UPower/devices/battery_BAT0
- upower -i `upower -e | grep 'BAT'`
- upower -i $(upower -e | grep BAT) | grep --color=never -E "state|to\ full|to\ empty|percentage"
- : Battery capacity
$: cat /sys/class/power_supply/BAT0/capacity
- : ACPI
$:
- apt install acpi
- acpi -V
- acpi -t
- : Watch the status for example
$: watch --interval=5 acpi -V
How to scan open ports:
$:
- nmap -sT -p- 10.10.8.8
- nmap -p 80 127.0.0.1
Remove non ASCII characters form the file:
$: sed 's/[^[:print:]\t]//g' script.sh > cleaned_script.sh
Network Manager:
- : Check Status
$:
- pacman -S networkmanager
- systemctl status NetworkManager
- $:
- nmcli dev status
- nmcli radio wifi
- $: nmcli radio wifi on
- $: nmcli dev wifi list
- $: nmcli dev wifi connect network-ssid
- $: nmcli dev wifi connect network-ssid password "network-password"
- : With password promot
$: nmcli dev wifi connect network-ssid password "network-password"
- $: nmcli con show
- $:
- nmcli con down ssid/uuid
- nmcli con up ssid/uuid
- $: ip link set eno1 up
DHCP Client:
$: pacman -S dhclient dhcpcd
Turn dchp on for the interface:
$: dhclient eth0 -v
Create file:
content: |
cat > filename <<- "EOF"
file contents
more contents
EOF
Get data about file include number of links:
$: stat f1
File decryption:
$: openssl aes256 -md sha256 -d -in file.enc.zip -out file.zip -pass pass:"<password>"
Base64:
$:
- openssl base64 -in qrcode.png -out qrcode.png.base64
- openssl base64 -in qrcode.png
Extract tar.xz:
$: tar -xJf file.tar.xz -C destination
Execute command:
- : Execute `ls` for each each object in current directory that starts from `D` or `M`
$: ls {D*,M*}
- : Utworzenie dwóch katalogów `test_a`, `test_b`
$: mkdir test_{a,b}
Copy content of directory and merge it. Dereference links:
$: cp -LTr /form/ .
JSON Linux apis:
$:
- tree -J
- ls -l | jq -R -s -c 'split("\n")[:-1]'
List dependencies:
$:
- pacman -Sy lld
- llvm-nm
Find location of executable:
$: type -a python
Execute Command when file is changed:
-
$: brew install fswatch
-
$: fswatch -o . --exclude "\.build.*$" | xargs -n1 -I{} your-command
Add capabilities:
description: allow all to open 443 port
$: sudo setcap 'cap_net_bind_service=+ep' ./service
Test speed of the drive:
$: sudo hdparam -t --direct /dev/mmcblk0

941
utils/recepiesmd.md Normal file
View file

@ -0,0 +1,941 @@
---
layout: default
title: Recipes MD
---
#### Read a DNS records
dig artgur.net +nostats +nocomments +nocmd
#### I/O Stats
iostat
#### Checking type of executable files
otool -hv test.so
#### #Receipe Gzip of image
```shell
dd if=/dev/sdb | gzip > ~/backup.img.gz
```
#### Progress with `dd`
```
sudo dd if=2024-11-19-raspios-bookworm-armhf.img of=/dev/disk27 status=progress
sudo dd if=/dev/sdb | pv -s 5.29G | dd of=DriveCopy1.dd bs=4096
sudo pv ubuntu-24.04.1-desktop-amd64.iso | sudo dd of=/dev/disk27
```
#### Get directory size
du -sh MacOSBackup
##### Print all sizes in directory
```bash
du -sh *
```
```bash
du -shc *
```
#### Compare two files
```bash
vim -d file1 file2
mcdiff file1 file2
```
### Disk manager
```bash
cfdisk /dev/sda
```
#### List disks
```
parted -l
```
#### informations about disk
```bash
fdisk -l /dev/sda
```
#### Power off the disk
```
udisksctl power-off -b /dev/sdX
```
#### Generate random password
```bash
pwgen -s -1 32
```
or
```
openssl rand -hex 12
```
#### List block devices
lsblk
#### Linux headers
```
uname -r
apt search linux-headers-$(uname -r)
```
Show all disks with json format
```shell
lsblk -J
```
List disk with uuid's
```shell
lsbkl -f
```
#### MKFS
```bash
mkfs.vfat -F 32 /dev/sdb4
```
```bash
mount -i -t vfat -oumask=0000,iocharset=utf8 /dev/sdb4 /root
```
#### See what processes are using the drive
```
lsof /where/drive/is/mounted
```
### See what process opens the port
```bash
lsof -p 6919
lsof -i :6919
```
#### See the stats of IO
```
apt install sysstat iotop
```
```
iostat -dh 2
iotop -o
sar -p -d -b 1
vmstat -d 1
vmstat -p /dev/sda2 1
```
### Rsync
```
rsync -ah --progress /Volumes/Data /Volumes/Data\ 1/Junk/1TB\ Drive
```
#### reloading local DNS
```shell
sudo /etc/init.d/dns-clean start
```
#### Print all processes in json format
``` shell
ps aux |
awk -v OFS=, '{print $1, $2}' |
jq -R 'split(",") | {user: .[0], pid: .[1]}'
```
### Split files
```
split -b 70M deno
```
#### Search and execute command from the history
```bash
eval `history | fzf | cut -s -d " " -f4-`
```
Adding this to `.zshrc`
```
export HISTSIZE=100000000
alias hexec='eval `history | fzf | cut -s -d " " -f4-`'
```
#### Editing command with editor
`~/.zshrc`
```
bindkey '^e' edit-command-line
```
#### Copy public ssh key
```bash
cat ~/.ssh/id_rsa.pub | pbcopy
```
#### change password that was saved in a variable
```bash
cho "$archpass" | passwd "$archuser" --stdin
```
#### Git diff between branches
git diff release-1.2.0..release-1.2.1
#### MacOS info aliases in`.zhrc`
```
alias cpu='sysctl -n machdep.cpu.brand_string'
alias cpu-temp='sudo powermetrics --samplers smc | grep -i "CPU die temperature"'
alias gpu-temp='sudo powermetrics --samplers smc | grep -i "GPU die temperature"'
alias lsusb='sudo ioreg -p IOUSB'
alias allusb='ioreg -p IOUSB -w0 -l'
```
**Power metrics**
```bash
sudo powermetrics --samplers all
```
#### Install pods from non standard localisations
```ruby
pod 'WASHD', :git => 'https://github.com/vatlib/EasyUITextFields.git'
pod 'WASHD', :path => '/Users/artur/projs/easyuitextfields'
```
#### SQLite select and search results with FZF
```bash
echo "select * from bookmarks" | sqlite3 bookmarks.db | fzf
```
#### Open file with FZF
```bash
nvim -o `fzf`
```
#### Set default shell. ZSH in this case
sudo chsh --shell /usr/bin/zsh user
#### Show Git object
```sh
pigz -d < .git/objects/02/f2cc93fee0b3cb7c9b75f49e4ded3f9b1480eb
```
#### list of wireless cards
lspci -knn | grep Net -A2
#### Scan networks
iwlist scan
#### Shutdown
shutdown -h now
#### Connect to the network
nmcli dev wifi connect TP-Link_5828 password my-secret-pass
#### You can forward port `80` to `8090`
```shell
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8090
```
#### Allow accepting connections on `8090`
```shell
iptables -I INPUT -m tcp -p tcp --dport 8090 -j ACCEPT
```
#### Search files that contains particular string
``` shell
grep -rnw "." -e "Search key"
```
#### Remove garbage files
find ./ -name ".DS_Store" -depth -exec rm {} \;
#### Find files, directories and symbolic links using regex
find ./ -iname `fo*` and `F??` -type f,d,l
#### Make text from pipe uppercased
```bash
cat file.txt | tr [:lower:] [:upper:]
cat file.txt | tr [a-z] [A-Z]
tr [a-z] [A-Z] < linux.txt > output.txt
```
#### Installing packages for python
**_just for user_**
```bash
pip3 install --user meson
```
**_calling module through interpreter_**
```bash
python3 -m pip install six
```
#### Remove spaces
```bash
cat file.txt | tr -d ' '
```
#### Remove duplicate characters
```bash
$ cat domains.txt
www.google.....com
www.linkedin.com
www.linuxsay.com
```
```bash
$ cat domains.txt | tr -s '.'
www.google.com
www.linkedin.com
```
#### Extract digit
``` bash
echo "My UID is $UID" | tr -cd "[:digit:]\n"
echo "My UID is $UID" | tr -d "a-zA-Z"
```
#### Translate single character
```bash
echo "My UID is $UID" | tr " " "\n"
```
#### Get path by number
```bash
echo $PATH | cut -d ":" -f 1
```
#### list search path line by line
```bash
echo $PATH | tr ":" "\n"
```
#### Screen capture
```
ffmpeg -f x11grab -video_size 1280x800 -framerate 25 -i $DISPLAY -c:v ffvhuff screen.mkv
ffmpeg -video_size 1280x800 -framerate 25 -f x11grab -i :0.0 -f pulse -ac 2. \
-i default -vcodec vp8 -acodec libvorbis myvideo_$(date +%d_%B_%Y_%H:%M).webm
```
#### Take a screenshot
```bash
xwd -root -out screenshot.xwd
maim -s -u | xclip -selection clipboard -t image/png -i
imlib2_grab screenshot.png
```
#### Install Python package for the user
python3 -m pip install --user pyelftools
#### Erase free space
sudo diskutil secureErase freespace 1 /Volumes/Data\ Drive
#### Format disk
sudo diskutil eraseDisk ExFAT data /dev/disk26
#### Search for commit
```bash
alias gf='git log --all --oneline | fzf'
```
#### Remove alpha channel from all files
```bash
# ➜ brew install imagemagick
```
**Converts all files in current directory revursevely**
```bash
alias rmalfa='find . -name “*.png” -exec convert “{}” -alpha off “{}” \;'
```
#### Weather alias
```sh
alias weather='curl wttr.in'
```
#### Starting an electron app on wayland
Start chromium using wayland
```bash
chromium --enable-features=UseOzonePlatform --ozone-platform=wayland
```
Its the same for electron-based apps:
```bash
`app-executable` --enable-features=UseOzonePlatform \
--ozone-platform=wayland
```
#### Save website As PDF
```bash
function aspdf {
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --print-to-pdf="./$1.pdf" $2
}
```
Usage
```bash
aspdf "filename" "https://superuser.com/questions/592974/how-to-print-to-save-as-pdf-from-a-command-line-with-chrome-or-chromium"
```
### Export Markdown as PDF
```bash
pandoc README.md -o README.pdf
```
```bash
pandoc --from=gfm --to=pdf -o README.pdf README.md
```
#### Gem path
```hash
export GEM_HOME=$HOME/.gem
path=("$GEM_HOME/bin" $path)
```
#### QEMU - port forwarding
```bash
qemu-system-i386 -net nic,model=rtl8139 \
-net user,hostfwd=tcp::3389-:3389,hostfwd=tcp::443-:443,hostfwd=tcp::992-:992
```
#### SQL using regex
Add a check constraint to the `id` column to enforce alphanumeric strings of exactly 5 characters long
```sql
ALTER TABLE short_urls ADD CONSTRAINT id CHECK (id ~ '^[a-zA-Z0-9]{5}$');
```
#### Console font size
Edit file &rarr; `/etc/default/console-setup`
```bash
dpkg-reconfigure -plow console-setup
```
#### Redirect errors to null device
find / 2>/dev/null
#### Installing nonfree firmware from repository
I.e: Firmware for nonfree driver for Intel's WIFI cards.
```
https://packages.debian.org/sid/firmware-iwlwifi
```
```bash
apt-get update && apt-get install firmware-linux-nonfree
```
#### Installing nonfree firmware from manufacturer
Search for binary. An example:
[https://www.intel.com/content/www/us/en/support/articles/000005511/wireless.html](https://www.intel.com/content/www/us/en/support/articles/000005511/wireless.html)
Extract and copy like
```bash
cp iwlwifi-cc-a0-46.ucode /lib/firmware
```
### Linux - RAM disk
This might be useful for spead up programs that heavily use disk.
```
mount -t TYPE -o size=SIZE FSTYPE MOUNTPOINT
```
* `TYPE` &rarr; either `tmpfs` or `ramfs`.
* `SIZE` &rarr; ie. `512m`
* `FSTYPE` &rarr; File system type, either `tmpfs`, `ramfs`, `ext4`, etc.
To make this setting persistent you might want to add to `/etc/fstab` fallowing line
```plain
tmpfs /mnt/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size=1024M 0 0
```
#### fstab
Use 'blkid' to print the universally unique identifiers, and can be used in fstab file like
```
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=1a38b8ca-e1f5-45e6-bbe8-3abd2775b3a6 / ext4 errors=remount-ro 0 1
/swapfile none swap sw 0 0
/dev/disk/by-uuid/4D3C-4E36 /mnt/4D3C-4E36 auto nosuid,nodev,nofail,x-gvfs-show 0 0
UUID=e21eebe4-471a-4375-8c4c-618b3733a940 /home ext4 nodev,nosuid 0 2
```
### Linux - Mount disk from `qcow2` image
Step 1 - Enable NBD on the Host
```bash
modprobe nbd max_part=8
```
Step 2 - Connect the QCOW2 as network block device
```bash
qemu-nbd --connect=/dev/nbd0 /var/lib/vz/images/100/vm-100-disk-1.qcow2
```
Step 3 - Find The Virtual Machine Partitions
```bash
fdisk /dev/nbd0 -l
```
Step 4 - Mount the partition from the VM
```bash
mount /dev/nbd0p1 /mnt/somepoint/
```
Step 5 - After you done, unmount and disconnect
```bash
umount /mnt/somepoint/
qemu-nbd --disconnect /dev/nbd0
rmmod nbd
```
### Ubuntu - Power management
To make Ubuntu do nothing when laptop lid is closed:
From For 13.10 onwards:
Open the `/etc/systemd/logind.conf` file in a text editor as root, for example:
```bash
sudo -H gedit /etc/systemd/logind.conf
```
If `HandleLidSwitch` is not set to ignore then change it:
```bash
HandleLidSwitch=ignore
```
Other settings that the action can be ignored: `HandleLidSwitchExternalPower`, `HandleLidSwitchDocked`, `IdleAction`.
Restart the systemd daemon (be aware that this command will log you out):
```bash
sudo systemctl restart systemd-logind
```
or, from 15.04 onwards:
```bash
sudo service systemd-logind restart
```
### Chroot environment of Debian sid
Install Bootstrap
```bash
sudo apt install debootstrap
```
Create a directory that you want to use for the base system (_chroot-debian_ in this case)
```bash
mkdir chroot-debian
```
Create a base system
```bash
sudo debootstrap sid chroot-debian http://deb.debian.org/debian
```
Valid names `sid`, `stable` or any debian code name
Mount  filesystems
```bash
sudo mount -o bind /dev chroot-debian/dev
sudo mount -t sysfs none chroot-debian/sys
sudo mount -o bind /proc chroot-debian/proc
```
Optionally, copy DNS resolver configuration.
```
sudo cp /etc/resolv.conf /path/to/chroot-env/etc/resolv.conf
```
Start chrooting
```bash
sudo chroot chroot-debian /bin/bash
```
Once done, exit the session and unmount
```bash
sudo umount chroot-debian/dev chroot-debian/proc
```
#### Pass variables to chrooted environment
```bash
chroot ./ env -i PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
```
# Allowing user to run a command as root
```shell
sudo visudo
```
```
artur ALL=(ALL) chroot /path/to/chroot-env
```
#### Nginx - serving files setup DAV
Full version with 3rd party extensions
```
apt install nginx-full nginx-extras
```
```
location / {
index nonextistent;
autoindex on;
autoindex_format json;
}
location /restricted {
fancyindex on;
fancyindex_exact_size off;
auth_basic "Restricted";
auth_basic_user_file "/etc/nginx/.htpasswd";
}
location /dropbox {
index nonextistent;
autoindex on;
autoindex_format json;
dav_methods PUT DELETE MKCOL COPY MOVE;
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
dav_access user:rw group:r all:r;
# client_max_body_size 0;
create_full_put_path on;
client_body_temp_path /tmp/;
limit_except GET PROPFIND OPTIONS HEAD {
auth_basic "Restricted";
auth_basic_user_file "/etc/nginx/.htpasswd";
}
        # auth_pam "Restricted";
        # auth_pam_service_name "common-auth";
}
```
Create password
``` bash
echo -n 'sammy:' >> /etc/nginx/.htpasswd
openssl passwd -apr1 >> /etc/nginx/.htpasswd
```
Another method to set the password
```bash
htpasswd -c /etc/nginx/.htpasswd sammy
htpasswd /etc/nginx/.htpasswd another_user
```
**UI Client `Cyberduck`**
#### Backing up the entire OS
```
sudo rsync -aAXHv / --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} /mnt
```
Python
```
install python3-full
```
### Check battery
```bash
upower -i /org/freedesktop/UPower/devices/battery_BAT0
upower -i `upower -e | grep 'BAT'`
upower -i $(upower -e | grep BAT) | grep --color=never -E "state|to\ full|to\ empty|percentage"
```
Battery capacity
```bash
cat /sys/class/power_supply/BAT0/capacity
```
`apt install acpi`
acpi -V
acpi -t
Watch the status for example:
```
watch --interval=5 acpi -V
```
### How to scan open ports
```
nmap -sT -p- 10.10.8.8
nmap -p 80 127.0.0.1
```
### Remove non ASCII characters form the file
```bash
sed 's/[^[:print:]\t]//g' script.sh > cleaned_script.sh
```
## Network Manager
Check Status
```
pacman -S networkmanager
systemctl status NetworkManager
```
```bash
nmcli dev status
nmcli radio wifi
```
```bash
nmcli radio wifi on
```
```bash
nmcli dev wifi list
```
```bash
nmcli dev wifi connect network-ssid
```
```bash
nmcli dev wifi connect network-ssid password "network-password"
# with password promot
nmcli dev wifi connect network-ssid password "network-password"
```
```
nmcli con show
```
```
nmcli con down ssid/uuid
nmcli con up ssid/uuid
```
```
ip link set eno1 up
```
### DHCP Client
```
pacman -S dhclient dhcpcd
```
Turn dchp on for the interface
```
dhclient eth0 -v
```
### Create file
```bash
cat > filename <<- "EOF"
file contents
more contents
EOF
```
### Get data about file include number of links
```bash
stat f1
```
### File decryption
```bash
openssl aes256 -md sha256 -d -in file.enc.zip -out file.zip -pass pass:"<password>"
```
### Base64
```bash
openssl base64 -in qrcode.png -out qrcode.png.base64
openssl base64 -in qrcode.png
```
### tar.xz
```
tar -xJf file.tar.xz -C destination
```
## Execute command
Execute `ls` for each each object in current directory that starts from `D` or `M`
```
ls {D*,M*}
```
Utworzenie dwóch katalogów `test_a`, `test_b`
```
mkdir test_{a,b}
```
### copy content of directory and merge it. Dereference links
```
cp -LTr /form/ .
```
## JSON Linux apis
```
tree -J
ls -l | jq -R -s -c 'split("\n")[:-1]'
```
### List dependencies
```bash
pacman -Sy lld
llvm-nm
```
### Find location of executable
```
type -a python
```
### Reload each file save
```bash
brew install fswatch
fswatch -o . --exclude "\.build.*$" | xargs -n1 -I{} your-command
```
## Add capabilities
allow all to open 443 port
```bash
sudo setcap 'cap_net_bind_service=+ep' ./service
```
# Test speed of the drive
```
sudo hdparam -t --direct /dev/mmcblk0
```

12
utils/regex.md Normal file
View file

@ -0,0 +1,12 @@
---
layout: default
title: Regex - notes
---
How to match “any character” in the regular expression
- `.` &rarr; any char except newline
- `\.` &rarr; the actual dot character
- `.?` = `.{0,1}` &rarr; match any char except newline zero or one times
- `.*` = `.{0,}` &rarr; match any char except newline zero or more times
- `.+` = `.{1,}` &rarr; match any char except newline one or more times

372
utils/vim.md Normal file
View file

@ -0,0 +1,372 @@
---
layout: default
title: Vim notes
categories: software
---
#### Symbols and meanings
- `%` &rarr; current file. An example: `:so %` &rarr; Source the current file
- `$` &rarr; end of line
- `.` &rarr; Current line An example: `:.!sh` &rarr; Pipe current line to `sh` and replace it with the output
Entering `!!` in normal mode is translated to `:.!` I. e. Typing `!!date` in normal mode replaces current line with the date.
#### Tips
- `:e[dit]` &rarr; Edit the current file. This is useful to re-edit the current file, when it has been changed outside of Vim. `:e!` Force reload file
- `:help index` &rarr; Get all default mappings
#### Navigation
- `h` `j` `k` `l` &rarr; left, down, up, right
- `*` &rarr; Next whole word under cursor (previous `#`)
- `e` &rarr; Forward to the end of word. `E` can contain punctuation
- `w` &rarr; Move forward to the beginning of a word. `W` Same as `w`, but special characters are treated as part of a word.
- `b` &rarr; Works as `w`, but backwards
- `{`,`}` &rarr; Jump by paragraphs
- `(`,`)` &rarr; Jump by sentences
- `G` &rarr; Jump to the end of the file
- `1G` &rarr; Jump to the beginning of the file (same as `gg`)
- `50G` &rarr; Jump to line 50
- `0` &rarr; Beginning of line
- `_` or `^` &rarr; first non-blank character of the line
- `g_` &rarr; last non-blank character of the line
- `fX` &rarr; next character `X`. `FX` previous. `;` repeat , `,` repeat in reverse
- `tX` &rarr; tili next `X` (similar to above, but the cursor is before `X`)
- `H` &rarr; Jump to the top of the screen
- `M` &rarr; Jump to the middle of the screen
- `L` &rarr; Jump to the bottom of the screen
#### Scrolling
* `10 <PageUp>` or `10<CTRL-B>` &rarr; Move 10 pages up
* `5 <PageDown>` or `5<CTRL-F>` &rarr; Move 5 pages down.
- `zz` &rarr; scroll the line with the cursor to the center of the screen
- `zt` &rarr; to the top
- `zb` &rarr; to the bottom
### Terminal buffers
- `:te[rm[inal]] command`
- `:b#` switch buffer
- `:ls` list buffers
- `:buff 1` or `:b1` switch to buffer 1
### List of the commands
Common meaning of letters in the commands
- `w` &rarr; word
- `i` &rarr; inner
| Command | |
| ---: | :--- |
| `dd` | Delete one line |
| `d` | Delete selection |
| `x` | Delete character under cursor |
| `d+` | Delete 2 lines |
| `:%d` or :`1,$d` | Delete the whole of the file |
| `dw`, `diw` | Delete what that the cursor is over |
| `di(` | Delete inner brackets. `da(` &rarr; including brackets |
| `:r[ead] !date` | Execute commend and put content into editor |
| `.` | Repeat the last operation |
| `gU` | Uppercase the selection, `gu` &rarr; lower |
| `%` | Jump to matching bracket `{ }` `[ ]` `( )` |
| `:%!column -t` | Put text in columns |
| `:%!sort` | Sort the whole file |
| `:'<,'>!grep text` | Keep lines that contains `text` |
| `:'<,'>!sort` | Sort selected lines |
| `:eariler 1m` | State from the 1 min before |
| `ga` | Display hex, ascii value of character under cursor |
| `g8 ` | Display hex value of utf-8 character under cursor |
| `ciw` | Change inner word |
| `yiw` | Yank inner word |
| `viwp` | Select word and then replace it with previously yanked text |
| `rX` | replace every character in selection or under cursor with `X` |
| `guiw` | Lower case word |
| `guu` | Lowercase line |
| `gUU` | Uppercase line |
| `=` | Indent the selection |
| `=%` | Indent the current braces |
| `G=gg` | indent entire document |
| `ZZ` | Write current file, if modified, and exit (same as `:wq`) |
| `ZQ` | Quit current file and exit (same as `:q!`) |
| `:so %` | Source current file |
| `@:` | Execute last command again |
#### Status line
```vim
:set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
```
#### Visual Mode
- `V` &rarr; Selection by lines
- `v` &rarr; Selection follows the cursor
- `Ctrl+v` &rarr; Block selection
- When selected block you can applay changes to each line by typing `I` editing and finally pressing `Esc`
#### Enter Insert Mode
- `I` &rarr; At the first non white character of the line
- `i` &rarr; On the left of the cursor
- `A` &rarr; At the very end of the line
- `a` &rarr; On the right of the cursor
- `c` &rarr; Delete selection and enter insert mode
- `o` &rarr; Create new line below and enter insert mode
- `O` &rarr; Create new line above and enter insert mode
#### Split the editor
- `:sp <filename>` &rarr; Vertically
- `:vs <filename>` &rarr; Horizontally
- `:set splitbelow`, `:set splitright`
#### Markers
- `:marks` &rarr; list of marks
- `ma` &rarr; set current position for mark `a`
- `` `a`` &rarr; jump to the cursor position of mark `a`
- `'a` &rarr; jump to the beginning of a line of a mark `a`
- ``y`a`` &rarr; yank text to position of mark `a`
* ``` `` ``` &rarr; Return to the cursor position before the latest jump
* `` `.`` &rarr; Jump to the last changed line.
### Recording macros
1. `qa` &rarr; Start recording macro under letter `a`
2. `q` &rarr; Stop recording
3. `@a` &rarr; Play the macro saved under letter a
4. `@@` &rarr; Play the last macro
#### Searching
- `:%s/Plug.*$//` &rarr; Search and delete all lines that starts from Plug
- `:%s/foo/bar/gc` &rarr; Replace all occurrence of foo by bar with confirmation
- `'<,'>:s/find/replacewith/` Replace selection
- `/pattern` &rarr; search for pattern then enter and `n` next `N` previous match
- `?pattern` &rarr; search backward for pattern
### Registers
- `:reg` &rarr; print all registers
- `"ap` &rarr; paste the register `a` , if the macro is recorded then it will paste it
- `"xy` &rarr; yank into register `x`
- `:let @a = "kkll"` &rarr; set a macro from the command mode
- `:let @A='i'` &rarr; append to register `a`
- `:%normal @a` &rarr; execute the macro on all lines of the current file
- `:'<,'>normal @a` &rarr; execute the macro on a visually selected lines
- `:10,20 normal @a` &rarr; execute the macro for lines from 10 to 20
- `:g/pattern/ normal @a` &rarr; Search for pattern and execute macro for it
#### Functions - An example
Function definition
```vim
function! CalculateAge()
normal 03wdei^R=2012-^R"^M^[0j
endfunction
```
Key banding to function
```vim
nnoremap <leader>a :call CalculateAge()<CR>
```
Preloading vim with macros like
```vim
let @a='03wdei^R=2012-^R"^M^[0j'
```
Call function from the command mode
```
:call CalculateAge()
```
#### Configuration
The config file is located at `.config/nvim/init.vim`
```vim
if empty(glob('~/.local/share/nvim/site/autoload/plug.vim'))
silent !curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs
\ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif
call plug#begin('~/.vim/plugged')
Plug 'junegunn/fzf'
Plug 'neovim/nvim-lspconfig'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'vim-syntastic/syntastic'
Plug 'tokorom/syntastic-swiftlint.vim'
call plug#end()
```
- `set relativenumber`
- `set encoding=utf-8`
- `syntax on`
- `map za :FZF<CR>` &rarr; fuzzy finder over `za`
Indentation setup
- `set tabstop=2 shiftwidth=2 expandtab`
- `filetype plugin indent on`
```vim
let g:syntastic_swift_checkers = ['swiftlint', 'swiftpm']
lua << EOF
local lspconfig = require('lspconfig')
lspconfig.sourcekit.setup{}
EOF
```
#### Rename current file
```vim
function! RenameFile()
let old_name = expand('%')
let new_name = input('New file name: ', expand('%'), 'file')
if new_name != '' && new_name != old_name
exec ':saveas ' . new_name
exec ':silent !rm ' . old_name
exec ':bd ' . old_file
redraw!
endif
endfunction
map <leader>n :call RenameFile()<cr>
```
<!--
### Navigation in Vimr
- jump to the next empty line (the next paragraph)`}`
* Recording macros
* `"xp` pastes the contents of the register `x`.
* `~ ` : invert case (upper->lower; lower->upper) of current character
* `gf ` : open file name under cursor (SUPER)
* `ggg?G` : rot13 whole file
* `xp` : swap next two characters around
* `CTRL-A,CTRL-X` : increment, decrement next number on same line as the cursor
* `CTRL-R=5*5` : insert 25 into text
* `'.` : jump to last modification line (SUPER)
* *`.* : jump to exact spot in last modification line
* `<C-O>` : retrace your movements in file (backward)
* `<C-I>` : retrace your movements in file (forward)
* `:ju(mps)` : list of your movements {{help|jump-motions}}
:history : list of all your commands
Sorting with external sort
:%!sort -u : contents of the current file is sorted and only unique lines are kept
:'v,'w!sort : sort from line marked v thru lines marked w
:g/^$/;,/^$/-1!sort : sort each block (note the crucial ;)
!1} sort : sorts paragraph; this is issued from normal mode!)
:wn : write file and move to next (SUPER)
:bd : remove file from buffer list (SUPER)
:sav php.html : Save current file as php.html and "move" to php.html
:w /some/path/%:r : save file in another directory, but with the same name
:e # : edit alternative file
:args : display argument list
:n : next file in argument list
:prev : previous file in argument list
:rew : rewind to first file in argument list
:ls : display buffer list
:bn : next buffer
:bp : previous buffer
:brew : rewind to first buffer in buffer list
:tabe : open new tab page (Ctrl-PgUp, Ctrl-PgDown for next/previous tab)
:tabm n : move tab to position n (0=leftmost position)
# editing a register/recording
"ap
<you can now see register contents, edit as required>
"add
@a
Ctrl-D move half-page down
Ctrl-U move half-page up
Ctrl-B page up
Ctrl-F page down
Ctrl-O jump to last (older) cursor position
Ctrl-I jump to next cursor position (after Ctrl-O)
Ctrl-Y move view pane up
Ctrl-E move view pane down
n next matching search pattern
N previous matching search pattern
g* next matching search (not whole word) pattern under cursor
g# previous matching search (not whole word) pattern under cursor
de — Delete to the end of the word
^R= — Insert the contents of the special = register, which accepts an expression to evaluate
gUgn - uppercase
gn
n move to the next match
Undo and redo
You can use u to undo the last change. CTRL-R redoes a change that has been undone. U returns the current line to its original state.
You can use g- or g+ to go between text-states.
Search and replace
* `\vpattern` - 'very magic' pattern: non-alphanumeric characters are interpreted as special regex symbols (no escaping needed)
* `n` - repeat search in same direction
* `N` - repeat search in opposite direction
* `:noh` - remove highlighting of search matches
Search in multiple files
* `:vimgrep /pattern/ {file}` - search for pattern in multiple files
* e.g. `:vimgrep /foo/ **/*`
* `:cn` - jump to the next match
* `:cp` - jump to the previous match
* `:copen` - open a window containing the list of matches
folding from selection
`: '<,'>fo`
`:help folding`
set foldmethod=syntax
`set foldlevel=1`
`set foldclose=all`
Sequence forfolding lines `Shift+V:fo`
`:set foldmethod=syntax` intent,
`zo` unfolding
`za` toogle folding
`zf#j` creates a fold from the cursor down # lines.
:CheckHealth
-->