diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 867d379..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.gem -.bundle -.sass-cache -_site -Gemfile.lock diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_base.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_base.scssc new file mode 100644 index 0000000..a4808e6 Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_base.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_dark.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_dark.scssc new file mode 100644 index 0000000..f80ff1d Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_dark.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_fonts.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_fonts.scssc new file mode 100644 index 0000000..70560c6 Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_fonts.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_layout.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_layout.scssc new file mode 100644 index 0000000..3cdc079 Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_layout.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_miscellaneous.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_miscellaneous.scssc new file mode 100644 index 0000000..151eeba Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_miscellaneous.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_post.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_post.scssc new file mode 100644 index 0000000..f6980b9 Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_post.scssc differ diff --git a/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_syntax.scssc b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_syntax.scssc new file mode 100644 index 0000000..c065a9a Binary files /dev/null and b/.sass-cache/86619ff212e9aa14fb08acc717900e7d9b190c3d/_syntax.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_base.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_base.scssc new file mode 100644 index 0000000..1b2cb5b Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_base.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_dark.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_dark.scssc new file mode 100644 index 0000000..0fe9166 Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_dark.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_fonts.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_fonts.scssc new file mode 100644 index 0000000..e927d2e Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_fonts.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_layout.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_layout.scssc new file mode 100644 index 0000000..bb14d25 Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_layout.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_miscellaneous.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_miscellaneous.scssc new file mode 100644 index 0000000..a216598 Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_miscellaneous.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_post.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_post.scssc new file mode 100644 index 0000000..cb9a37a Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_post.scssc differ diff --git a/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_syntax.scssc b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_syntax.scssc new file mode 100644 index 0000000..b279a5b Binary files /dev/null and b/.sass-cache/a28b70ffa7da60916248ddaa0e5956aa0b4fa593/_syntax.scssc differ diff --git a/.sass-cache/d8f8e2d7794ba233dc975c25d0b156d5405bb87a/main.scssc b/.sass-cache/d8f8e2d7794ba233dc975c25d0b156d5405bb87a/main.scssc new file mode 100644 index 0000000..6ae6f88 Binary files /dev/null and b/.sass-cache/d8f8e2d7794ba233dc975c25d0b156d5405bb87a/main.scssc differ diff --git a/Gemfile b/Gemfile index bb94df8..f540ee0 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,34 @@ -# frozen_string_literal: true - source "https://rubygems.org" -gemspec + +# Hello! This is where you manage which Jekyll version is used to run. +# When you want to use a different version, change it below, save the +# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: +# +# bundle exec jekyll serve +# +# This will help ensure the proper Jekyll version is running. +# Happy Jekylling! +gem "jekyll", "~> 3.8.3" + +# This is the default theme for new Jekyll sites. You may change this to anything you like. +# gem "minima", "~> 2.0" + +# If you want to use GitHub Pages, remove the "gem "jekyll"" above and +# uncomment the line below. To upgrade, run `bundle update github-pages`. +# gem "github-pages", group: :jekyll_plugins + +# If you have any plugins, put them here! +group :jekyll_plugins do + gem 'jekyll-feed', '~> 0.11.0' + gem 'jekyll-sitemap' + gem 'jekyll-sass-converter', '~> 1.5', '>= 1.5.2' + gem 'jekyll-compose' + gem 'jekyll-postfiles', '~> 3.0' + gem 'rouge', '3.3.0' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +# gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +# Performance-booster for watching directories on Windows +# gem "wdm", "~> 0.1.0" if Gem.win_platform? diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..3c26de9 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,75 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + colorator (1.1.0) + concurrent-ruby (1.1.5) + em-websocket (0.5.1) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.6.0) + eventmachine (1.2.7) + ffi (1.12.1) + forwardable-extended (2.6.0) + http_parser.rb (0.6.0) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + jekyll (3.8.6) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 0.7) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (~> 1.14) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + jekyll-compose (0.12.0) + jekyll (>= 3.7, < 5.0) + jekyll-feed (0.11.0) + jekyll (~> 3.3) + jekyll-postfiles (3.1.0) + jekyll (>= 3.8.6, < 5) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-sitemap (1.4.0) + jekyll (>= 3.7, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + kramdown (1.17.0) + liquid (4.0.3) + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.3.6) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.3) + rb-fsevent (0.10.3) + rb-inotify (0.10.1) + ffi (~> 1.0) + rouge (3.3.0) + safe_yaml (1.0.5) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + +PLATFORMS + ruby + +DEPENDENCIES + jekyll (~> 3.8.3) + jekyll-compose + jekyll-feed (~> 0.11.0) + jekyll-postfiles (~> 3.0) + jekyll-sass-converter (~> 1.5, >= 1.5.2) + jekyll-sitemap + rouge (= 3.3.0) + +BUNDLED WITH + 2.0.2 diff --git a/LICENSE.txt b/LICENSE similarity index 87% rename from LICENSE.txt rename to LICENSE index ce9be25..88aa011 100644 --- a/LICENSE.txt +++ b/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +MIT License -Copyright (c) 2019 piharpi +Copyright (c) 2019 Mahendrata Harpi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 4e78a35..9a1ea94 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,24 @@ -# bangsring - -Welcome to your new Jekyll theme! In this directory, you'll find the files you need to be able to package up your theme into a gem. Put your layouts in `_layouts`, your includes in `_includes`, your sass files in `_sass` and any other assets in `assets`. - -To experiment with this code, add some sample content and run `bundle exec jekyll serve` – this directory is setup just like a Jekyll site! - -TODO: Delete this and the text above, and describe your gem +# Klisé +Klisé is minimalist Jekyll theme for running a personal site and blog running on Jekyll, Ruby, Netlify, Now.sh. ## Installation -Add this line to your Jekyll site's `Gemfile`: +Run local server: -```ruby -gem "bangsring" +```bash +git clone https://github.com/piharpi/jekyll-klise.git +cd jekyll-klise +bundle install +bundel exec jekyll serve ``` -And add this line to your Jekyll site's `_config.yml`: - -```yaml -theme: bangsring -``` - -And then execute: - - $ bundle - -Or install it yourself as: - - $ gem install bangsring - -## Usage - -TODO: Write usage instructions here. Describe your available layouts, includes, sass and/or assets. +Navigate to `localhost:4000`. ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/hello. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. - -## Development - -To set up your environment to develop this theme, run `bundle install`. - -Your theme is setup just like a normal Jekyll site! To test your theme, run `bundle exec jekyll serve` and open your browser at `http://localhost:4000`. This starts a Jekyll server using your theme. Add pages, documents, data, etc. like normal to test your theme's contents. As you make modifications to your theme and to your content, your site will regenerate and you should see the changes in the browser after a refresh, just like normal. - -When your theme is released, only the files in `_layouts`, `_includes`, `_sass` and `assets` tracked with Git will be bundled. -To add a custom directory to your theme-gem, please edit the regexp in `bangsring.gemspec` accordingly. +If you see any typos or formatting errors in a post, or any other issue that needs to be addressed, please do not hesitate to open a pull request and fix it! ## License -The theme is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). - +This project is open source and available under the [MIT License](LICENSE). diff --git a/_config.yml b/_config.yml index 69d765d..4125455 100644 --- a/_config.yml +++ b/_config.yml @@ -1,25 +1,30 @@ # Site settings -title: Mahendrata Harpi 🇮🇩 +title: Klise Theme description: >- - this blog is place where i'm writing about web technology - what i like and as journal for documentation things what i learned, meet me @github. + He's writing in Bahasa about web technology and experience as a journal + for documentation things that he learned, meet him @github. lang: en-US timezone: Asia/Jakarta -icon: "favicon.ico" +image: assets/img/ogp.png # This image used for Open Graph more info https://ogp.me/ +repo: https://github.com/piharpi/mahendrata.now.sh +mode: dark # default theme "dark" | "light" -# User settings +# Profile settings author: - name: Mahendrata Harpi - username: piharpi - email: justharpi@gmail.com - avatar: "/assets/img/avatar.jpg" + name: Klisé Theme + bio: >- + He's writing in Bahasa about web technology and experience as a journal + for documentation things that he learned, meet him @github. + username: username + email: your-email@email.com + avatar: /assets/img/avatar.jpg # Url settings -url: https://piharpi.com -baseurl: "" -permalink: blog/:categories/:title/ -google_analytics: UA-105586262-1 -fb_appid: "" +url: "https://klise.now.sh" +baseurl: +permalink: /:title/ +google_analytics: +fb_appid: # Collection setting collections: @@ -67,7 +72,6 @@ exclude: - CHANGELOG.md - README.md - node_modules - - bangsring.gemspec - CODE_OF_CONDUCT.md # Plugins @@ -75,3 +79,4 @@ plugins: - jekyll-feed - jekyll-sass-converter - jekyll-sitemap + - jekyll-postfiles diff --git a/_data/menus.yml b/_data/menus.yml index cfe6a56..40eb273 100644 --- a/_data/menus.yml +++ b/_data/menus.yml @@ -1,8 +1,16 @@ -- title: Home +- title: home url: / + external: false -- title: About +- title: about url: /about/ + external: false -- title: RSS - url: /feed.xml/ +- title: notes + url: /notes/ + external: false # set true if you using external link, see bellow + +# Example: +# - title: github +# url: https://github.com/piharpi/jekyll-klise +# external: true diff --git a/_includes/anchor_headings.html b/_includes/anchor_headings.html new file mode 100644 index 0000000..7a56b16 --- /dev/null +++ b/_includes/anchor_headings.html @@ -0,0 +1,105 @@ +{% capture headingsWorkspace %} + {% comment %} + Version 1.0.4 + https://github.com/allejo/jekyll-anchor-headings + + "Be the pull request you wish to see in the world." ~Ben Balter + + Usage: + {% include anchor_headings.html html=content %} + + Parameters: + * html (string) - the HTML of compiled markdown generated by kramdown in Jekyll + + Optional Parameters: + * beforeHeading (bool) : false - Set to true if the anchor should be placed _before_ the heading's content + * anchorAttrs (string) : '' - Any custom HTML attributes that will be added to the `` tag; you may NOT use `href`, `class` or `title` + * anchorBody (string) : '' - The content that will be placed inside the anchor; the `%heading%` placeholder is available + * anchorClass (string) : '' - The class(es) that will be used for each anchor. Separate multiple classes with a space + * anchorTitle (string) : '' - The `title` attribute that will be used for anchors + * h_min (int) : 1 - The minimum header level to build an anchor for; any header lower than this value will be ignored + * h_max (int) : 6 - The maximum header level to build an anchor for; any header greater than this value will be ignored + * bodyPrefix (string) : '' - Anything that should be inserted inside of the heading tag _before_ its anchor and content + * bodySuffix (string) : '' - Anything that should be inserted inside of the heading tag _after_ its anchor and content + + Output: + The original HTML with the addition of anchors inside of all of the h1-h6 headings. + {% endcomment %} + + {% assign minHeader = include.h_min | default: 1 %} + {% assign maxHeader = include.h_max | default: 6 %} + {% assign beforeHeading = include.beforeHeading %} + {% assign nodes = include.html | split: ' + {% if headerLevel == 0 %} + {% if nextChar != '<' and nextChar != '' %} + {% capture node %}' | first }}>{% endcapture %} + {% assign header = _workspace[0] | replace: _hAttrToStrip, '' %} + + + {% capture anchor %}{% endcapture %} + + {% if html_id and headerLevel >= minHeader and headerLevel <= maxHeader %} + {% capture anchor %}href="#{{ html_id }}"{% endcapture %} + + {% if include.anchorClass %} + {% capture anchor %}{{ anchor }} class="{{ include.anchorClass }}"{% endcapture %} + {% endif %} + + {% if include.anchorTitle %} + {% capture anchor %}{{ anchor }} title="{{ include.anchorTitle | replace: '%heading%', header }}"{% endcapture %} + {% endif %} + + {% if include.anchorAttrs %} + {% capture anchor %}{{ anchor }} {{ include.anchorAttrs }}{% endcapture %} + {% endif %} + + {% capture anchor %}{{ include.anchorBody | replace: '%heading%', header | default: '' }}{% endcapture %} + + + {% if beforeHeading %} + {% capture anchor %}{{ anchor }} {% endcapture %} + {% else %} + {% capture anchor %} {{ anchor }}{% endcapture %} + {% endif %} + {% endif %} + + {% capture new_heading %} + + {{ site.author.username }} +

{{ site.author.name }}

+

{{ site.author.bio }}

+ diff --git a/_includes/comments.html b/_includes/comments.html index e97f140..c1bcb37 100644 --- a/_includes/comments.html +++ b/_includes/comments.html @@ -1 +1,10 @@ - + + diff --git a/_includes/footer.html b/_includes/footer.html index 5a9a8f2..d9a4f7a 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -1,12 +1,16 @@ + diff --git a/_site/about/index.html b/_site/about/index.html new file mode 100644 index 0000000..aeafca9 --- /dev/null +++ b/_site/about/index.html @@ -0,0 +1 @@ + Colophon - Klise Theme

Colophon.

He’s a student from Banyuwangi, living in Jogjakarta. the blog for documentation about his programming 🎒 journey, running on jekyll, hosting on now.sh and using his own theme, he name it klisé, he also loves to learning web technology; but he often forgot, that a reason why him doing the writing.

If you have a question about him or else, just send a letter to him.

You can report if there is an broken link(s) or somethings else.

may u needs ✨
  • your-email@email.com
  • github.com/username
diff --git a/_site/apa-itu-shell/index.html b/_site/apa-itu-shell/index.html new file mode 100644 index 0000000..da4ce53 --- /dev/null +++ b/_site/apa-itu-shell/index.html @@ -0,0 +1,17 @@ + What is a shell? 🐚 adalah kerang ajaib? - Klise Theme

What is a shell? 🐚 adalah kerang ajaib?

Dulu Sebelum adanya GUI cara user berinteraksi dengan komputer menggunakan CLI yaitu mengetik baris perintah pada sebuah antarmuka dalam bentuk baris teks seperti 👇.

installing nginx in ubuntu
Fig 1. Terminal emulator, instalasi package dan check service.

Jika kamu pernah menggunakan unix/linux mungkin pernah menggunakan program diatas, bahkan mungkin setiap hari menggunakannya untuk mengeksekusi suatu perintah melalui terminal emulator.

User[1] tidak bisa secara langsung berkomunikasi dengan sebuah hardware komputer, maka dari itu kita membutuhkan sebuah sistem operasi; Kernel adalah program yang merupakan inti utama dari sistem operasi komputer.

kernel central of operating system
Fig 2. bagan kernel.

Kernel memfasilitasi interaksi antara komponen perangkat keras dan perangkat lunak, berperan untuk menangani permintaan input/ouput dari perangkat lunak, selanjutnya menerjemahkannya ke dalam pemrosesan data untuk diintruksikan ke CPU, sehingga Hardware(cpu, memory, devices) mengerti perintah yang dimaksud dari pengguna.

Ketika kita menginputkan suatu perintah pada terminal emulator, kernel tidak langsung mengerti perintah yang kita ketik, kita membutuhkan suatu interface sebagai perantara menuju kernel yaitu Shell.

shell
Fig 3. bagan komunikasi shell.

Shell adalah sebuah command-line interpreter; program yang berperan sebagai penerjemah perintah yang diinputkan oleh User yang melalui terminal, sehingga perintah tersebut bisa dimengerti oleh si Kernel.

Login shell biasanya ditetapkan oleh local System Administrator ketika pada saat pertama user kamu dibuat, kamu bisa lihat login shell yang sedang kamu gunakan dengan perintah dibawah ini.

$ echo $SHELL
+# atau
+$ echo $0
+

Setiap shell mempunyai default prompt. beberapa shell yang paling umum:

$ (dollar sign)   # sh, ksh, bash
+% (percent sign)  # csh, tcsh
+
Terminologi pada shell prompt

Shell prompt adalah tempat dimana kita menuliskan suatu perintah, berikut adalah terminologinya ini membantu, jika kamu ingin mengetahui bagian-bagianya.

shell
Fig 4. bagian-bagin dari shell prompt.

Dibawah ini salah satu contoh perintah sederhana untuk menampilkan sebuah arsitektur CPU komputer yang sedang saya gunakan.

installing nginx in ubuntu
Fig 5. menampilkan informasi tentang arsitektur CPU.

Dari perintah yang contohkan, ketika user mengetikan suatu inputan perintah di terminal dan menekan ENTER, maka shell akan mengubah perintah user menjadi bahasa yang bisa dipahami oleh kernel, dan Kernel menerjemahkannya ke dalam pemrosesan data untuk diintruksikan ke Hardware sehingga menghasilkan output yg sesuai dengan perintah user.

Shell mempunyai beberapa macam dan turunan, berikut yang paling umum.

shell evolution
Fig 6. evaluasi shell dari tahun ke tahun.

Sedikit penjelasan dari gambar diatas.

  • Bourne shell sh Dikembangkan oleh Stephen Bourne di Bell Labs, yang kala itu sebagai pengganti Thompson shell(diciptakan Ken Thompson), banyak sistem unix-like tetap memiliki /bin/sh—yang mana menjadi symbolic link atau hard link, bahkan ketika shell lain yang digunakan tetap sh adalah sebagai dasarnya, sebagai kompatibilitas perintah.
  • Korn shell ksh Unix shell yang dikembangkan oleh David Korn di Bell Labs, inisialiasi pengembangan ini berdasar pada source code Bourne shell, namun juga memiliki fitur csh dan sh, pengembanganya pun pada saat saya menulis ini pun terus terawat.
  • Bourne again shell bash adalah proyek ini open source GNU project memilki kompatibel dengan sh yang menggabungkan fitur penting dari ksh dan csh, dan menjadi salah satu shell yang paling umum digunakan (umumnya menjadi default shell login Linux dan Apple’s macOS Mojave).
  • Z shell zsh ini mempunyai wadah komunitasnya disebutnya “Oh My Zsh”, plug-in dan theme zsh bisa kita temukan di komunitas ini, saya saat ini menggunakan zsh, shell ini juga menjadi default dari sistem operasi macOS Catalina, yang menggantikan bash.
  • friendly interactive shell fish yah sesuai dengan deskripsi di web nya, menurut saya shell ini fun banget, fitur yang saya sukai dari shell ini autosuggestions, dan konfigurasi yang mudah melalui web based.

Masih banyak yang belum dijelaskan pada tulisan ini jika masih tertarik, baca lebih banyak dan juga komparasinya masing-masing shell.

Jika kamu tertarik untuk mengubah default shell login pada sistem operasi, kamu bisa menginstall dengan cara mengikuti didokumentasi/cara penginstallan dimasing-masing shell disini saya tidak membahas karena distro yang kita pakai mungkin berbeda-beda.

Untuk menjadikan default shell login pada OS bisa menggunakan perintah ini.

# command
+$ sudo chsh [options] [LOGIN]
+
+# contoh penggunaan
+$ sudo chsh -s /user/bin/zsh harpi
+# mengubah default shell user harpi menjadi zsh shell.
+$ reboot
+
+# atau kamu juga bisa mengubah file /etc/passwd dan edit secara manual user shellnya.
+# jika masih bingung manfaatkan perintah man untuk melihat manual page.
+$ man chsh
+

Terakhir untuk tulisan ini, shell memilki berbagai macam, pilihlah shell yang sesuai dengan keinginanmu untuk menunjang produktivitas dan sesuaikan dengan kebutuhan, terlalu banyak plugin dan kebingungan memilih tema itu buruk 😁.

Terimakasih sudah baca, penulis menerima kritik dan saran.

Notes

[1] Manusia yang mengoperasikan dan mengendalikan sistem komputer.

Resources
updated_at 02-02-2020
diff --git a/_site/apa-itu-shell/kernel.png b/_site/apa-itu-shell/kernel.png new file mode 100644 index 0000000..26fb4a6 Binary files /dev/null and b/_site/apa-itu-shell/kernel.png differ diff --git a/_site/apa-itu-shell/photo-1556075798-4825dfaaf498_ixlib=rb-1.2.jpg b/_site/apa-itu-shell/photo-1556075798-4825dfaaf498_ixlib=rb-1.2.jpg new file mode 100644 index 0000000..b5cdec7 Binary files /dev/null and b/_site/apa-itu-shell/photo-1556075798-4825dfaaf498_ixlib=rb-1.2.jpg differ diff --git a/_site/apa-itu-shell/shell.png b/_site/apa-itu-shell/shell.png new file mode 100644 index 0000000..e9c2447 Binary files /dev/null and b/_site/apa-itu-shell/shell.png differ diff --git a/_site/apa-itu-shell/shell_evolution.png b/_site/apa-itu-shell/shell_evolution.png new file mode 100644 index 0000000..a712bed Binary files /dev/null and b/_site/apa-itu-shell/shell_evolution.png differ diff --git a/_site/apa-itu-shell/term_shell_prompt.png b/_site/apa-itu-shell/term_shell_prompt.png new file mode 100644 index 0000000..d0ffb8b Binary files /dev/null and b/_site/apa-itu-shell/term_shell_prompt.png differ diff --git a/_site/apa-itu-shell/terminal_lscpu.gif b/_site/apa-itu-shell/terminal_lscpu.gif new file mode 100644 index 0000000..6916f19 Binary files /dev/null and b/_site/apa-itu-shell/terminal_lscpu.gif differ diff --git a/_site/apa-itu-shell/terminal_nginx.gif b/_site/apa-itu-shell/terminal_nginx.gif new file mode 100644 index 0000000..e81039e Binary files /dev/null and b/_site/apa-itu-shell/terminal_nginx.gif differ diff --git a/_site/apa-itu-shell/weird_guyyy.gif b/_site/apa-itu-shell/weird_guyyy.gif new file mode 100644 index 0000000..4c44a16 Binary files /dev/null and b/_site/apa-itu-shell/weird_guyyy.gif differ diff --git a/_site/assets/css/style.css b/_site/assets/css/style.css new file mode 100644 index 0000000..a860441 --- /dev/null +++ b/_site/assets/css/style.css @@ -0,0 +1 @@ +@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:400;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxK.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:700;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Roboto";font-style:normal;font-weight:300;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7qsDJT9g.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7jsDJT9g.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7rsDJT9g.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7ksDJT9g.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7osDJT9g.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7psDJT9g.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Sans Pro";font-style:italic;font-weight:400;font-display:swap;src:local("Source Sans Pro Italic"),local("SourceSansPro-Italic"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK1dSBYKcSV-LCoeQqfX1RYOo3qPZ7nsDI.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNa7lqDY.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qPK7lqDY.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNK7lqDY.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qO67lqDY.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qN67lqDY.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+1EA0-1EF9,U+20AB}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qNq7lqDY.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Source Sans Pro";font-style:normal;font-weight:400;font-display:swap;src:local("Source Sans Pro Regular"),local("SourceSansPro-Regular"),url(https://fonts.gstatic.com/s/sourcesanspro/v13/6xK3dSBYKcSV-LCoeQqfX1RYOo3qOK7l.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsvSkLBP.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsLSkLBP.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsrSkLBP.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsXSkLBP.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsjSkLBP.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:400;font-display:swap;src:local("Ubuntu Mono Italic"),local("UbuntuMono-Italic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOhCneDtsqEr0keqCMhbCc_OsbSkA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hYJufkO1.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hYtufkO1.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hYNufkO1.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hYxufkO1.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hYFufkO1.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Ubuntu Mono";font-style:italic;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold Italic"),local("UbuntuMono-BoldItalic"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO8CneDtsqEr0keqCMhbCc_Mn33hY9ufg.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc3CsTKlA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc-CsTKlA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc2CsTKlA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc5CsTKlA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc0CsTKlA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:400;font-display:swap;src:local("Ubuntu Mono"),local("UbuntuMono-Regular"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFOjCneDtsqEr0keqCMhbCc6CsQ.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9H4tY12eg.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9HxtY12eg.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9H5tY12eg.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9H2tY12eg.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9H7tY12eg.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Ubuntu Mono";font-style:normal;font-weight:700;font-display:swap;src:local("Ubuntu Mono Bold"),local("UbuntuMono-Bold"),url(https://fonts.gstatic.com/s/ubuntumono/v9/KFO-CneDtsqEr0keqCMhbC-BL9H1tY0.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}html{overflow-x:hidden;width:100%}body,h1,h2,h3,h4,h5,h6,p,blockquote,pre,hr,dl,dd,ol,ul,figure{margin:0;padding:0}body{min-height:100vh;overflow-x:hidden;position:relative;color:#434648;background-color:#fff;font:400 16px/1.85 Roboto,sans-serif;-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-webkit-font-feature-settings:"kern" 1;-moz-font-feature-settings:"kern" 1;-o-font-feature-settings:"kern" 1;font-feature-settings:"kern" 1;font-kerning:normal;box-sizing:border-box}h1,h2,h3,h4,h5,h6,p,blockquote,pre,ul,ol,dl,figure{margin-top:10px;margin-bottom:10px}strong,b{font-weight:700;color:#0d122b}hr{border-bottom:0;border-style:solid;border-color:#ececec}kbd{-moz-border-radius:3px;-webkit-border-radius:3px;border:1px solid #ececec;border-radius:2px;color:#0d122b;display:inline-block;font-size:14px;line-height:1.4;font-family:Consolas,monospace;margin:0 0.1em;font-weight:700;padding:0.01em 0.4em;text-shadow:0 1px 0 #fff}img{max-width:100%;vertical-align:middle;-webkit-user-drag:none;margin:0 auto;text-align:center}figure{position:relative}figure>img{display:block;position:relative}figcaption{font-size:13px;text-align:center}ul{list-style:none}ul li{display:list-item;text-align:-webkit-match-parent}ul li::before{content:"\03BB";display:inline-block;width:1em;position:relative;margin-left:-1em;font-weight:700}ol{list-style:none;counter-reset:li}ol li{position:relative;counter-increment:li}ol li::before{content:counter(li);display:inline-block;width:1em;margin-right:0.5em;margin-left:-1.6em;text-align:right;direction:rtl;font-weight:700;font-size:14px}ul,ol{margin-top:0;margin-left:30px}li{padding-bottom:1px;padding-top:1px}li:before{color:#0d122b}li>ul,li>ol{margin-bottom:2px;margin-top:0}h1,h2,h3,h4,h5,h6{color:#0d122b;font-weight:700}h1+ul,h1+ol,h2+ul,h2+ol,h3+ul,h3+ol,h4+ul,h4+ol,h5+ul,h5+ol,h6+ul,h6+ol{margin-top:10px}h1>a,h2>a,h3>a,h4>a,h5>a,h6>a{text-decoration:none;border:none}h1>a:hover,h2>a:hover,h3>a:hover,h4>a:hover,h5>a:hover,h6>a:hover{text-decoration:none;border:none}a{color:inherit;text-decoration-color:#d2c7c7}a:hover{color:#003fff}a:focus{outline:3px solid rgba(0,54,199,0.6);outline-offset:2px}del{color:inherit}em{color:inherit}blockquote{color:#6b7886;font-style:italic;text-align:center;opacity:0.9;border-top:1px solid #ececec;border-bottom:1px solid #ececec;padding:10px;margin-left:10px;margin-right:10px;font-size:1em}blockquote>:last-child{margin-bottom:0;margin-top:0}.wrapper{max-width:-webkit-calc(720px - (30px * 2));max-width:calc(720px - (30px * 2));position:relative;margin-right:auto;margin-left:auto;padding-right:30px;padding-left:30px}@media screen and (max-width: 768px){.wrapper{max-width:-webkit-calc(720px - (30px));max-width:calc(720px - (30px));padding-right:20px;padding-left:20px}}u{text-decoration-color:#d2c7c7}small{font-size:14px}sup{border-radius:10%;top:-3px;left:2px;font-size:small;position:relative;margin-right:2px}table{margin:0 auto;border-collapse:collapse;background:#fff;font-size:14px}table th{font-weight:700;background:#f5f5f5;text-align:left;border-bottom:2px solid #f5f5f5}table th,table td,table tr{border:1px solid #ececec;padding:4px 8px}.wrapper:after,.navbar:after,.post-item:after{content:"";display:table;clear:both}mark,::selection{background:#fffba0;color:#0d122b}.gist table{border:0}.gist table tr,.gist table td{border:0}.navbar{height:auto;max-width:calc(890px - (30px * 2));max-width:-webkit-calc(890px - (30px * 2));position:relative;margin-right:auto;margin-left:auto;border-bottom:1px solid #ececec;padding:15px 30px}.menu{user-select:none;-ms-user-select:none;-webkit-user-select:none}.menu a#mood{float:left;left:8px;top:6px;position:relative;clear:both;-webkit-transform:scale(1, 1);transform:scale(1, 1);opacity:0.7}.menu a#mood:hover{cursor:pointer;opacity:1}.menu a#mood:active{-webkit-transform:scale(0.9, 0.9);transform:scale(0.9, 0.9)}.menu a#mood .mood-moon{display:block}.menu a#mood .mood-moon line{stroke:#0d122b;fill:none}.menu a#mood .mood-moon circle{fill:#0d122b;stroke:#0d122b}.menu a#mood .mood-sunny{display:none}.menu a#mood .mood-sunny line{stroke:#f0f8ff;fill:none}.menu a#mood .mood-sunny circle{fill:none;stroke:#f0f8ff}.menu .trigger{float:right}.menu .menu-trigger{display:none}.menu .menu-icon{display:none}.menu .menu-link{color:#0d122b;line-height:2.25;text-decoration:none;padding:5px 8px;opacity:0.7;letter-spacing:0.3px}.menu .menu-link:hover{opacity:1}.menu .menu-link:not(:last-child){margin-right:5px}.menu .menu-link.rss{position:relative;bottom:-3px;outline:none}@media screen and (max-width: 768px){.menu .menu-link{opacity:0.8}}.menu .menu-link.active{opacity:1;font-weight:600}@media screen and (max-width: 768px){.menu{position:fixed;top:0;left:0;right:0;z-index:2;text-align:center;height:50px;background-color:#fff;border-bottom:1px solid #ececec}.menu a#mood{left:10px;top:12px}.menu .menu-icon{display:block;position:absolute;right:0;width:50px;height:23px;line-height:0;padding-top:13px;padding-bottom:15px;cursor:pointer;text-align:center;z-index:10}.menu .menu-icon>svg{fill:#0d122b;opacity:0.7}.menu .menu-icon:hover>svg{opacity:1}.menu .menu-icon:active{-webkit-transform:scale(0.9, 0.9);transform:scale(0.9, 0.9)}.menu input[type="checkbox"]:not(:checked) ~ .trigger{clear:both;visibility:hidden}.menu input[type="checkbox"]:checked ~ .trigger{position:fixed;animation:0.2s ease-in forwards fadein;-webkit-animation:0.2s ease-in forwards fadein;display:flex;flex-direction:row;justify-content:center;align-items:center;background-color:#fff;height:100vh;width:100%;top:0}.menu .menu-link{display:block;box-sizing:border-box;font-size:1.1em}.menu .menu-link:not(:last-child){margin:0;padding:2px 0}}.author{margin-top:6.3rem;margin-bottom:7.2rem;text-align:center}@media screen and (max-width: 768px){.author{margin-bottom:3em}}.author .author-avatar{width:70px;height:70px;border-radius:100%;user-select:none;background-color:#0d122b;-ms-user-select:none;-webkit-user-select:none;-webkit-animation:0.5s ease-in forwards fadein;animation:0.5s ease-in forwards fadein;opacity:1}.author .author-name{font-size:1.7em;margin-bottom:2px}.author .author-bio{margin:0 auto;opacity:0.9;max-width:393px;line-height:1.688}.posts-item-note{font-weight:700;margin-bottom:5px;color:#0d122b}.post-item{display:flex;padding-top:5px;padding-bottom:6px}.post-item:not(:first-child){border-top:1px solid #ececec}.post-item .post-item-date{min-width:96px;color:#0d122b;font-weight:700;padding-right:10px}@media screen and (max-width: 768px){.post-item .post-item-date{font-size:16px}}.post-item .post-item-title{margin:0;color:#434648;font-weight:normal;letter-spacing:0.1px}.post-item .post-item-title a:hover,.post-item .post-item-title afocus{color:#0d122b}.footer{margin-top:8em;margin-bottom:2em;text-align:center}@media screen and (max-width: 768px){.footer{margin-top:3em}}.footer span.footer_item{color:#0d122b;opacity:0.8;font-weight:700;font-size:14px}.footer a.footer_item{color:#0d122b;opacity:0.8;text-decoration:none}.footer a.footer_item:not(:last-child){margin-right:10px}.footer a.footer_item:not(:last-child):hover{opacity:1}.footer .footer_theme-copyright{font-size:13px;margin-top:3px;display:block;color:#6b7886;opacity:0.8}.wrapper.not-found{text-align:center;display:flex;justify-content:center;flex-direction:column;height:75vh}.wrapper.not-found .title{font-size:5em;font-weight:700;line-height:1.1;color:#0d122b;text-shadow:1px 0px 0px #003fff}.wrapper.not-found .phrase{color:#434648}.wrapper.not-found .solution{color:#003fff;letter-spacing:0.5px}.wrapper.not-found .solution:hover{color:#0036c7}@media screen and (max-width: 768px){.wrapper.post{padding-left:15px;padding-right:15px}}.header{margin-top:7.8em;margin-bottom:3em}.header .tags{margin-left:3px;letter-spacing:0.5px}.header .tags .tag{font-weight:700;font-size:12px}.header .tags .tag:hover{text-decoration:none}.header .header-title{font-size:2em;line-height:1.2;margin-top:10px;margin-bottom:20px}.header .header-title.center{text-align:center}@media screen and (max-width: 768px){.header .header-title{font-size:1.9em}}.post-meta{padding-top:3px;line-height:1.3;color:#6b7886}.post-meta time{position:relative;margin-right:1.5em}.post-meta time::after{background:#ececec;bottom:1px;content:" ";height:2px;position:absolute;right:-20px;width:12px}.post-meta span[itemprop="author"]{border-bottom:1px dotted #ececec}.page-content{padding-top:8px}.page-content iframe{text-align:center}.page-content figure img{border-radius:2px}.page-content figure figcaption{margin-top:5px;font-style:italic;font-size:14px}.page-content a{color:#003fff;text-decoration:none}.page-content a[target="_blank"]::after{content:" \2197";font-size:14px;line-height:0;position:relative;bottom:5px;vertical-align:baseline}.page-content a:hover{color:#0036c7}.page-content a:focus{color:#003fff}.page-content>p{margin:0;padding-top:15px;padding-bottom:15px}.page-content ul.task-list{list-style:none;margin:0}.page-content ul.task-list li input[type="checkbox"]{margin-right:10px}.page-content dl dt{font-weight:700}.page-content h1,.page-content h2,.page-content h3,.page-content h4,.page-content h5,.page-content h6{color:#0d122b;font-weight:700;margin-top:30px;margin-bottom:0}.page-content h1:hover .anchor-head,.page-content h2:hover .anchor-head,.page-content h3:hover .anchor-head,.page-content h4:hover .anchor-head,.page-content h5:hover .anchor-head,.page-content h6:hover .anchor-head{color:#003fff;opacity:1}.page-content h1 .anchor-head,.page-content h2 .anchor-head,.page-content h3 .anchor-head,.page-content h4 .anchor-head,.page-content h5 .anchor-head,.page-content h6 .anchor-head{position:relative;opacity:0;outline:none}.page-content h1 .anchor-head::before,.page-content h2 .anchor-head::before,.page-content h3 .anchor-head::before,.page-content h4 .anchor-head::before,.page-content h5 .anchor-head::before,.page-content h6 .anchor-head::before{content:"#";position:absolute;right:-3px;width:1em;font-weight:700}.page-content h1{font-size:24px}.page-content h2{font-size:22px}.page-content h3{font-size:20px;border-bottom:1px solid #ececec;padding-bottom:4px}.page-content h4{font-size:20px}.page-content h5{font-size:16px}.page-content h6{font-size:14px}.post-nav{display:flex;position:relative;margin-top:5em;border-top:1px solid #ececec;line-height:1.4}.post-nav .post-nav-item{border-bottom:0;font-weight:700;padding-bottom:10px;width:50%;padding-top:10px;text-decoration:none;box-sizing:border-box}.post-nav .post-nav-item .post-title{color:#0d122b}.post-nav .post-nav-item:hover .post-title,.post-nav .post-nav-item:focus .post-title{color:#0036c7;opacity:0.9}.post-nav .post-nav-item .nav-arrow{font-weight:400;font-size:14px;color:#6b7886;margin-bottom:3px}.post-nav .post-nav-item:nth-child(odd){padding-left:0;padding-right:20px}.post-nav .post-nav-item:nth-child(even){text-align:right;padding-right:0;padding-left:20px}@media screen and (max-width: 768px){.post-nav{display:block;font-size:14px}.post-nav .post-nav-item{display:block;width:100%}.post-nav .post-nav-item:nth-child(even){border-left:0;padding-left:0;border-top:1px solid #ececec}}.post-updated-at{font-family:"Ubuntu mono", "monospace"}@keyframes fadein{0%{opacity:0.2}100%{opacity:0.99}}.embed-responsive{height:0;max-width:100%;overflow:hidden;position:relative;padding-bottom:56.25%;margin-top:20px}.embed-responsive iframe,.embed-responsive object,.embed-responsive embed{top:0;left:0;width:100%;height:100%;position:absolute}code{font-family:Consolas,monospace;text-rendering:optimizeLegibility;font-feature-settings:"calt" 1;font-variant-ligatures:normal;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;font-size:16px}code.highlighter-rouge{padding:1px 4px;position:relative;top:-1px;background-color:#f6f6f6;border-radius:2px}pre.highlight{margin:0 -27px;border-radius:2px;padding:10px;display:block;overflow-x:auto}@media screen and (max-width: 768px){pre.highlight{margin:0 calc(51% - 51vw);padding-left:20px}}pre.highlight>code{width:100%;max-width:50rem;margin-left:auto;margin-right:auto;line-height:1.5;display:block;border:0}.highlight table td{padding:5px}.highlight table pre{margin:0}.highlight,.highlight .w{color:#fbf1c7;background-color:#1a1b21}.highlight .err{color:#fb4934;background-color:#1a1b21;font-weight:bold}.highlight .c,.highlight .cd,.highlight .cm,.highlight .c1,.highlight .cs{color:#928374;font-style:italic}.highlight .cp{color:#8ec07c}.highlight .nt{color:#fb4934}.highlight .o,.highlight .ow{color:#fbf1c7}.highlight .p,.highlight .pi{color:#fbf1c7}.highlight .gi{color:#b8bb26;background-color:#282828}.highlight .gd{color:#fb4934;background-color:#282828}.highlight .gh{color:#b8bb26;font-weight:bold}.highlight .k,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kv{color:#fb4934}.highlight .kc{color:#d3869b}.highlight .kt{color:#fabd2f}.highlight .kd{color:#fe8019}.highlight .s,.highlight .sb,.highlight .sc,.highlight .sd,.highlight .s2,.highlight .sh,.highlight .sx,.highlight .s1{color:#b8bb26;font-style:italic}.highlight .si{color:#b8bb26;font-style:italic}.highlight .sr{color:#b8bb26;font-style:italic}.highlight .se{color:#fe8019}.highlight .nn{color:#8ec07c}.highlight .nc{color:#8ec07c}.highlight .no{color:#d3869b}.highlight .na{color:#b8bb26}.highlight .m,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo,.highlight .mb,.highlight .mx{color:#d3869b}.highlight .ss{color:#83a598}body[data-theme="dark"]{color:#d9d7e0;background-color:#131418}body[data-theme="dark"] h1,body[data-theme="dark"] h2,body[data-theme="dark"] h3,body[data-theme="dark"] h4,body[data-theme="dark"] h5,body[data-theme="dark"] h6{color:#f0f8ff}body[data-theme="dark"] .page-content a{color:#ff5277}body[data-theme="dark"] .page-content a:hover,body[data-theme="dark"] .page-content a:active,body[data-theme="dark"] .page-content a:focus{color:#ff2957}body[data-theme="dark"] .page-content h3{border-color:#1b1d25}body[data-theme="dark"] .page-content h1 .anchor-head,body[data-theme="dark"] .page-content h2 .anchor-head,body[data-theme="dark"] .page-content h3 .anchor-head,body[data-theme="dark"] .page-content h4 .anchor-head,body[data-theme="dark"] .page-content h5 .anchor-head,body[data-theme="dark"] .page-content h6 .anchor-head{color:#ff5277}body[data-theme="dark"] code.highlighter-rouge{background-color:#1b1d25}body[data-theme="dark"] kbd{border-color:#1b1d25;color:#f0f8ff;text-shadow:0 1px 0 #131418}body[data-theme="dark"] hr{border-color:#1b1d25}body[data-theme="dark"] .post-meta{color:#767f87}body[data-theme="dark"] .post-meta time::after{background-color:#1b1d25}body[data-theme="dark"] .post-meta span[itemprop="author"]{border-color:#1b1d25}body[data-theme="dark"] a{color:inherit;text-decoration-color:#4a4d56}body[data-theme="dark"] a:hover{color:#ff5277}body[data-theme="dark"] a:focus{outline-color:rgba(255,82,119,0.6)}body[data-theme="dark"] li:before{color:#f0f8ff}body[data-theme="dark"] strong,body[data-theme="dark"] b{color:#f0f8ff}body[data-theme="dark"] .navbar{border-color:#1b1d25}body[data-theme="dark"] .navbar .menu a#mood .mood-sunny{display:block}body[data-theme="dark"] .navbar .menu a#mood .mood-moon{display:none}body[data-theme="dark"] .navbar .menu .menu-link{color:#f0f8ff}@media screen and (max-width: 768px){body[data-theme="dark"] .navbar .menu{background-color:#131418;border-color:#1b1d25}body[data-theme="dark"] .navbar .menu .menu-icon>svg{fill:#f0f8ff}body[data-theme="dark"] .navbar .menu input[type="checkbox"]:checked ~ .trigger{background:#131418}}body[data-theme="dark"] .post-item:not(:first-child){border-color:#1b1d25}body[data-theme="dark"] .post-item .post-item-date{color:#f0f8ff}body[data-theme="dark"] .post-item .post-item-title a{color:#d9d7e0}body[data-theme="dark"] .post-item .post-item-title a:hover,body[data-theme="dark"] .post-item .post-item-title afocus{color:#f0f8ff}body[data-theme="dark"] .post-nav{border-color:#1b1d25}body[data-theme="dark"] .post-nav .post-nav-item{font-weight:700}body[data-theme="dark"] .post-nav .post-nav-item .post-title{color:#f0f8ff;opacity:0.9}body[data-theme="dark"] .post-nav .post-nav-item:hover .post-title,body[data-theme="dark"] .post-nav .post-nav-item:focus .post-title{color:#ff2957}body[data-theme="dark"] .post-nav .post-nav-item .nav-arrow{color:#767f87}@media screen and (max-width: 768px){body[data-theme="dark"] .post-nav .post-nav-item:nth-child(even){border-color:#1b1d25}}body[data-theme="dark"] .footer span.footer_item{color:#f0f8ff}body[data-theme="dark"] .footer a.footer_item:not(:last-child){color:#f0f8ff}body[data-theme="dark"] .footer .footer_theme-copyright{color:#767f87;opacity:0.4}body[data-theme="dark"] .wrapper.not-found .title{color:#f0f8ff;text-shadow:1px 0px 0px #ff5277}body[data-theme="dark"] .wrapper.not-found .phrase{color:#d9d7e0}body[data-theme="dark"] .wrapper.not-found .solution{color:#ff5277}body[data-theme="dark"] .wrapper.not-found .solution:hover{color:#ff2957} diff --git a/_site/assets/favicons/android-chrome-96x96.png b/_site/assets/favicons/android-chrome-96x96.png new file mode 100644 index 0000000..db86510 Binary files /dev/null and b/_site/assets/favicons/android-chrome-96x96.png differ diff --git a/_site/assets/favicons/apple-touch-icon.png b/_site/assets/favicons/apple-touch-icon.png new file mode 100644 index 0000000..96770fd Binary files /dev/null and b/_site/assets/favicons/apple-touch-icon.png differ diff --git a/_site/assets/favicons/favicon-16x16.png b/_site/assets/favicons/favicon-16x16.png new file mode 100644 index 0000000..7f31f47 Binary files /dev/null and b/_site/assets/favicons/favicon-16x16.png differ diff --git a/_site/assets/favicons/favicon-32x32.png b/_site/assets/favicons/favicon-32x32.png new file mode 100644 index 0000000..7d8ba7d Binary files /dev/null and b/_site/assets/favicons/favicon-32x32.png differ diff --git a/_site/assets/favicons/favicon.ico b/_site/assets/favicons/favicon.ico new file mode 100644 index 0000000..b1f3051 Binary files /dev/null and b/_site/assets/favicons/favicon.ico differ diff --git a/_site/assets/favicons/mstile-150x150.png b/_site/assets/favicons/mstile-150x150.png new file mode 100644 index 0000000..6645adc Binary files /dev/null and b/_site/assets/favicons/mstile-150x150.png differ diff --git a/_site/assets/favicons/safari-pinned-tab.svg b/_site/assets/favicons/safari-pinned-tab.svg new file mode 100644 index 0000000..d96e929 --- /dev/null +++ b/_site/assets/favicons/safari-pinned-tab.svg @@ -0,0 +1,27 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/_site/assets/favicons/site.webmanifest b/_site/assets/favicons/site.webmanifest new file mode 100644 index 0000000..315db41 --- /dev/null +++ b/_site/assets/favicons/site.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "Mahendrata", + "short_name": "Mahendrata", + "icons": [ + { + "src": "/assets/favicons/android-chrome-96x96.png", + "sizes": "96x96", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/_site/assets/img/avatar.jpg b/_site/assets/img/avatar.jpg new file mode 100644 index 0000000..6e5e18a Binary files /dev/null and b/_site/assets/img/avatar.jpg differ diff --git a/_site/assets/img/ogp.png b/_site/assets/img/ogp.png new file mode 100644 index 0000000..a18683c Binary files /dev/null and b/_site/assets/img/ogp.png differ diff --git a/_site/assets/js/disqus.js b/_site/assets/js/disqus.js new file mode 100644 index 0000000..f490611 --- /dev/null +++ b/_site/assets/js/disqus.js @@ -0,0 +1 @@ +!function(t,e,n){"use strict";var o=function(t,e){var n,o;return function(){var i=this,r=arguments,d=+new Date;n&&dt.innerHeight*r||i-l-u.offsetHeight-t.innerHeight*r>0)return!0;var c,f,p,y=e.getElementById("disqus_thread");y&&y.removeAttribute("id"),u.setAttribute("id","disqus_thread"),u.disqusLoaderStatus="loaded","loaded"==a?DISQUS.reset({reload:!0,config:d}):(t.disqus_config=d,"unloaded"==a&&(a="loading",c=s,f=function(){a="loaded"},(p=e.createElement("script")).src=c,p.async=!0,p.setAttribute("data-timestamp",+new Date),p.addEventListener("load",function(){"function"==typeof f&&f()}),(e.head||e.body).appendChild(p)))};t.addEventListener("scroll",o(i,l)),t.addEventListener("resize",o(i,l)),t.disqusLoader=function(t,n){n=function(t,e){var n,o={};for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(o[n]=t[n]);for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);return o}({laziness:1,throttle:250,scriptUrl:!1,disqusConfig:!1},n),r=n.laziness+1,i=n.throttle,d=n.disqusConfig,s=!1===s?n.scriptUrl:s,(u="string"==typeof t?e.querySelector(t):"number"==typeof t.length?t[0]:t)&&(u.disqusLoaderStatus="unloaded"),l()}}(window,document); \ No newline at end of file diff --git a/_site/assets/js/galite.js b/_site/assets/js/galite.js new file mode 100644 index 0000000..810673f --- /dev/null +++ b/_site/assets/js/galite.js @@ -0,0 +1 @@ +(function(b,l,e,g,h,f){1!==parseInt(e.msDoNotTrack||b.doNotTrack||e.doNotTrack,10)&&b.addEventListener("load",function(){var r=(new Date).getTime();b.galite=b.galite||{};var m=new XMLHttpRequest,n="https://www.google-analytics.com/collect?cid="+(l.uid=l.uid||Math.random()+"."+Math.random())+"&v=1&tid="+galite.UA+"&dl="+f(h.location.href)+"&ul=en-us&de=UTF-8",a=function(b){var d="",c;for(c in b){if(void 0===b[c])return!1;d+=f(b[c])}return d},p={dt:[h.title],sd:[g.colorDepth,"-bit"],sr:[g.availHeight,"x",g.availWidth],vp:[innerWidth,"x",innerHeight],dr:[h.referrer]},k;for(k in p){var q=k+"="+a(p[k]);q&&(n+="&"+q)}a=function(b,d){var c="",a;for(a in d)c+="&"+a+"="+f(d[a]);return function(){var a=n+c+(galite.anonymizeIp?"&aip=1":"")+"&t="+f(b)+"&z="+(new Date).getTime();if(e.sendBeacon)e.sendBeacon(a);else try{m.open("GET",a,!1),m.send()}catch(t){(new Image).src=a}}};setTimeout(a("pageview",null),100);b.addEventListener("unload",a("timing",{utc:"JS Dependencies",utv:"unload",utt:(new Date).getTime()-r}))})})(window,localStorage,navigator,screen,document,encodeURIComponent) \ No newline at end of file diff --git a/_site/assets/js/main.js b/_site/assets/js/main.js new file mode 100644 index 0000000..dbf1cfc --- /dev/null +++ b/_site/assets/js/main.js @@ -0,0 +1,35 @@ +(() => { + // Theme switch + const root = document.body; + const themeSwitch = document.getElementById("mood"); + const themeData = root.getAttribute("data-theme"); + + if (themeSwitch) { + initTheme(localStorage.getItem("theme")); + themeSwitch.addEventListener("click", () => + toggleTheme(localStorage.getItem("theme")) + ); + + function toggleTheme(state) { + if (state === "dark") { + localStorage.setItem("theme", "light"); + root.removeAttribute("data-theme"); + } else if (state === "light") { + localStorage.setItem("theme", "dark"); + document.body.setAttribute("data-theme", "dark"); + } else { + initTheme(state); + } + } + + function initTheme(state) { + if (state === "dark") { + document.body.setAttribute("data-theme", "dark"); + } else if (state === "light") { + root.removeAttribute("data-theme"); + } else { + localStorage.setItem("theme", themeData); + } + } + } +})(); diff --git a/_site/browserconfig.xml b/_site/browserconfig.xml new file mode 100644 index 0000000..4c5c4ec --- /dev/null +++ b/_site/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #2c2c2c + + + diff --git a/_site/cara-memperbarui-fork-repository/index.html b/_site/cara-memperbarui-fork-repository/index.html new file mode 100644 index 0000000..19a3a86 --- /dev/null +++ b/_site/cara-memperbarui-fork-repository/index.html @@ -0,0 +1,12 @@ + Cara ribet memperbarui forked repo - Klise Theme

Cara ribet memperbarui forked repo

Berawal dari saya pengen memperbarui repo yang tua dari suatu organisasi, niatnya pengen rumat ulang nih, ternyata dari orginal reponya ada update, sekalian buat artikel deh, lebih kurang gambaranya seperti ini.

ilustrasi repo yang mau diupdate
Fig 1. Gambaran ribetnya.

Ada dua cara untuk memperbarui forked repository menggunakan web interface yang disediakan oleh github tapi ribet, atau melalui terminal yang lebih ribet lagi.

Melalui Github (boring way) 💻

  1. Buka repo yang hasil fork di Github.
  2. Klik Pull Requests di sebelah kanan, lalu New Pull Request.
  3. Akan memunculkan hasil compare antara repo upstream dengan repo kamu(forked repo), dan jika menyatakan “There isn’t anything to compare.”, tekan link switching the base, yang mana sekarang repo kamu(forked repo) akan dibalik menjadi base repo dan repo upstream menjadi head repo.
  4. Tekan Create Pull Request, beri judul pull request, Tekan Send Pull Request.
  5. Tekan Merge Pull Request dan Confirm Merge.

* pastikan kamu tidak merubah apapun pada forked repo, supaya melakukan merge secara otomatis, kalo tidak ya paling2 konflik.

Melalui terminal ⌨️

Tambahkan remote alamat repository yang aslinya disini tak beri nama upstream., ganti ORIGINAL_OWNER dan ORIGINAL_REPO dengan alamat repo aslimu.

$ git add remote upstream git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git
+$ git remote -v
+> origin    git@github.com:piharpi/www.git (fetch) # forked repo
+> origin    git@github.com:piharpi/www.git (push) # forked repo
+> upstream    git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git (fetch) # upstream repo / original repo
+> upstream    git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git (push) # upstream repo / original repo
+

Checkout ke local branch master.

$ git checkout master
+> Switched to branch 'master'
+

Jika sudah, Merge local repo dengan remote upstream/master.

$ git merge upstream/master
+

Terakhir push local repo ke remote origin.

$ git add -A
+$ git commit -m "updating origin repo" && git push -u origin master
+

Selamat mencoba cara ribet ini, semoga bisa dipahami, saya sendiri lebih senang melalui terminal, klo ada yang ribet kenapa cari yang mudah.

Resources
updated_at 07-03-2020
diff --git a/_site/cara-memperbarui-fork-repository/repo.png b/_site/cara-memperbarui-fork-repository/repo.png new file mode 100644 index 0000000..66eae64 Binary files /dev/null and b/_site/cara-memperbarui-fork-repository/repo.png differ diff --git a/_site/feed.xml b/_site/feed.xml new file mode 100644 index 0000000..0e8fafa --- /dev/null +++ b/_site/feed.xml @@ -0,0 +1,825 @@ +Jekyll2020-03-09T22:32:09+07:00http://localhost:4000/feed.xmlKlise ThemeHe's writing in Bahasa about web technology and experience as a journal for documentation things that he learned, meet him <a href="https://github.com/piharpi" target="_blank" rel="noopener">@github</a>.Klisé Themeyour-email@email.comCara ribet memperbarui forked repo2020-01-29T01:00:00+07:002020-01-29T01:00:00+07:00http://localhost:4000/cara-memperbarui-fork-repository<p>Berawal dari saya pengen memperbarui repo yang tua dari suatu organisasi, niatnya pengen rumat ulang nih, ternyata dari orginal reponya ada update, sekalian buat artikel deh, lebih kurang gambaranya seperti ini.</p> + +<figure> +<img src="/cara-memperbarui-fork-repository/repo.png" alt="ilustrasi repo yang mau diupdate" /> +<figcaption>Fig 1. Gambaran ribetnya.</figcaption> +</figure> + +<p>Ada dua cara untuk memperbarui forked repository menggunakan web interface yang disediakan oleh github tapi ribet, atau melalui terminal yang lebih ribet lagi.</p> + +<h3 id="melalui-github-boring-way-">Melalui Github (boring way) 💻</h3> + +<ol> + <li>Buka repo yang hasil fork di Github.</li> + <li>Klik <strong>Pull Requests</strong> di sebelah kanan, lalu <strong>New Pull Request</strong>.</li> + <li>Akan memunculkan hasil compare antara repo upstream dengan repo kamu(forked repo), dan jika menyatakan “There isn’t anything to compare.”, tekan link <strong>switching the base</strong>, yang mana sekarang repo kamu(forked repo) akan dibalik menjadi base repo dan repo upstream menjadi head repo.</li> + <li>Tekan <strong>Create Pull Request</strong>, beri judul pull request, Tekan <strong>Send Pull Request</strong>.</li> + <li>Tekan <strong>Merge Pull Request</strong> dan <strong>Confirm Merge</strong>.</li> +</ol> + +<p>* <em>pastikan kamu tidak merubah apapun pada forked repo, supaya melakukan merge secara otomatis, kalo tidak ya paling2 konflik.</em></p> + +<h3 id="melalui-terminal-️">Melalui terminal ⌨️</h3> + +<p>Tambahkan remote alamat repository yang aslinya disini tak beri nama <code class="highlighter-rouge">upstream</code>., ganti <code class="highlighter-rouge">ORIGINAL_OWNER</code> dan <code class="highlighter-rouge">ORIGINAL_REPO</code> dengan alamat repo aslimu.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add remote upstream git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git +<span class="nv">$ </span>git remote <span class="nt">-v</span> +<span class="o">&gt;</span> origin git@github.com:piharpi/www.git <span class="o">(</span>fetch<span class="o">)</span> <span class="c"># forked repo</span> +<span class="o">&gt;</span> origin git@github.com:piharpi/www.git <span class="o">(</span>push<span class="o">)</span> <span class="c"># forked repo</span> +<span class="o">&gt;</span> upstream git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git <span class="o">(</span>fetch<span class="o">)</span> <span class="c"># upstream repo / original repo</span> +<span class="o">&gt;</span> upstream git@github.com:ORIGINAL_OWNER/ORIGINAL_REPO.git <span class="o">(</span>push<span class="o">)</span> <span class="c"># upstream repo / original repo</span> +</code></pre></div></div> + +<p>Checkout ke local branch <code class="highlighter-rouge">master</code>.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git checkout master +<span class="o">&gt;</span> Switched to branch <span class="s1">'master'</span> +</code></pre></div></div> + +<p>Jika sudah, Merge local repo dengan remote <code class="highlighter-rouge">upstream/master</code>.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git merge upstream/master +</code></pre></div></div> + +<p>Terakhir push local repo ke remote <code class="highlighter-rouge">origin</code>.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add <span class="nt">-A</span> +<span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"updating origin repo"</span> <span class="o">&amp;&amp;</span> git push <span class="nt">-u</span> origin master +</code></pre></div></div> + +<p>Selamat mencoba cara ribet ini, semoga bisa dipahami, saya sendiri lebih senang melalui terminal, klo ada yang ribet kenapa cari yang mudah.</p> + +<h5 id="resources">Resources</h5> + +<ul> + <li><a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/syncing-a-fork">Syncing a fork</a></li> + <li><a href="https://rick.cogley.info/post/update-your-forked-repository-directly-on-github/#top">Update your fork directly on Github</a></li> +</ul>Klisé Themeyour-email@email.comBerawal dari saya pengen memperbarui repo yang tua dari suatu organisasi, niatnya pengen rumat ulang nih, ternyata dari orginal reponya ada update, sekalian buat artikel deh, lebih kurang gambaranya seperti ini.What is a shell? 🐚 adalah kerang ajaib?2020-01-25T11:58:47+07:002020-01-25T11:58:47+07:00http://localhost:4000/apa-itu-shell<p><a href="http://www.youtube.com/watch?v=tc4ROCJYbm0&amp;t=70" target="_blank" rel="noopener">Dulu</a> Sebelum adanya <abbr title="Graphical User Interface">GUI</abbr> cara user berinteraksi dengan komputer menggunakan <abbr title="Command Line Interface">CLI</abbr> yaitu mengetik baris perintah pada sebuah antarmuka dalam bentuk baris teks seperti 👇.</p> + +<figure> +<img src="/apa-itu-shell/terminal_nginx.gif" alt="installing nginx in ubuntu" /> +<figcaption>Fig 1. Terminal emulator, instalasi package dan check service.</figcaption> +</figure> + +<p>Jika kamu pernah menggunakan unix/linux mungkin pernah menggunakan program diatas, bahkan mungkin setiap hari menggunakannya untuk mengeksekusi suatu perintah melalui <a href="http://en.wikipedia.org/wiki/List_of_terminal_emulators" target="_blank" rel="noopener">terminal emulator</a>.</p> + +<p>User<sup id="user"><a href="#user-ref">[1]</a></sup> tidak bisa secara langsung berkomunikasi dengan sebuah hardware komputer, maka dari itu kita membutuhkan sebuah sistem operasi; <strong>Kernel</strong> adalah program yang merupakan inti utama dari sistem operasi komputer.</p> + +<figure> +<img src="/apa-itu-shell/kernel.png" alt="kernel central of operating system" /> +<figcaption>Fig 2. bagan kernel.</figcaption> +</figure> + +<p>Kernel memfasilitasi interaksi antara komponen perangkat keras dan perangkat lunak, berperan untuk menangani permintaan input/ouput dari perangkat lunak, selanjutnya menerjemahkannya ke dalam pemrosesan data untuk diintruksikan ke CPU, sehingga Hardware(cpu, memory, devices) mengerti perintah yang dimaksud dari pengguna.</p> + +<p>Ketika kita menginputkan suatu perintah pada terminal emulator, kernel tidak langsung mengerti perintah yang kita ketik, kita membutuhkan suatu interface sebagai perantara menuju kernel yaitu <strong>Shell</strong>.</p> + +<figure> +<img src="/apa-itu-shell/shell.png" alt="shell" /> +<figcaption>Fig 3. bagan komunikasi shell.</figcaption> +</figure> + +<p><mark>Shell adalah sebuah command-line interpreter; program yang berperan sebagai penerjemah perintah yang diinputkan oleh User yang melalui terminal</mark>, sehingga perintah tersebut bisa dimengerti oleh si Kernel.</p> + +<p>Login shell biasanya ditetapkan oleh local System Administrator ketika pada saat pertama user kamu dibuat, kamu bisa lihat login shell yang sedang kamu gunakan dengan perintah dibawah ini.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$SHELL</span> +<span class="c"># atau</span> +<span class="nv">$ </span><span class="nb">echo</span> <span class="nv">$0</span> +</code></pre></div></div> + +<p>Setiap shell mempunyai default prompt. beberapa shell yang paling umum:</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="o">(</span>dollar sign<span class="o">)</span> <span class="c"># sh, ksh, bash</span> +% <span class="o">(</span>percent sign<span class="o">)</span> <span class="c"># csh, tcsh</span> +</code></pre></div></div> + +<h5 id="terminologi-pada-shell-prompt">Terminologi pada shell prompt</h5> + +<p>Shell prompt adalah tempat dimana kita menuliskan suatu perintah, berikut adalah terminologinya ini membantu, jika kamu ingin mengetahui bagian-bagianya.</p> + +<figure> +<img src="/apa-itu-shell/term_shell_prompt.png" alt="shell" /> +<figcaption>Fig 4. bagian-bagin dari shell prompt.</figcaption> +</figure> + +<p>Dibawah ini salah satu contoh perintah sederhana untuk menampilkan sebuah arsitektur CPU komputer yang sedang saya gunakan.</p> + +<figure> +<img src="/apa-itu-shell/terminal_lscpu.gif" alt="installing nginx in ubuntu" /> +<figcaption>Fig 5. menampilkan informasi tentang arsitektur CPU.</figcaption> +</figure> + +<p>Dari perintah yang contohkan, ketika user mengetikan suatu inputan perintah di terminal dan menekan <kbd>ENTER</kbd>, maka shell akan mengubah perintah user menjadi bahasa yang bisa dipahami oleh kernel, dan Kernel menerjemahkannya ke dalam pemrosesan data untuk diintruksikan ke Hardware sehingga menghasilkan output yg sesuai dengan perintah user.</p> + +<p>Shell mempunyai beberapa macam dan turunan, berikut yang paling umum.</p> + +<figure> +<img src="/apa-itu-shell/shell_evolution.png" alt="shell evolution" /> +<figcaption>Fig 6. evaluasi shell dari tahun ke tahun.</figcaption> +</figure> + +<p>Sedikit penjelasan dari gambar diatas.</p> + +<ul> + <li>Bourne shell <code class="highlighter-rouge">sh</code> +Dikembangkan oleh Stephen Bourne di Bell Labs, yang kala itu sebagai pengganti Thompson shell(diciptakan Ken Thompson), banyak sistem unix-like tetap memiliki <code class="highlighter-rouge">/bin/sh</code>—yang mana menjadi symbolic link atau hard link, bahkan ketika shell lain yang digunakan tetap <code class="highlighter-rouge">sh</code> adalah sebagai dasarnya, sebagai kompatibilitas perintah.</li> + <li>Korn shell <code class="highlighter-rouge">ksh</code> Unix shell yang dikembangkan oleh David Korn di Bell Labs, +inisialiasi pengembangan ini berdasar pada source code Bourne shell, namun juga memiliki fitur <code class="highlighter-rouge">csh</code> dan <code class="highlighter-rouge">sh</code>, pengembanganya pun pada saat saya menulis ini pun terus <a href="http://github.com/att/ast" target="_blank" rel="noopener">terawat</a>.</li> + <li>Bourne again shell <code class="highlighter-rouge">bash</code> +adalah proyek ini open source <a href="http://gnu.org/software/bash/" target="_blank" rel="noopener">GNU project</a> memilki kompatibel dengan <code class="highlighter-rouge">sh</code> yang menggabungkan fitur penting dari <code class="highlighter-rouge">ksh</code> dan <code class="highlighter-rouge">csh</code>, dan menjadi salah satu shell yang paling umum digunakan (umumnya menjadi default shell login Linux dan Apple’s macOS Mojave).</li> + <li>Z shell <code class="highlighter-rouge">zsh</code> ini mempunyai wadah komunitasnya disebutnya <a href="http://ohmyz.sh/" target="_blank" rel="noopener">“Oh My Zsh”</a>, plug-in dan theme <code class="highlighter-rouge">zsh</code> bisa kita temukan di komunitas ini, saya saat ini menggunakan <code class="highlighter-rouge">zsh</code>, shell ini juga menjadi default dari sistem operasi macOS Catalina, yang menggantikan bash.</li> + <li>friendly interactive shell <code class="highlighter-rouge">fish</code> +yah sesuai dengan <a href="http://fishshell.com/" target="_blank" rel="noopener">deskripsi</a> di web nya, menurut saya shell ini fun banget, fitur yang saya sukai dari shell ini autosuggestions, dan konfigurasi yang mudah melalui web based.</li> +</ul> + +<p>Masih banyak yang belum dijelaskan pada tulisan ini jika masih tertarik, baca lebih <a href="http://en.wikipedia.org/wiki/List_of_command-line_interpreters#Operating_system_shells" target="_blank" rel="noopener">banyak</a> dan juga <a href="http://en.wikipedia.org/wiki/Comparison_of_command_shells" target="_blank" rel="noopener">komparasinya</a> masing-masing shell.</p> + +<p>Jika kamu tertarik untuk mengubah default shell login pada sistem operasi, kamu bisa menginstall dengan cara mengikuti didokumentasi/cara penginstallan dimasing-masing shell disini saya tidak membahas karena distro yang kita pakai mungkin berbeda-beda.</p> + +<p>Untuk menjadikan default shell login pada OS bisa menggunakan perintah ini.</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># command</span> +<span class="nv">$ </span><span class="nb">sudo </span>chsh <span class="o">[</span>options] <span class="o">[</span>LOGIN] + +<span class="c"># contoh penggunaan</span> +<span class="nv">$ </span><span class="nb">sudo </span>chsh <span class="nt">-s</span> /user/bin/zsh harpi +<span class="c"># mengubah default shell user harpi menjadi zsh shell.</span> +<span class="nv">$ </span>reboot + +<span class="c"># atau kamu juga bisa mengubah file /etc/passwd dan edit secara manual user shellnya.</span> +<span class="c"># jika masih bingung manfaatkan perintah man untuk melihat manual page.</span> +<span class="nv">$ </span>man chsh +</code></pre></div></div> + +<p>Terakhir untuk tulisan ini, shell memilki berbagai macam, pilihlah shell yang sesuai dengan keinginanmu untuk menunjang produktivitas dan sesuaikan dengan kebutuhan, terlalu banyak plugin dan kebingungan memilih tema itu buruk 😁.</p> + +<p>Terimakasih sudah baca, <em>penulis menerima kritik dan saran.</em></p> + +<h5 id="notes">Notes</h5> + +<p><small id="user-ref"><sup><a href="#user">[1]</a></sup> Manusia yang mengoperasikan dan mengendalikan sistem komputer.</small></p> + +<h5 id="resources">Resources</h5> + +<ul> + <li><a href="http://developer.ibm.com/tutorials/l-linux-shells/">Evolution shells in Linux</a></li> + <li><a href="http://www.linfo.org/kernel.html">Kernel Defintion</a></li> + <li><a href="http://www.cis.rit.edu/class/simg211/unixintro/Shell.html">The Shell</a></li> +</ul>Klisé Themeyour-email@email.comDulu Sebelum adanya GUI cara user berinteraksi dengan komputer menggunakan CLI yaitu mengetik baris perintah pada sebuah antarmuka dalam bentuk baris teks seperti 👇.How this site was born 👶2018-09-28T09:45:47+07:002018-09-28T09:45:47+07:00http://localhost:4000/how-this-site-was-made<p>The website was made using Jekyll the one of open source static sites generator, and using my own simple theme, I called <a href="https://github.com/piharpi/klise">klisé</a>.</p> + +<hr /> + +<p>All the services are free, source code the site was placed on my <a href="https://github.com/piharpi/mahendrata.now.sh">github</a> repository and intergration with <del><a href="https://netlify.com">netlify</a></del> service, another service that you can use is <a href="https://pages.github.com/">github page</a> for hosting your own static site.</p> + +<hr /> + +<h4 id="lets-do-this">Let’s do this</h4> + +<p>So, before we start create a site, you need some tools, you can self paced for how to installing each tools, on this guide i’m just want to show you how to install jekyll and deploying in netlify, but make sure you have each tools below.</p> + +<h4 id="prerequisites">Prerequisites</h4> + +<p>Requirements before we doing magic show.</p> + +<ul> + <li><a href="https://www.ruby-lang.org/en/downloads/">Ruby</a> programming language</li> + <li><a href="https://git-scm.com">Git</a> (version control)</li> + <li><a href="https://netlify.com">Netlify</a> and <a href="https://github.com">Github</a> account</li> + <li><a href="https://bundler.io">Bundler</a></li> +</ul> + +<h4 id="installation">Installation</h4> + +<p>First, you need some <a href="https://www.staticgen.com/">SSG</a>, there are many kind ssg, but in case i’m using Jekyll cause i’m already familiar with it, open your terminal and type command on below</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>bundle <span class="nb">install </span>jekyll <span class="c"># installing jekyll in your machine</span> +<span class="nv">$ </span>jekyll new my-site <span class="o">&amp;&amp;</span> <span class="nb">cd </span>my-site <span class="c"># create new jekyll project</span> +<span class="nv">$ </span>jekyll s <span class="c"># run jekyll server</span> +</code></pre></div></div> + +<p>Now, jekyll is running on your local machine, open your browser and go to <code class="highlighter-rouge">localhost:4000</code> is default address from jekyll, press <kbd>CTRL</kbd> + <kbd>C</kbd> to stop the jekyll server.</p> + +<h4 id="adding-remote-repository">Adding remote repository</h4> + +<p>Before we adding remote repository, you must have <a href="https://github.com/new">github</a> repository, if already have repository, just add github remote address to your local folder, with the following commands</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git init <span class="c"># initializing project folder</span> +<span class="nv">$ </span>git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPO.git <span class="c"># change UPPERCASE with your own!</span> +<span class="nv">$ </span>git add <span class="nt">-A</span> <span class="o">&amp;&amp;</span> git commit <span class="nt">-m</span> <span class="s2">"Initialize"</span> <span class="o">&amp;&amp;</span> git push <span class="nt">-u</span> origin master <span class="c"># push code to github</span> +</code></pre></div></div> + +<p>Now check your github repository, make sure the files is uploaded correctly.</p> + +<h4 id="deploying-to-netlify">Deploying to netlify</h4> + +<p>Go <a href="https://netlify.com">netlify</a> dashboard, and following this step.</p> + +<ol> + <li>click <code class="highlighter-rouge">new site from git</code>, then choose <code class="highlighter-rouge">Github</code>.</li> + <li>then choose your repository where is the jekyll sources uploaded.</li> + <li>netlify smart enough to configuring, we just need’s are hosting’s are hosting’s are hosting’s are hosting to click <code class="highlighter-rouge">Deploy site button</code>.</li> +</ol> + +<p>Wait for moment, and voila..! your site’s are hosting and using <code class="highlighter-rouge">.netlify.com</code> tld, if your website wants to look professional, just buy a domain from your favorite domain store. or if you the first time, I advice using namecheap.com<em>(isn’t sponsor)</em> *based on my experienced it provides good service and have various TLDs.</p> + +<p>So, what you waiting for, just create your own website for free.</p>Klisé Themeyour-email@email.comThe website was made using Jekyll the one of open source static sites generator, and using my own simple theme, I called klisé.Python Notes from Intro to Machine Learning2018-04-14T10:00:00+07:002018-04-14T10:00:00+07:00http://localhost:4000/python-notes-from-Intro-to-machine-learning<h5 id="this-article-is-for-demo-purpose">This article is for Demo purpose</h5> + +<p>The article was originally on <a href="https://github.com/risan/risanb.com/blob/master/content/posts/python-notes-from-intro-to-machine-learning/index.md">this repo</a></p> + +<p>I rarely use Python. I only have one repository at Github that is written in Python: <a href="https://github.com/risan/iris-flower-classifier">iris-flower-classifier</a>. And it was written two years ago!</p> + +<p>A few days ago I took this free course from Udacity: <a href="https://eu.udacity.com/course/intro-to-machine-learning--ud120">Intro to Machine Learning</a>. The machine learning related codes are quite easy to grasp since it simply uses the <a href="http://scikit-learn.org/">scikit-learn</a> modules. But most of the supporting Python modules that are provided by this course were like a black-box to me. I had no idea how to download a file in Python or what’s the difference between a list, a tuple and a dictionary.</p> + +<p>That’s why I decided to read all of the provided Python modules and implement it myself. I ended up refactor most of the code so it’s easier to understand: <a href="https://github.com/risan/intro-to-machine-learning">github.com/risan/intro-to-machine-learning</a>.</p> + +<p>So here are some notes and snippets of Python that I’ve been collecting so far (I’m not even halfway through the course 😝). Also, note that the codes here are still using Python version 2.7.</p> + +<h2 id="table-of-contents">Table of Contents</h2> + +<h2 id="modules-classes-and-functions">Modules Classes and Functions</h2> + +<h3 id="main-entry-file">Main Entry File</h3> + +<p>Suppose our Python project is stored in <code class="highlighter-rouge">/foo/bar</code> directory. And this application has one file that serves as the single entry point. We can name this file <code class="highlighter-rouge">__main__.py</code> so we can run this project simply be referencing its directory path:</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Referencing its directory.</span> +<span class="nv">$ </span>python /foo/bar + +<span class="c"># It's equivalent to this.</span> +<span class="nv">$ </span>python /foo/bar/__main__.py +</code></pre></div></div> + +<h3 id="import-python-module-dynamically">Import Python Module Dynamically</h3> + +<p>Suppose we would like to import a Python module dynamically based on a variable value. We can achieve this through the <a href="https://docs.python.org/2/library/functions.html#__import__"><code class="highlighter-rouge">__import__</code></a> function:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">module_name</span> <span class="o">=</span> <span class="s">"numpy"</span> + +<span class="nb">__import__</span><span class="p">(</span><span class="n">module_name</span><span class="p">)</span> +</code></pre></div></div> + +<h3 id="multiple-returns-in-python">Multiple Returns in Python</h3> + +<p>In Python, it’s possible for a function or a method to return multiple values. We can do this simply by separating each return value by a comma:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">test</span><span class="p">():</span> + <span class="k">return</span> <span class="mi">100</span><span class="p">,</span> <span class="s">"foo"</span> + +<span class="n">someNumber</span><span class="p">,</span> <span class="n">someString</span> <span class="o">=</span> <span class="n">test</span><span class="p">()</span> +</code></pre></div></div> + +<h3 id="importing-modules-outside-of-the-directory">Importing Modules Outside of the Directory</h3> + +<p>In order to import a module from outside of the directory, we need to add that module’s directory path into the current file with <code class="highlighter-rouge">sys.path.append</code>. Suppose we have the following directory structure:</p> + +<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|--foo +| |-- bar.py +| +|-- tools +| |-- speak_yoda.py +</code></pre></div></div> + +<p>If we want to use the <code class="highlighter-rouge">speak_yoda.py</code> module within the <code class="highlighter-rouge">bar.py</code>, we can do the following:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># /foo/bar.py +</span><span class="kn">import</span> <span class="nn">os</span> + +<span class="c1"># Use relative path to tools directory. +</span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">"../tools"</span><span class="p">)</span> + +<span class="kn">import</span> <span class="nn">speak_yoda</span> +</code></pre></div></div> + +<p>However, this won’t work if we run the <code class="highlighter-rouge">baz.py</code> file from outside of its <code class="highlighter-rouge">foo</code> directory:</p> + +<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># It works inside of the /foo directory.</span> +<span class="nv">$ </span><span class="nb">cd</span> /foo +<span class="nv">$ </span>python bar.py + +<span class="c"># But it won't work if the code runs from outside of /foo directory.</span> +<span class="nv">$ </span>python foo/bar.py +</code></pre></div></div> + +<p>To solve this problem we can refer to the <code class="highlighter-rouge">tools</code> directory using its absolute path.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># /foo/bar.py +</span><span class="kn">import</span> <span class="nn">os</span> +<span class="kn">import</span> <span class="nn">sys</span> + +<span class="c1"># Get the directory name for this file. +</span><span class="n">current_dirname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">realpath</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span> + +<span class="c1"># Use the absolute path to the tools directory +</span><span class="n">tools_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">dirname</span><span class="p">,</span> <span class="s">"../tools"</span><span class="p">))</span> +<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">tools_path</span><span class="p">)</span> + +<span class="kn">import</span> <span class="nn">speak_yoda</span> +</code></pre></div></div> + +<h2 id="output">Output</h2> + +<h3 id="print-the-emojis">Print The Emojis</h3> + +<p>It turns out you can’t just print an emoji or any other Unicode characters to the console. You need to specify the encoding type beforehand:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># coding: utf8 +</span> +<span class="k">print</span><span class="p">(</span><span class="s">"😅"</span><span class="p">)</span> +</code></pre></div></div> + +<h3 id="pretty-print">Pretty Print</h3> + +<p>We can use the <code class="highlighter-rouge">pprint</code> module to pretty-print Python data structure with a configurable indentation:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pprint</span> +<span class="n">pp</span> <span class="o">=</span> <span class="n">pprint</span><span class="o">.</span><span class="n">PrettyPrinter</span><span class="p">(</span><span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> + +<span class="n">pp</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">people</span><span class="p">)</span> +</code></pre></div></div> + +<h2 id="working-with-pathname">Working with Pathname</h2> + +<p>Read more about pathname manipulations in the <a href="https://docs.python.org/2/library/os.path.html"><code class="highlighter-rouge">os.path</code> documentation</a>.</p> + +<h3 id="get-filename-from-url">Get Filename From URL</h3> + +<p>Suppose the last segment of the URL contains a filename that we would like to download. We can extract this filename with the following code:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span> +<span class="kn">from</span> <span class="nn">urlparse</span> <span class="kn">import</span> <span class="n">urlparse</span> + +<span class="n">url</span> <span class="o">=</span> <span class="s">"https://example.com/foo.txt"</span> + +<span class="n">url_components</span> <span class="o">=</span> <span class="n">urlparse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> + +<span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">url_components</span><span class="o">.</span><span class="n">path</span><span class="p">)</span> <span class="c1"># foo.txt +</span></code></pre></div></div> + +<h3 id="check-if-file-exists">Check if File Exists</h3> + +<p>To check whether the given file path exists or not:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span> + +<span class="n">is_exists</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="s">"foo.txt"</span><span class="p">)</span> +</code></pre></div></div> + +<h3 id="create-a-directory-if-it-does-not-exists">Create a Directory if It Does Not Exists</h3> + +<p>To create a directory only if it does not exist:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span> +<span class="kn">import</span> <span class="nn">errno</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">directory_path</span><span class="p">)</span> +<span class="k">except</span> <span class="nb">OSError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> + <span class="k">if</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">!=</span> <span class="n">errno</span><span class="o">.</span><span class="n">EEXIST</span><span class="p">:</span> + <span class="k">raise</span> +</code></pre></div></div> + +<h2 id="working-with-files">Working with Files</h2> + +<h3 id="downloading-a-file">Downloading a File</h3> + +<p>We can use the <code class="highlighter-rouge">urllib</code> module to download a file in Python. The first argument is the file URL that we would like to download. The second argument is the optional filename that will be used to store the file.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">urllib</span> + +<span class="n">urllib</span><span class="o">.</span><span class="n">urlretrieve</span><span class="p">(</span><span class="s">"https://example.com/foo.txt"</span><span class="p">,</span> <span class="s">"foo.txt"</span><span class="p">)</span> +</code></pre></div></div> + +<h3 id="extracting-tar-file">Extracting Tar File</h3> + +<p>There’s a built-in <code class="highlighter-rouge">tarfile</code> module that we can use to work with Tar file in Python. To extract the <code class="highlighter-rouge">tar.gz</code> file we can use the following code:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">tarfile</span> + +<span class="c1"># Open the file. +</span><span class="n">tfile</span> <span class="o">=</span> <span class="n">tarfile</span><span class="o">.</span><span class="nb">open</span><span class="p">(</span><span class="s">"foo.tar.gz"</span><span class="p">)</span> + +<span class="c1"># Extract the file to the given path. +</span><span class="n">tfile</span><span class="o">.</span><span class="n">extractall</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> +</code></pre></div></div> + +<p>We can pass the <code class="highlighter-rouge">mode</code> argument to the <code class="highlighter-rouge">open</code> method. By default, the <code class="highlighter-rouge">mode</code> would be <code class="highlighter-rouge">r</code>—reading mode with transparent compression. There are also other mode options that we can use:</p> + +<ul> + <li><code class="highlighter-rouge">r:gz</code>: Reading mode with gzip compression.</li> + <li><code class="highlighter-rouge">r:</code>: Reading mode without compression.</li> + <li><code class="highlighter-rouge">a</code>: Appending mode without compression.</li> + <li><code class="highlighter-rouge">w</code>: Writting mode without compression.</li> + <li>Checkout other available options in <a href="https://docs.python.org/2/library/tarfile.html">tarfile documentation</a>.</li> +</ul> + +<h2 id="working-with-list">Working with List</h2> + +<h3 id="generate-a-list-of-random-numbers">Generate a List of Random Numbers</h3> + +<p>Use the <code class="highlighter-rouge">for..in</code> syntax to generate a list of random numbers in a one-liner style.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">random</span> + +<span class="c1"># Initialize internal state of random generator. +</span><span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> + +<span class="c1"># Generate random points. +</span><span class="n">randomNumbers</span> <span class="o">=</span> <span class="p">[</span><span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span> +<span class="c1"># [0.6394267984578837, 0.025010755222666936, 0.27502931836911926, ...] +</span></code></pre></div></div> + +<h3 id="pair-values-from-two-lists">Pair Values from Two Lists</h3> + +<p>The built-in <code class="highlighter-rouge">zip</code> function can pair values from two lists. However, this <code class="highlighter-rouge">zip</code> function will return a list of tuples instead. To get a list of value pairs, we can combine it with <code class="highlighter-rouge">for..in</code> syntax:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">coordinates</span> <span class="o">=</span> <span class="p">[[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">([</span><span class="mi">5</span><span class="p">,</span><span class="mi">10</span><span class="p">,</span><span class="mi">15</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">])]</span> +<span class="c1"># [[5, 0], [10, 1], [15, 0]] +</span></code></pre></div></div> + +<h3 id="splitting-a-list">Splitting a List</h3> + +<p>We can easily split a list in Python by specifying the starting index and it’s ending index. Note that the ending index is excluded from the result.</p> + +<p>We can also specify a negative index. And also note that both of these indices are optional!</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> + +<span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="c1"># 0,1,2 +</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span> <span class="c1"># 1,2 +</span><span class="n">a</span><span class="p">[</span><span class="mi">2</span><span class="p">:]</span> <span class="c1"># 2,3,4,5 +</span><span class="n">a</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="c1"># 0,1,2 +</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="c1"># 0,1,2,3 +</span><span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">:]</span> <span class="c1"># 4,5 +</span><span class="n">a</span><span class="p">[:]</span> <span class="c1"># 0,1,2,3,4,5 +</span></code></pre></div></div> + +<h3 id="filtering-a-list-in-one-line">Filtering a List In One Line</h3> + +<p>We can easily filter a list in Python by combining the <code class="highlighter-rouge">for..in</code> and the <code class="highlighter-rouge">if</code> syntax together:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">numbers</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">11</span><span class="p">)</span> + +<span class="c1"># Filter even numbers only. +</span><span class="p">[</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">numbers</span><span class="p">))</span> <span class="k">if</span> <span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span> +<span class="c1"># [2, 4, 6, 8, 10] +</span></code></pre></div></div> + +<h3 id="sorting-a-list-in-ascending-order">Sorting a List in Ascending Order</h3> + +<p>In Python, we can sort a list in ascending order simply by calling the <code class="highlighter-rouge">sort</code> method like so:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">people</span> <span class="o">=</span> <span class="p">[</span><span class="s">"John"</span><span class="p">,</span> <span class="s">"Alice"</span><span class="p">,</span> <span class="s">"Poe"</span><span class="p">]</span> +<span class="n">people</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span> +<span class="k">print</span><span class="p">(</span><span class="n">people</span><span class="p">)</span> <span class="c1"># ["Alice", "John", "Poe"] +</span></code></pre></div></div> + +<h3 id="using-filter-function-with-a-list">Using Filter Function with a List</h3> + +<p>Just like its name, we can use the <code class="highlighter-rouge">filter</code> function to filter out our list:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">numbers</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">)</span> + +<span class="n">even_numbers</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">number</span><span class="p">:</span> <span class="n">number</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">,</span> <span class="n">numbers</span><span class="p">)</span> +<span class="c1"># [2, 4, 6, 8, 10] +</span></code></pre></div></div> + +<p>We can break the above statement into two parts:</p> + +<ul> + <li><code class="highlighter-rouge">lambda number: statement</code>: The first part is the function that we would like to run to every item on the list. <code class="highlighter-rouge">number</code> is the variable name we’d like to use in this function to refer to a single item from the <code class="highlighter-rouge">numbers</code> list. The following function body must evaluate to truthy/falsy value—falsy means the current item will be removed from the final result.</li> + <li><code class="highlighter-rouge">numbers</code>: The second parameter is the list that we’d like to filter.</li> +</ul> + +<h3 id="using-reduce-with-a-list-of-dictionary">Using Reduce with a List of Dictionary</h3> + +<p>We can use the <code class="highlighter-rouge">reduce</code> function to calculate the total of a particular key in a list of a dictionary:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">items</span> <span class="o">=</span> <span class="p">[{</span><span class="n">value</span><span class="p">:</span><span class="mi">10</span><span class="p">},</span> <span class="p">{</span><span class="n">value</span><span class="p">:</span><span class="mi">20</span><span class="p">},</span> <span class="p">{</span><span class="n">value</span><span class="p">:</span><span class="mi">50</span><span class="p">}]</span> + +<span class="c1"># Calculate the total of value key. +</span><span class="n">totalValues</span> <span class="o">=</span> <span class="nb">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">total</span><span class="p">,</span> <span class="n">item</span><span class="p">:</span> <span class="n">total</span> <span class="o">+</span> <span class="n">item</span><span class="p">[</span><span class="s">"value"</span><span class="p">],</span> <span class="n">items</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="c1"># 80 +</span></code></pre></div></div> + +<p>It can be broken down into 4 parts:</p> + +<ul> + <li><code class="highlighter-rouge">lambda total</code>: It’s the variable name that we’d like to use in the function body to refer to the carried or the accumulative value that will finally be returned.</li> + <li><code class="highlighter-rouge">item: statement</code>: <code class="highlighter-rouge">item</code> is the name of the variable we’d like to use within the function body to refer to the single item in the <code class="highlighter-rouge">items</code> list. The following function body will be executed in order to define the accumulative value of <code class="highlighter-rouge">total</code> for the next iteration.</li> + <li><code class="highlighter-rouge">items</code>: It’s the list of item that we would like to “reduce”.</li> + <li><code class="highlighter-rouge">0</code>: The last parameter is optional and it’s the initial accumulative value for the first iteration.</li> +</ul> + +<p>We can also use this <code class="highlighter-rouge">reduce</code> function to find a single item from the list. Here’s an example of code to find the person with the biggest <code class="highlighter-rouge">total_payments</code> within the given list of <code class="highlighter-rouge">people</code> dictionary.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">people</span> <span class="o">=</span> <span class="p">[</span> + <span class="p">{</span><span class="s">"name"</span><span class="p">:</span> <span class="s">"John"</span><span class="p">,</span> <span class="s">"total_payments"</span><span class="p">:</span> <span class="mi">100</span><span class="p">},</span> + <span class="p">{</span><span class="s">"name"</span><span class="p">:</span> <span class="s">"Alice"</span><span class="p">,</span> <span class="s">"total_payments"</span><span class="p">:</span> <span class="mi">1000</span><span class="p">},</span> + <span class="p">{</span><span class="s">"name"</span><span class="p">:</span> <span class="s">"Poe"</span><span class="p">,</span> <span class="s">"total_payments"</span><span class="p">:</span> <span class="mi">800</span><span class="p">}</span> +<span class="p">]</span> + +<span class="n">person_biggest_total_payments</span> <span class="o">=</span> <span class="nb">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">paid_most</span><span class="p">,</span> <span class="n">person</span><span class="p">:</span> <span class="n">person</span> <span class="k">if</span> <span class="n">person</span><span class="p">[</span><span class="s">"total_payments"</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">paid_most</span><span class="p">[</span><span class="s">"total_payments"</span><span class="p">]</span> <span class="k">else</span> <span class="n">paid_most</span><span class="p">,</span> <span class="n">people</span><span class="p">,</span> <span class="p">{</span> <span class="s">"total_payments"</span><span class="p">:</span> <span class="mi">0</span> <span class="p">})</span> +<span class="c1"># {'name': 'Alice', 'total_payments': 1000} +</span></code></pre></div></div> + +<h2 id="working-with-dictionary">Working with Dictionary</h2> + +<h3 id="loop-through-dictionary">Loop Through Dictionary</h3> + +<p>We can use the <code class="highlighter-rouge">itervalues</code> method to loop through a dictionary:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">people</span><span class="o">.</span><span class="n">itervalues</span><span class="p">():</span> + <span class="k">print</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="s">"email_address"</span><span class="p">])</span> +</code></pre></div></div> + +<p>We can also use the <code class="highlighter-rouge">iteritems</code> method if we want to access the key too:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">people</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span> + <span class="k">print</span><span class="p">(</span><span class="n">person</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">": "</span> <span class="o">+</span> <span class="n">person</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s">"email_address"</span><span class="p">])</span> +</code></pre></div></div> + +<h3 id="calculate-total-of-particular-dictionary-key">Calculate Total of Particular Dictionary Key</h3> + +<p>Suppose we would like to calculate the total amount of <code class="highlighter-rouge">salary</code> key on a <code class="highlighter-rouge">people</code> dictionary. We can extract the <code class="highlighter-rouge">salary</code> key and use the <code class="highlighter-rouge">sum</code> function to get the total:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">total_salary</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">person</span><span class="p">[</span><span class="s">"salary"</span><span class="p">]</span> <span class="k">for</span> <span class="n">person</span> <span class="ow">in</span> <span class="n">people</span><span class="o">.</span><span class="n">itervalues</span><span class="p">()])</span> +</code></pre></div></div> + +<h2 id="working-with-numpy">Working with Numpy</h2> + +<h3 id="numpy-create-range-of-values-with-the-given-interval">Numpy Create Range of Values with The Given Interval</h3> + +<p>Use the <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html"><code class="highlighter-rouge">arange</code></a> method to create an array with an evenly spaced interval.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span> + +<span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> +<span class="c1"># array([0,1,2,3,4]) +</span> +<span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">)</span> +<span class="c1"># array([1. , 1.5, 2. , 2.5, 3. , 3.5]) +</span></code></pre></div></div> + +<h3 id="numpy-create-coordinate-matrices-from-coordinate-vectors">Numpy Create Coordinate Matrices from Coordinate Vectors</h3> + +<p>We can use the Numpy <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html"><code class="highlighter-rouge">meshgrid</code></a> method to make coordinate matrices from one-dimentional coordinate arrays.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span> + +<span class="n">np</span><span class="o">.</span><span class="n">meshgrid</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">7</span><span class="p">])</span> +<span class="c1"># [ +# array([[1,2,3], [1,2,3]]), +# array([[0,0,0], [7,7,7]]) +# ] +</span></code></pre></div></div> + +<h3 id="flatten-numpy-array">Flatten Numpy Array</h3> + +<p>When we have a multi-dimensional Numpy array, we can easily flatten it with the <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html"><code class="highlighter-rouge">ravel</code></a> method:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span> + +<span class="n">arr</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]])</span> +<span class="n">arr</span><span class="o">.</span><span class="n">ravel</span><span class="p">()</span> +<span class="c1"># array([1, 2, 3, 4]) +</span></code></pre></div></div> + +<h3 id="pairing-array-values-with-second-axis">Pairing Array Values with Second Axis</h3> + +<p>We can use Numpy <code class="highlighter-rouge">c_</code> function to pair array values with another array that will be it’s second axis. Read the <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.c_.html"><code class="highlighter-rouge">numpy.c_</code> documentation</a>.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span> + +<span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> +<span class="n">y</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">20</span><span class="p">]</span> + +<span class="n">np</span><span class="o">.</span><span class="n">c_</span><span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span> +<span class="c1"># array([1,10], [2,20]) +</span></code></pre></div></div> + +<h3 id="generate-coordinates-across-the-grid">Generate Coordinates Across The Grid</h3> + +<p>With the knowledge of Numpy <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html"><code class="highlighter-rouge">arange</code></a>, <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html"><code class="highlighter-rouge">meshgrid</code></a>, <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html"><code class="highlighter-rouge">ravel</code></a> and <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.c_.html"><code class="highlighter-rouge">c_</code></a> methods, we can easily generate an evenly spaced coordinates across the grid so we can pass it to the classifier and plot the decision surface.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span> + +<span class="c1"># Generate an evenly spaced coordinates. +</span><span class="n">x_points</span><span class="p">,</span> <span class="n">y_points</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">meshgrid</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="n">x_min</span><span class="p">,</span> <span class="n">x_max</span><span class="p">,</span> <span class="n">step</span><span class="p">),</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="n">y_min</span><span class="p">,</span> <span class="n">y_max</span><span class="p">,</span> <span class="n">step</span><span class="p">))</span> + +<span class="c1"># Pair the x and y points. +</span><span class="n">test_coordinates</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">c_</span><span class="p">[</span><span class="n">x_points</span><span class="o">.</span><span class="n">ravel</span><span class="p">(),</span> <span class="n">y_points</span><span class="o">.</span><span class="n">ravel</span><span class="p">()]</span> +</code></pre></div></div> + +<h2 id="plotting-the-data">Plotting the Data</h2> + +<h3 id="plot-the-surface-decision">Plot The Surface Decision</h3> + +<p>We can pass an evenly spaced coordinates across the grid to the classifier to predict the output on each of that coordinate. We can then use <a href="https://matplotlib.org/api/pyplot_api.html"><code class="highlighter-rouge">matplotlib.pyplot</code></a> to plot the surface decision.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span> +<span class="kn">import</span> <span class="nn">pylab</span> <span class="k">as</span> <span class="n">pl</span> + +<span class="c1"># Pass coordinates across the grid. +</span><span class="n">predicted_labels</span> <span class="o">=</span> <span class="n">classifier</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">test_coordinates</span><span class="p">)</span> + +<span class="c1"># Don't forget to reshape the output array dimension. +</span><span class="n">predicted_labels</span> <span class="o">=</span> <span class="n">predicted_labels</span><span class="o">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">x_points</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span> + +<span class="c1"># Set the axes limit. +</span><span class="n">plt</span><span class="o">.</span><span class="n">xlim</span><span class="p">(</span><span class="n">x_points</span><span class="o">.</span><span class="nb">min</span><span class="p">(),</span> <span class="n">x_points</span><span class="o">.</span><span class="nb">max</span><span class="p">())</span> +<span class="n">plt</span><span class="o">.</span><span class="n">ylim</span><span class="p">(</span><span class="n">y_points</span><span class="o">.</span><span class="nb">min</span><span class="p">(),</span> <span class="n">y_points</span><span class="o">.</span><span class="nb">max</span><span class="p">())</span> + +<span class="c1"># Plot the decision boundary with seismic color map. +</span><span class="n">plt</span><span class="o">.</span><span class="n">pcolormesh</span><span class="p">(</span><span class="n">x_points</span><span class="p">,</span> <span class="n">y_points</span><span class="p">,</span> <span class="n">predicted_labels</span><span class="p">,</span> <span class="n">cmap</span> <span class="o">=</span> <span class="n">pl</span><span class="o">.</span><span class="n">cm</span><span class="o">.</span><span class="n">seismic</span><span class="p">)</span> +</code></pre></div></div> + +<p>The classifier output would be a one-dimensional array, so don’t forget to <a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html"><code class="highlighter-rouge">reshape</code></a> it back into a two-dimensional array before plotting. The <code class="highlighter-rouge">cmap</code> is an optional parameter for the color map. Here we use the <code class="highlighter-rouge">seismic</code> color map from <code class="highlighter-rouge">pylab</code> module. It has the red-blue colors.</p> + +<h3 id="scatter-plot">Scatter Plot</h3> + +<p>We need to separate the test points based on its predicted label (the speed). So we can plot the test points with two different colors.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Separate fast (label = 0) &amp; slow (label = 1) test points. +</span><span class="n">grade_fast</span> <span class="o">=</span> <span class="p">[</span><span class="n">features_test</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">features_test</span><span class="p">))</span> <span class="k">if</span> <span class="n">labels_test</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span> +<span class="n">bumpy_fast</span> <span class="o">=</span> <span class="p">[</span><span class="n">features_test</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">features_test</span><span class="p">))</span> <span class="k">if</span> <span class="n">labels_test</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">]</span> +<span class="n">grade_slow</span> <span class="o">=</span> <span class="p">[</span><span class="n">features_test</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">features_test</span><span class="p">))</span> <span class="k">if</span> <span class="n">labels_test</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">]</span> +<span class="n">bumpy_slow</span> <span class="o">=</span> <span class="p">[</span><span class="n">features_test</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">features_test</span><span class="p">))</span> <span class="k">if</span> <span class="n">labels_test</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">]</span> + +<span class="c1"># Plot the test points based on its speed. +</span><span class="n">plt</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">grade_fast</span><span class="p">,</span> <span class="n">bumpy_fast</span><span class="p">,</span> <span class="n">color</span> <span class="o">=</span> <span class="s">"b"</span><span class="p">,</span> <span class="n">label</span> <span class="o">=</span> <span class="s">"fast"</span><span class="p">)</span> +<span class="n">plt</span><span class="o">.</span><span class="n">scatter</span><span class="p">(</span><span class="n">grade_slow</span><span class="p">,</span> <span class="n">bumpy_slow</span><span class="p">,</span> <span class="n">color</span> <span class="o">=</span> <span class="s">"r"</span><span class="p">,</span> <span class="n">label</span> <span class="o">=</span> <span class="s">"slow"</span><span class="p">)</span> + +<span class="c1"># Show the plot legend. +</span><span class="n">plt</span><span class="o">.</span><span class="n">legend</span><span class="p">()</span> + +<span class="c1"># Add the axis labels. +</span><span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s">"grade"</span><span class="p">)</span> +<span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s">"bumpiness"</span><span class="p">)</span> + +<span class="c1"># Show the plot. +</span><span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span> +</code></pre></div></div> + +<p>If we want to save the plot into an image, we can use the <code class="highlighter-rouge">savefig</code> method instead:</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plt</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="s">'scatter_plot.png'</span><span class="p">)</span> +</code></pre></div></div> + +<h2 id="dealing-with-data">Dealing with Data</h2> + +<h3 id="deserializing-python-object">Deserializing Python Object</h3> + +<p>We can use <a href="https://docs.python.org/2/library/pickle.html"><code class="highlighter-rouge">pickle</code></a> module for serializing and deserializing Python object. There’s also the <code class="highlighter-rouge">cPickle</code>—the faster C implementation. We use both of these modules to deserialize the email text and author list.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pickle</span> +<span class="kn">import</span> <span class="nn">cPickle</span> + +<span class="c1"># Unpickling or deserializing the texts. +</span><span class="n">texts_file_handler</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">texts_file</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> +<span class="n">texts</span> <span class="o">=</span> <span class="n">cPickle</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">texts_file_handler</span><span class="p">)</span> +<span class="n">texts_file_handler</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> + +<span class="c1"># Unpickling or deserializing the authors. +</span><span class="n">authors_file_handler</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">authors_file</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> +<span class="n">authors</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">authors_file_handler</span><span class="p">)</span> +<span class="n">authors_file_handler</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> +</code></pre></div></div> + +<h3 id="split-data-for-training-and-testing">Split Data for Training and Testing</h3> + +<p>We can use the built-in <a href="http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html"><code class="highlighter-rouge">train_test_split</code></a> function from scikit-learn to split the data both for training and testing.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sklearn.model_selection</span> <span class="kn">import</span> <span class="n">train_test_split</span> + +<span class="n">features_train</span><span class="p">,</span> <span class="n">features_test</span><span class="p">,</span> <span class="n">labels_train</span><span class="p">,</span> <span class="n">labels_test</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">texts</span><span class="p">,</span> <span class="n">authors</span><span class="p">,</span> <span class="n">test_size</span> <span class="o">=</span> <span class="mf">0.1</span><span class="p">,</span> <span class="n">random_state</span> <span class="o">=</span> <span class="mi">42</span><span class="p">)</span> +</code></pre></div></div> + +<p>The <code class="highlighter-rouge">test_size</code> argument is the proportion of data to split into the test, in our case we split 10% for testing.</p> + +<h3 id="vectorized-the-strings">Vectorized the Strings</h3> + +<p>When working with a text document, we need to vectorize the strings into a list of numbers so it’s easier and more efficient to process. We can use the <a href="http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html"><code class="highlighter-rouge">TfidfVectorizer</code></a> class to vectorize the strings into a matrix of TF-IDF features.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">sklearn.feature_extraction.text</span> <span class="kn">import</span> <span class="n">TfidfVectorizer</span> + +<span class="n">vectorizer</span> <span class="o">=</span> <span class="n">TfidfVectorizer</span><span class="p">(</span><span class="n">sublinear_tf</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">max_df</span> <span class="o">=</span> <span class="mf">0.5</span><span class="p">,</span> <span class="n">stop_words</span> <span class="o">=</span> <span class="s">"english"</span><span class="p">)</span> +<span class="n">features_train_transformed</span> <span class="o">=</span> <span class="n">vectorizer</span><span class="o">.</span><span class="n">fit_transform</span><span class="p">(</span><span class="n">features_train</span><span class="p">)</span> +<span class="n">features_test_transformed</span> <span class="o">=</span> <span class="n">vectorizer</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">features_test</span><span class="p">)</span> +</code></pre></div></div> + +<p>Word with a frequency higher than the <code class="highlighter-rouge">max_df</code> will be ignored. Stop words are also ignored—stop words are the most common words in a language (e.g. a, the, has).</p> + +<h3 id="feature-selection">Feature Selection</h3> + +<p>Text can have a lot of features thus it may slow to compute. We can use scikit <a href="http://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectPercentile.html"><code class="highlighter-rouge">SelectPercentile</code></a> class to select only the important features.</p> + +<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">selector</span> <span class="o">=</span> <span class="n">SelectPercentile</span><span class="p">(</span><span class="n">f_classif</span><span class="p">,</span> <span class="n">percentile</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> +<span class="n">selector</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">features_train_transformed</span><span class="p">,</span> <span class="n">labels_train</span><span class="p">)</span> +<span class="n">selected_features_train_transformed</span> <span class="o">=</span> <span class="n">selector</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">features_train_transformed</span><span class="p">)</span><span class="o">.</span><span class="n">toarray</span><span class="p">()</span> +<span class="n">selected_features_test_transformed</span> <span class="o">=</span> <span class="n">selector</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">features_test_transformed</span><span class="p">)</span><span class="o">.</span><span class="n">toarray</span><span class="p">()</span> +</code></pre></div></div> + +<p>The <code class="highlighter-rouge">percentile</code> is the percentage of features that we’d like to select based on its highest score.</p> + +<h5 id="this-article-is-for-demo-purpose-1">This article is for Demo purpose</h5> + +<p>The article was originally on <a href="https://github.com/risan/risanb.com/blob/master/content/posts/python-notes-from-intro-to-machine-learning/index.md">this repo</a></p>Klisé Themeyour-email@email.comThis article is for Demo purposeReact Component with Dot Notation2018-04-07T23:04:00+07:002018-04-07T23:04:00+07:00http://localhost:4000/react-component-with-dot-notation<h5 id="this-article-is-for-demo-purpose">This article is for Demo purpose</h5> + +<p>The article was originally on <a href="https://github.com/risan/risanb.com/blob/master/content/posts/react-component-with-dot-notation/index.md">this repo</a></p> + +<p>This is my answer to someone’s question on <a href="https://stackoverflow.com/questions/49256472/react-how-to-extend-a-component-that-has-child-components-and-keep-them/49258038#answer-49258038">StackOverflow</a>. How can we define a React component that is accessible through the dot notation?</p> + +<p>Take a look at the following code. We have the <code class="highlighter-rouge">Menu</code> component and its three children <code class="highlighter-rouge">Menu.Item</code>:</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">App</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">(</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>Home<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>Blog<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">&gt;</span> +<span class="p">);</span> +</code></pre></div></div> + +<p>How can we define a component like <code class="highlighter-rouge">Menu</code>? Where it has some kind of “sub-component” that is accessible through a dot notation.</p> + +<p>Well, it’s actually a pretty common pattern. And it’s not really a sub-component, it’s just another component being attached to another one.</p> + +<p>Let’s use the above <code class="highlighter-rouge">Menu</code> component for example. We’ll put this component to its own dedicated file: <code class="highlighter-rouge">menu.js</code>. First, let’s define these two components separately on this module file:</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// menu.js</span> +<span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s1">'react'</span><span class="p">;</span> + +<span class="k">export</span> <span class="kd">const</span> <span class="nx">MenuItem</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="si">{</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;;</span> + +<span class="k">export</span> <span class="k">default</span> <span class="kd">const</span> <span class="nx">Menu</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span><span class="si">{</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;;</span> +</code></pre></div></div> + +<p>It’s just a simple functional component. The <code class="highlighter-rouge">Menu</code> is the parent with <code class="highlighter-rouge">ul</code> tag. And the <code class="highlighter-rouge">MenuItem</code> will act as its children. Now we can use these two components like so:</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span> +<span class="k">import</span> <span class="p">{</span> <span class="nx">render</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"react-dom"</span><span class="p">;</span> +<span class="k">import</span> <span class="nx">Menu</span><span class="p">,</span> <span class="p">{</span> <span class="nx">MenuItem</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"./menu"</span><span class="p">;</span> + +<span class="kd">const</span> <span class="nx">App</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">(</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">MenuItem</span><span class="p">&gt;</span>Home<span class="p">&lt;/</span><span class="nc">MenuItem</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">MenuItem</span><span class="p">&gt;</span>Blog<span class="p">&lt;/</span><span class="nc">MenuItem</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">MenuItem</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nc">MenuItem</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">&gt;</span> +<span class="p">);</span> + +<span class="nx">render</span><span class="p">(&lt;</span><span class="nc">App</span> <span class="p">/&gt;,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"root"</span><span class="p">));</span> +</code></pre></div></div> + +<p>Where’s the dot notation? To make our <code class="highlighter-rouge">MenuItem</code> component accessible through the dot nation, we can simply attach it to the <code class="highlighter-rouge">Menu</code> component as a static property. To do so, we can no longer use the functional component for <code class="highlighter-rouge">Menu</code> and switch to the class component instead:</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// menu.js</span> +<span class="k">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="k">from</span> <span class="s1">'react'</span><span class="p">;</span> + +<span class="k">export</span> <span class="k">default</span> <span class="kd">const</span> <span class="nx">MenuItem</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="si">{</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;;</span> + +<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">Menu</span> <span class="kd">extends</span> <span class="nx">Component</span> <span class="p">{</span> + <span class="kr">static</span> <span class="nx">Item</span> <span class="o">=</span> <span class="nx">MenuItem</span><span class="p">;</span> + + <span class="nx">render</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="p">(</span> + <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span><span class="si">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span> + <span class="p">);</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div></div> + +<p>Now we can use the dot notation to declare the <code class="highlighter-rouge">MenuItem</code> component:</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span> +<span class="k">import</span> <span class="p">{</span> <span class="nx">render</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"react-dom"</span><span class="p">;</span> +<span class="k">import</span> <span class="nx">Menu</span> <span class="k">from</span> <span class="s2">"./menu"</span><span class="p">;</span> + +<span class="kd">const</span> <span class="nx">App</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">(</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>Home<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>Blog<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span>About<span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">.</span><span class="nc">Item</span><span class="p">&gt;</span> + <span class="p">&lt;/</span><span class="nc">Menu</span><span class="p">&gt;</span> +<span class="p">);</span> + +<span class="nx">render</span><span class="p">(&lt;</span><span class="nc">App</span> <span class="p">/&gt;,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"root"</span><span class="p">));</span> +</code></pre></div></div> + +<p>You can also put the <code class="highlighter-rouge">MenuItem</code> component definition directly within the <code class="highlighter-rouge">Menu</code> class. But this way you can no longer import <code class="highlighter-rouge">MenuItem</code> individually.</p> + +<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="k">from</span> <span class="s2">"react"</span><span class="p">;</span> + +<span class="k">export</span> <span class="k">default</span> <span class="kd">class</span> <span class="nx">Menu</span> <span class="kd">extends</span> <span class="nx">Component</span> <span class="p">{</span> + <span class="kr">static</span> <span class="nx">Item</span> <span class="o">=</span> <span class="p">({</span> <span class="nx">children</span> <span class="p">})</span> <span class="o">=&gt;</span> <span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="si">{</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;;</span> + + <span class="nx">render</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span><span class="si">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">children</span><span class="si">}</span><span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;;</span> + <span class="p">}</span> +<span class="p">}</span> +</code></pre></div></div> + +<h5 id="this-article-is-for-demo-purpose-1">This article is for Demo purpose</h5> + +<p>The article was originally on <a href="https://github.com/risan/risanb.com/blob/master/content/posts/react-component-with-dot-notation/index.md">this repo</a></p>Klisé Themeyour-email@email.comThis article is for Demo purpose \ No newline at end of file diff --git a/_site/how-this-site-was-made/index.html b/_site/how-this-site-was-made/index.html new file mode 100644 index 0000000..b9223c4 --- /dev/null +++ b/_site/how-this-site-was-made/index.html @@ -0,0 +1,7 @@ + How this site was born 👶 - Klise Theme

How this site was born 👶

The website was made using Jekyll the one of open source static sites generator, and using my own simple theme, I called klisé.


All the services are free, source code the site was placed on my github repository and intergration with netlify service, another service that you can use is github page for hosting your own static site.


Let’s do this

So, before we start create a site, you need some tools, you can self paced for how to installing each tools, on this guide i’m just want to show you how to install jekyll and deploying in netlify, but make sure you have each tools below.

Prerequisites

Requirements before we doing magic show.

Installation

First, you need some SSG, there are many kind ssg, but in case i’m using Jekyll cause i’m already familiar with it, open your terminal and type command on below

$ bundle install jekyll # installing jekyll in your machine
+$ jekyll new my-site && cd my-site # create new jekyll project
+$ jekyll s # run jekyll server
+

Now, jekyll is running on your local machine, open your browser and go to localhost:4000 is default address from jekyll, press CTRL + C to stop the jekyll server.

Adding remote repository

Before we adding remote repository, you must have github repository, if already have repository, just add github remote address to your local folder, with the following commands

$ git init # initializing project folder
+$ git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPO.git # change UPPERCASE with your own!
+$ git add -A && git commit -m "Initialize" && git push -u origin master # push code to github
+

Now check your github repository, make sure the files is uploaded correctly.

Deploying to netlify

Go netlify dashboard, and following this step.

  1. click new site from git, then choose Github.
  2. then choose your repository where is the jekyll sources uploaded.
  3. netlify smart enough to configuring, we just need’s are hosting’s are hosting’s are hosting’s are hosting to click Deploy site button.

Wait for moment, and voila..! your site’s are hosting and using .netlify.com tld, if your website wants to look professional, just buy a domain from your favorite domain store. or if you the first time, I advice using namecheap.com(isn’t sponsor) *based on my experienced it provides good service and have various TLDs.

So, what you waiting for, just create your own website for free.

updated_at 29-08-2019
diff --git a/_site/index.html b/_site/index.html new file mode 100644 index 0000000..3933b3d --- /dev/null +++ b/_site/index.html @@ -0,0 +1 @@ + Klise Theme
username

Klisé Theme

He's writing in Bahasa about web technology and experience as a journal for documentation things that he learned, meet him @github.

Recent Posts

diff --git a/_site/notes/index.html b/_site/notes/index.html new file mode 100644 index 0000000..622beb7 --- /dev/null +++ b/_site/notes/index.html @@ -0,0 +1,5 @@ + Pub Notes - Klise Theme

Pub Notes.

Rails 6 db:system:change –to command

Untuk menggunakan perintah db:system:change pada rails 6 perlu menentukan database adapter dengan --to option.

rails db:system:change --to=<adapter>
+# <adapter> : postgresql, mysql, sqlite3, oracle, sqlserver, dll...
+

Setelah menjalankan perintah diatas, jangan lupa untuk mengubah versi database adapter di Gemfile.


Mematikan Jekyll Server

Mengehentikan server Jekyll dengan tombol CTRL + Z tidak menghentikan proses secara penuh, untuk menangani hal ini matikan PID dengan cara ini.

$ lsof -wni tcp:4000
+$ kill -9 <PID of process>
+

Dan lain waktu, gunakan CTRL + C untuk menghentikan server.

diff --git a/_site/now.json b/_site/now.json new file mode 100644 index 0000000..b6dcfd5 --- /dev/null +++ b/_site/now.json @@ -0,0 +1,7 @@ +{ + "version": 2, + "routes": [ + { "handle": "filesystem" }, + { "src": "/.*", "status": 404, "dest": "404.html" } + ] +} diff --git a/_site/python-notes-from-Intro-to-machine-learning/index.html b/_site/python-notes-from-Intro-to-machine-learning/index.html new file mode 100644 index 0000000..3e47736 --- /dev/null +++ b/_site/python-notes-from-Intro-to-machine-learning/index.html @@ -0,0 +1,219 @@ + Python Notes from Intro to Machine Learning - Klise Theme

Python Notes from Intro to Machine Learning

This article is for Demo purpose

The article was originally on this repo

I rarely use Python. I only have one repository at Github that is written in Python: iris-flower-classifier. And it was written two years ago!

A few days ago I took this free course from Udacity: Intro to Machine Learning. The machine learning related codes are quite easy to grasp since it simply uses the scikit-learn modules. But most of the supporting Python modules that are provided by this course were like a black-box to me. I had no idea how to download a file in Python or what’s the difference between a list, a tuple and a dictionary.

That’s why I decided to read all of the provided Python modules and implement it myself. I ended up refactor most of the code so it’s easier to understand: github.com/risan/intro-to-machine-learning.

So here are some notes and snippets of Python that I’ve been collecting so far (I’m not even halfway through the course 😝). Also, note that the codes here are still using Python version 2.7.

Table of Contents

Modules Classes and Functions

Main Entry File

Suppose our Python project is stored in /foo/bar directory. And this application has one file that serves as the single entry point. We can name this file __main__.py so we can run this project simply be referencing its directory path:

# Referencing its directory.
+$ python /foo/bar
+
+# It's equivalent to this.
+$ python /foo/bar/__main__.py
+

Import Python Module Dynamically

Suppose we would like to import a Python module dynamically based on a variable value. We can achieve this through the __import__ function:

module_name = "numpy"
+
+__import__(module_name)
+

Multiple Returns in Python

In Python, it’s possible for a function or a method to return multiple values. We can do this simply by separating each return value by a comma:

def test():
+    return 100, "foo"
+
+someNumber, someString = test()
+

Importing Modules Outside of the Directory

In order to import a module from outside of the directory, we need to add that module’s directory path into the current file with sys.path.append. Suppose we have the following directory structure:

|--foo
+| |-- bar.py
+|
+|-- tools
+| |-- speak_yoda.py
+

If we want to use the speak_yoda.py module within the bar.py, we can do the following:

# /foo/bar.py
+import os
+
+# Use relative path to tools directory.
+sys.path.append("../tools")
+
+import speak_yoda
+

However, this won’t work if we run the baz.py file from outside of its foo directory:

# It works inside of the /foo directory.
+$ cd /foo
+$ python bar.py
+
+# But it won't work if the code runs from outside of /foo directory.
+$ python foo/bar.py
+

To solve this problem we can refer to the tools directory using its absolute path.

# /foo/bar.py
+import os
+import sys
+
+# Get the directory name for this file.
+current_dirname = os.path.dirname(os.path.realpath(__file__))
+
+# Use the absolute path to the tools directory
+tools_path = os.path.abspath(os.path.join(dirname, "../tools"))
+sys.path.append(tools_path)
+
+import speak_yoda
+

Output

It turns out you can’t just print an emoji or any other Unicode characters to the console. You need to specify the encoding type beforehand:

# coding: utf8
+
+print("😅")
+

Pretty Print

We can use the pprint module to pretty-print Python data structure with a configurable indentation:

import pprint
+pp = pprint.PrettyPrinter(indent=2)
+
+pp.pprint(people)
+

Working with Pathname

Read more about pathname manipulations in the os.path documentation.

Get Filename From URL

Suppose the last segment of the URL contains a filename that we would like to download. We can extract this filename with the following code:

import os
+from urlparse import urlparse
+
+url = "https://example.com/foo.txt"
+
+url_components = urlparse(url)
+
+filename = os.path.basename(url_components.path) # foo.txt
+

Check if File Exists

To check whether the given file path exists or not:

import os
+
+is_exists = os.path.isfile("foo.txt")
+

Create a Directory if It Does Not Exists

To create a directory only if it does not exist:

import os
+import errno
+
+try:
+    os.makedirs(directory_path)
+except OSError, e:
+    if e.errno != errno.EEXIST:
+        raise
+

Working with Files

Downloading a File

We can use the urllib module to download a file in Python. The first argument is the file URL that we would like to download. The second argument is the optional filename that will be used to store the file.

import urllib
+
+urllib.urlretrieve("https://example.com/foo.txt", "foo.txt")
+

Extracting Tar File

There’s a built-in tarfile module that we can use to work with Tar file in Python. To extract the tar.gz file we can use the following code:

import tarfile
+
+# Open the file.
+tfile = tarfile.open("foo.tar.gz")
+
+# Extract the file to the given path.
+tfile.extractall(path)
+

We can pass the mode argument to the open method. By default, the mode would be r—reading mode with transparent compression. There are also other mode options that we can use:

  • r:gz: Reading mode with gzip compression.
  • r:: Reading mode without compression.
  • a: Appending mode without compression.
  • w: Writting mode without compression.
  • Checkout other available options in tarfile documentation.

Working with List

Generate a List of Random Numbers

Use the for..in syntax to generate a list of random numbers in a one-liner style.

import random
+
+# Initialize internal state of random generator.
+random.seed(42)
+
+# Generate random points.
+randomNumbers = [random.random() for i in range(0, 10)]
+# [0.6394267984578837, 0.025010755222666936, 0.27502931836911926, ...]
+

Pair Values from Two Lists

The built-in zip function can pair values from two lists. However, this zip function will return a list of tuples instead. To get a list of value pairs, we can combine it with for..in syntax:

coordinates = [[x, y] for x,y in zip([5,10,15], [0,1,0])]
+# [[5, 0], [10, 1], [15, 0]]
+

Splitting a List

We can easily split a list in Python by specifying the starting index and it’s ending index. Note that the ending index is excluded from the result.

We can also specify a negative index. And also note that both of these indices are optional!

a = [0,1,2,3,4,5]
+
+a[0:3]  # 0,1,2
+a[1:3]  # 1,2
+a[2:]   # 2,3,4,5
+a[:3]   # 0,1,2
+a[0:-2] # 0,1,2,3
+a[-2:]  # 4,5
+a[:]    # 0,1,2,3,4,5
+

Filtering a List In One Line

We can easily filter a list in Python by combining the for..in and the if syntax together:

numbers = range(1,11)
+
+# Filter even numbers only.
+[numbers[i] for i in range(0, len(numbers)) if numbers[i] % 2 == 0]
+# [2, 4, 6, 8, 10]
+

Sorting a List in Ascending Order

In Python, we can sort a list in ascending order simply by calling the sort method like so:

people = ["John", "Alice", "Poe"]
+people.sort()
+print(people) # ["Alice", "John", "Poe"]
+

Using Filter Function with a List

Just like its name, we can use the filter function to filter out our list:

numbers = range(1, 11)
+
+even_numbers = filter(lambda number: number % 2 == 0, numbers)
+# [2, 4, 6, 8, 10]
+

We can break the above statement into two parts:

  • lambda number: statement: The first part is the function that we would like to run to every item on the list. number is the variable name we’d like to use in this function to refer to a single item from the numbers list. The following function body must evaluate to truthy/falsy value—falsy means the current item will be removed from the final result.
  • numbers: The second parameter is the list that we’d like to filter.

Using Reduce with a List of Dictionary

We can use the reduce function to calculate the total of a particular key in a list of a dictionary:

items = [{value:10}, {value:20}, {value:50}]
+
+# Calculate the total of value key.
+totalValues = reduce(lambda total, item: total + item["value"], items, 0) # 80
+

It can be broken down into 4 parts:

  • lambda total: It’s the variable name that we’d like to use in the function body to refer to the carried or the accumulative value that will finally be returned.
  • item: statement: item is the name of the variable we’d like to use within the function body to refer to the single item in the items list. The following function body will be executed in order to define the accumulative value of total for the next iteration.
  • items: It’s the list of item that we would like to “reduce”.
  • 0: The last parameter is optional and it’s the initial accumulative value for the first iteration.

We can also use this reduce function to find a single item from the list. Here’s an example of code to find the person with the biggest total_payments within the given list of people dictionary.

people = [
+    {"name": "John", "total_payments": 100},
+    {"name": "Alice", "total_payments": 1000},
+    {"name": "Poe", "total_payments": 800}
+]
+
+person_biggest_total_payments = reduce(lambda paid_most, person: person if person["total_payments"] > paid_most["total_payments"] else paid_most, people, { "total_payments": 0 })
+# {'name': 'Alice', 'total_payments': 1000}
+

Working with Dictionary

Loop Through Dictionary

We can use the itervalues method to loop through a dictionary:

for person in people.itervalues():
+    print(person["email_address"])
+

We can also use the iteritems method if we want to access the key too:

for person in people.iteritems():
+    print(person[0] + ": " + person[1]["email_address"])
+

Calculate Total of Particular Dictionary Key

Suppose we would like to calculate the total amount of salary key on a people dictionary. We can extract the salary key and use the sum function to get the total:

total_salary = sum([person["salary"] for person in people.itervalues()])
+

Working with Numpy

Numpy Create Range of Values with The Given Interval

Use the arange method to create an array with an evenly spaced interval.

import numpy as np
+
+np.arange(0, 5, 1)
+# array([0,1,2,3,4])
+
+np.arange(1, 4, 0.5)
+# array([1. , 1.5, 2. , 2.5, 3. , 3.5])
+

Numpy Create Coordinate Matrices from Coordinate Vectors

We can use the Numpy meshgrid method to make coordinate matrices from one-dimentional coordinate arrays.

import numpy as np
+
+np.meshgrid([1, 2, 3], [0, 7])
+# [
+#   array([[1,2,3], [1,2,3]]),
+#   array([[0,0,0], [7,7,7]])
+# ]
+

Flatten Numpy Array

When we have a multi-dimensional Numpy array, we can easily flatten it with the ravel method:

import numpy as np
+
+arr = np.array([[1,2], [3,4]])
+arr.ravel()
+# array([1, 2, 3, 4])
+

Pairing Array Values with Second Axis

We can use Numpy c_ function to pair array values with another array that will be it’s second axis. Read the numpy.c_ documentation.

import numpy as np
+
+x = [1,2]
+y = [10,20]
+
+np.c_[x, y]
+# array([1,10], [2,20])
+

Generate Coordinates Across The Grid

With the knowledge of Numpy arange, meshgrid, ravel and c_ methods, we can easily generate an evenly spaced coordinates across the grid so we can pass it to the classifier and plot the decision surface.

import numpy as np
+
+# Generate an evenly spaced coordinates.
+x_points, y_points = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step))
+
+# Pair the x and y points.
+test_coordinates = np.c_[x_points.ravel(), y_points.ravel()]
+

Plotting the Data

Plot The Surface Decision

We can pass an evenly spaced coordinates across the grid to the classifier to predict the output on each of that coordinate. We can then use matplotlib.pyplot to plot the surface decision.

import matplotlib.pyplot as plt
+import pylab as pl
+
+# Pass coordinates across the grid.
+predicted_labels = classifier.predict(test_coordinates)
+
+# Don't forget to reshape the output array dimension.
+predicted_labels = predicted_labels.reshape(x_points.shape)
+
+# Set the axes limit.
+plt.xlim(x_points.min(), x_points.max())
+plt.ylim(y_points.min(), y_points.max())
+
+# Plot the decision boundary with seismic color map.
+plt.pcolormesh(x_points, y_points, predicted_labels, cmap = pl.cm.seismic)
+

The classifier output would be a one-dimensional array, so don’t forget to reshape it back into a two-dimensional array before plotting. The cmap is an optional parameter for the color map. Here we use the seismic color map from pylab module. It has the red-blue colors.

Scatter Plot

We need to separate the test points based on its predicted label (the speed). So we can plot the test points with two different colors.

# Separate fast (label = 0) & slow (label = 1) test points.
+grade_fast = [features_test[i][0] for i in range(0, len(features_test)) if labels_test[i] == 0]
+bumpy_fast = [features_test[i][1] for i in range(0, len(features_test)) if labels_test[i] == 0]
+grade_slow = [features_test[i][0] for i in range(0, len(features_test)) if labels_test[i] == 1]
+bumpy_slow = [features_test[i][1] for i in range(0, len(features_test)) if labels_test[i] == 1]
+
+# Plot the test points based on its speed.
+plt.scatter(grade_fast, bumpy_fast, color = "b", label = "fast")
+plt.scatter(grade_slow, bumpy_slow, color = "r", label = "slow")
+
+# Show the plot legend.
+plt.legend()
+
+# Add the axis labels.
+plt.xlabel("grade")
+plt.ylabel("bumpiness")
+
+# Show the plot.
+plt.show()
+

If we want to save the plot into an image, we can use the savefig method instead:

plt.savefig('scatter_plot.png')
+

Dealing with Data

Deserializing Python Object

We can use pickle module for serializing and deserializing Python object. There’s also the cPickle—the faster C implementation. We use both of these modules to deserialize the email text and author list.

import pickle
+import cPickle
+
+# Unpickling or deserializing the texts.
+texts_file_handler = open(texts_file, "r")
+texts = cPickle.load(texts_file_handler)
+texts_file_handler.close()
+
+# Unpickling or deserializing the authors.
+authors_file_handler = open(authors_file, "r")
+authors = pickle.load(authors_file_handler)
+authors_file_handler.close()
+

Split Data for Training and Testing

We can use the built-in train_test_split function from scikit-learn to split the data both for training and testing.

from sklearn.model_selection import train_test_split
+
+features_train, features_test, labels_train, labels_test = train_test_split(texts, authors, test_size = 0.1, random_state = 42)
+

The test_size argument is the proportion of data to split into the test, in our case we split 10% for testing.

Vectorized the Strings

When working with a text document, we need to vectorize the strings into a list of numbers so it’s easier and more efficient to process. We can use the TfidfVectorizer class to vectorize the strings into a matrix of TF-IDF features.

from sklearn.feature_extraction.text import TfidfVectorizer
+
+vectorizer = TfidfVectorizer(sublinear_tf = True, max_df = 0.5, stop_words = "english")
+features_train_transformed = vectorizer.fit_transform(features_train)
+features_test_transformed = vectorizer.transform(features_test)
+

Word with a frequency higher than the max_df will be ignored. Stop words are also ignored—stop words are the most common words in a language (e.g. a, the, has).

Feature Selection

Text can have a lot of features thus it may slow to compute. We can use scikit SelectPercentile class to select only the important features.

selector = SelectPercentile(f_classif, percentile = 10)
+selector.fit(features_train_transformed, labels_train)
+selected_features_train_transformed = selector.transform(features_train_transformed).toarray()
+selected_features_test_transformed = selector.transform(features_test_transformed).toarray()
+

The percentile is the percentage of features that we’d like to select based on its highest score.

This article is for Demo purpose

The article was originally on this repo

diff --git a/_site/react-component-with-dot-notation/index.html b/_site/react-component-with-dot-notation/index.html new file mode 100644 index 0000000..058950c --- /dev/null +++ b/_site/react-component-with-dot-notation/index.html @@ -0,0 +1,63 @@ + React Component with Dot Notation - Klise Theme

React Component with Dot Notation

This article is for Demo purpose

The article was originally on this repo

This is my answer to someone’s question on StackOverflow. How can we define a React component that is accessible through the dot notation?

Take a look at the following code. We have the Menu component and its three children Menu.Item:

const App = () => (
+  <Menu>
+    <Menu.Item>Home</Menu.Item>
+    <Menu.Item>Blog</Menu.Item>
+    <Menu.Item>About</Menu.Item>
+  </Menu>
+);
+

How can we define a component like Menu? Where it has some kind of “sub-component” that is accessible through a dot notation.

Well, it’s actually a pretty common pattern. And it’s not really a sub-component, it’s just another component being attached to another one.

Let’s use the above Menu component for example. We’ll put this component to its own dedicated file: menu.js. First, let’s define these two components separately on this module file:

// menu.js
+import React from 'react';
+
+export const MenuItem = ({ children }) => <li>{children}</li>;
+
+export default const Menu = ({ children }) => <ul>{children}</ul>;
+

It’s just a simple functional component. The Menu is the parent with ul tag. And the MenuItem will act as its children. Now we can use these two components like so:

import React from "react";
+import { render } from "react-dom";
+import Menu, { MenuItem } from "./menu";
+
+const App = () => (
+  <Menu>
+    <MenuItem>Home</MenuItem>
+    <MenuItem>Blog</MenuItem>
+    <MenuItem>About</MenuItem>
+  </Menu>
+);
+
+render(<App />, document.getElementById("root"));
+

Where’s the dot notation? To make our MenuItem component accessible through the dot nation, we can simply attach it to the Menu component as a static property. To do so, we can no longer use the functional component for Menu and switch to the class component instead:

// menu.js
+import React, { Component } from 'react';
+
+export default const MenuItem = ({ children }) => <li>{children}</li>;
+
+export default class Menu extends Component {
+  static Item = MenuItem;
+
+  render() {
+    return (
+      <ul>{this.props.children}</ul>
+    );
+  }
+}
+

Now we can use the dot notation to declare the MenuItem component:

import React from "react";
+import { render } from "react-dom";
+import Menu from "./menu";
+
+const App = () => (
+  <Menu>
+    <Menu.Item>Home</Menu.Item>
+    <Menu.Item>Blog</Menu.Item>
+    <Menu.Item>About</Menu.Item>
+  </Menu>
+);
+
+render(<App />, document.getElementById("root"));
+

You can also put the MenuItem component definition directly within the Menu class. But this way you can no longer import MenuItem individually.

import React, { Component } from "react";
+
+export default class Menu extends Component {
+  static Item = ({ children }) => <li>{children}</li>;
+
+  render() {
+    return <ul>{this.props.children}</ul>;
+  }
+}
+
This article is for Demo purpose

The article was originally on this repo

diff --git a/_site/resume/index.html b/_site/resume/index.html new file mode 100644 index 0000000..7d77659 --- /dev/null +++ b/_site/resume/index.html @@ -0,0 +1 @@ + Resume - Klise Theme

Resume.

Biography, I am student of Computer Science from Banyuwangi, Indonesia, living in Jogjakarta, willingnes to learn other technology.

Skill

  • Core: HTML, CSS & SASS, Vanilla JavaScript ES6, Ruby, OOP, SOLID.
  • Libraries, Framework & Tools: Ruby On Rails, NPM & Yarn, BEM CSS, Bootstrap, Bulma.
  • Languages: Profecient English, Native Bahasa.

Experience

  • Provincial Students Competition / 9th
    Oct 2017, Jawa Timur, Banyuwangi
    East Java Provincial Level Competency Contest for Web Design.
  • PT Erporate Solusi Global / Apprenticeship
    Oct 2016 - Jan 2017, Yogyakarta, Sleman
    Working with HTML, CSS, Bootstrap, Javascript.

Education

  • University Of AMIKOM Yogyakarta - Bachelor of CS
    May 2018 - now.
  • SMK Negeri 1 Banyuwangi - Software Engineering
    April 2015 - 2018.

I love participating and organizing communities. Together with some friends I founded the Banyuwangi Developer.

I’m pragmatic yet curious. I love what is simple, obvious, consistent. I am passionate about my work. I choose the right idea over my own. I work well in teams and can take responsibilities. Fun to work with.

GitHub / Contact / Email / mahendrata.now.sh

diff --git a/_site/robots.txt b/_site/robots.txt new file mode 100644 index 0000000..d297064 --- /dev/null +++ b/_site/robots.txt @@ -0,0 +1 @@ +Sitemap: http://localhost:4000/sitemap.xml diff --git a/_site/sitemap.xml b/_site/sitemap.xml new file mode 100644 index 0000000..b143d7c --- /dev/null +++ b/_site/sitemap.xml @@ -0,0 +1,41 @@ + + + +http://localhost:4000/react-component-with-dot-notation/ +2018-04-07T23:04:00+07:00 + + +http://localhost:4000/python-notes-from-Intro-to-machine-learning/ +2018-04-14T10:00:00+07:00 + + +http://localhost:4000/how-this-site-was-made/ +2018-09-28T09:45:47+07:00 + + +http://localhost:4000/apa-itu-shell/ +2020-01-25T11:58:47+07:00 + + +http://localhost:4000/cara-memperbarui-fork-repository/ +2020-01-29T01:00:00+07:00 + + +http://localhost:4000/about/ + + +http://localhost:4000/ + + +http://localhost:4000/notes/ + + +http://localhost:4000/resume/ + + +http://localhost:4000/tags/ + + +http://localhost:4000/thanks/ + + diff --git a/_site/tags/index.html b/_site/tags/index.html new file mode 100644 index 0000000..f7e4b6e --- /dev/null +++ b/_site/tags/index.html @@ -0,0 +1 @@ + Tags - Klise Theme diff --git a/_site/thanks/index.html b/_site/thanks/index.html new file mode 100644 index 0000000..3bccc35 --- /dev/null +++ b/_site/thanks/index.html @@ -0,0 +1 @@ + Acknowledgment - Klise Theme

Acknowledgment.

Thanks to amazing people that i met, who help me out from follishness, connecting me with another good person, giving some advice when i’m at a bad things, pulling me from ordinary to be great.


Hopefully the knowledge that I got from them can be useful, and become a charity for them, Aamiin.

diff --git a/about.md b/about.md index 1c48289..1be0041 100644 --- a/about.md +++ b/about.md @@ -6,16 +6,13 @@ excerpt: Hello peeps, I'm student of computer science from Banyuwangi, living in comments: false --- -Hello peeps, I'm student of computer science from Banyuwangi, living in Jogjakarta. This blog for documentation about my programming 🎒 journey, running on jekyll, hosting on netlify and using my [own](http://github.com/piharpi/bangsring) simple theme. +He's a student from Banyuwangi, living in Jogjakarta. the blog for documentation about his programming 🎒 journey, running on jekyll, hosting on [now.sh](http://now.sh) and using his own theme, he name it klisé, he also loves to learning web technology; but he often forgot, that a reason why him doing the writing. -Day to day use Ruby, Javascript and doing fun with HTML/CSS, Ruby on Rails is my fav framework right now, i also willingness to learn another web technology; but i often forgot 🌚. If you have a question about me or else, letter to me. +If you have a question about him or else, just send a letter to him. -You can **[report](https://github.com/piharpi/me/issues/new?template=bug_report.md)** if there is an broken link(s) or somethings else. +You can [report](http://github.com/piharpi/jekyll-klise/issues/new) if there is an broken link(s) or somethings else. -_22 August 2019, Harpi_ +##### may u needs ✨ -### Further information - -- [resume]() _(soon)_ -- justharpi[at]gmail[dot]com -- github.com/piharpi +- {{ site.author.email }} +- github.com/{{ site.author.username }} diff --git a/assets/css/style.scss b/assets/css/style.scss index 4e445d8..9f41894 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -1,3 +1,4 @@ --- --- -@import "main"; \ No newline at end of file + +@import "main"; diff --git a/assets/favicons/android-chrome-96x96.png b/assets/favicons/android-chrome-96x96.png new file mode 100644 index 0000000..db86510 Binary files /dev/null and b/assets/favicons/android-chrome-96x96.png differ diff --git a/assets/favicons/apple-touch-icon.png b/assets/favicons/apple-touch-icon.png new file mode 100644 index 0000000..96770fd Binary files /dev/null and b/assets/favicons/apple-touch-icon.png differ diff --git a/assets/favicons/favicon-16x16.png b/assets/favicons/favicon-16x16.png new file mode 100644 index 0000000..7f31f47 Binary files /dev/null and b/assets/favicons/favicon-16x16.png differ diff --git a/assets/favicons/favicon-32x32.png b/assets/favicons/favicon-32x32.png new file mode 100644 index 0000000..7d8ba7d Binary files /dev/null and b/assets/favicons/favicon-32x32.png differ diff --git a/assets/favicons/favicon.ico b/assets/favicons/favicon.ico new file mode 100644 index 0000000..b1f3051 Binary files /dev/null and b/assets/favicons/favicon.ico differ diff --git a/assets/favicons/mstile-150x150.png b/assets/favicons/mstile-150x150.png new file mode 100644 index 0000000..6645adc Binary files /dev/null and b/assets/favicons/mstile-150x150.png differ diff --git a/assets/favicons/safari-pinned-tab.svg b/assets/favicons/safari-pinned-tab.svg new file mode 100644 index 0000000..d96e929 --- /dev/null +++ b/assets/favicons/safari-pinned-tab.svg @@ -0,0 +1,27 @@ + + + + +Created by potrace 1.11, written by Peter Selinger 2001-2013 + + + + + diff --git a/assets/favicons/site.webmanifest b/assets/favicons/site.webmanifest new file mode 100644 index 0000000..315db41 --- /dev/null +++ b/assets/favicons/site.webmanifest @@ -0,0 +1,14 @@ +{ + "name": "Mahendrata", + "short_name": "Mahendrata", + "icons": [ + { + "src": "/assets/favicons/android-chrome-96x96.png", + "sizes": "96x96", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/assets/img/avatar.jpg b/assets/img/avatar.jpg index 80636e5..6e5e18a 100644 Binary files a/assets/img/avatar.jpg and b/assets/img/avatar.jpg differ diff --git a/assets/img/ogp.png b/assets/img/ogp.png new file mode 100644 index 0000000..a18683c Binary files /dev/null and b/assets/img/ogp.png differ diff --git a/assets/img/posts/p1070511.jpg b/assets/img/posts/p1070511.jpg deleted file mode 100644 index 5d3b9d8..0000000 Binary files a/assets/img/posts/p1070511.jpg and /dev/null differ diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..dbf1cfc --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,35 @@ +(() => { + // Theme switch + const root = document.body; + const themeSwitch = document.getElementById("mood"); + const themeData = root.getAttribute("data-theme"); + + if (themeSwitch) { + initTheme(localStorage.getItem("theme")); + themeSwitch.addEventListener("click", () => + toggleTheme(localStorage.getItem("theme")) + ); + + function toggleTheme(state) { + if (state === "dark") { + localStorage.setItem("theme", "light"); + root.removeAttribute("data-theme"); + } else if (state === "light") { + localStorage.setItem("theme", "dark"); + document.body.setAttribute("data-theme", "dark"); + } else { + initTheme(state); + } + } + + function initTheme(state) { + if (state === "dark") { + document.body.setAttribute("data-theme", "dark"); + } else if (state === "light") { + root.removeAttribute("data-theme"); + } else { + localStorage.setItem("theme", themeData); + } + } + } +})(); diff --git a/bangsring.gemspec b/bangsring.gemspec deleted file mode 100644 index 824af58..0000000 --- a/bangsring.gemspec +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -Gem::Specification.new do |spec| - spec.name = "bangsring" - spec.version = "0.1.0" - spec.authors = ["piharpi"] - spec.email = ["justharpi@gmail.com"] - - spec.summary = "🏖 Bangsring is minimalist Jekyll theme for running a personal site and blog." - spec.homepage = "https://github.com/piharpi/bangsring" - spec.license = "MIT" - - spec.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r!^(assets|_layouts|_includes|_sass|LICENSE|README)!i) } - - spec.add_runtime_dependency "jekyll", "~> 3.8" - - spec.add_development_dependency "jekyll-feed", "~> 0.11.0" - spec.add_development_dependency "jekyll-sitemap" - - spec.add_development_dependency "bundler" -end diff --git a/browserconfig.xml b/browserconfig.xml new file mode 100644 index 0000000..4c5c4ec --- /dev/null +++ b/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #2c2c2c + + + diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..c07973c --- /dev/null +++ b/notes.md @@ -0,0 +1,31 @@ +--- +title: Pub Notes +permalink: /notes/ +layout: page +excerpt: Catatan Public agar enggak usah pusing-pusing mengingat. +comments: false +--- + +#### Rails 6 db:system:change --to command + +Untuk menggunakan perintah `db:system:change` pada rails 6 perlu menentukan database adapter dengan `--to` option. + +```bash +rails db:system:change --to= +# : postgresql, mysql, sqlite3, oracle, sqlserver, dll... +``` + +Setelah menjalankan perintah diatas, jangan lupa untuk mengubah versi database adapter di `Gemfile`. + +--- + +#### Mematikan Jekyll Server + +Mengehentikan server Jekyll dengan tombol CTRL + Z tidak menghentikan proses secara penuh, untuk menangani hal ini matikan `PID` dengan cara ini. + +```bash +$ lsof -wni tcp:4000 +$ kill -9 +``` + +Dan lain waktu, gunakan CTRL + C untuk menghentikan server. diff --git a/now.json b/now.json new file mode 100644 index 0000000..b6dcfd5 --- /dev/null +++ b/now.json @@ -0,0 +1,7 @@ +{ + "version": 2, + "routes": [ + { "handle": "filesystem" }, + { "src": "/.*", "status": 404, "dest": "404.html" } + ] +} diff --git a/resume.md b/resume.md new file mode 100644 index 0000000..f9ef6cf --- /dev/null +++ b/resume.md @@ -0,0 +1,42 @@ +--- +title: Resume +permalink: /resume/ +layout: page +excerpt: Hello I'm Mahendrata Harpi, student of Computer Science, from Banyuwangi, Indonesia, living in Jogjakarta, +comments: false +--- + +Biography, I am student of Computer Science from Banyuwangi, Indonesia, living in Jogjakarta, willingnes to learn other technology. + +#### Skill + +- Core: HTML, CSS & SASS, Vanilla JavaScript ES6, Ruby, OOP, SOLID. +- Libraries, Framework & Tools: Ruby On Rails, NPM & Yarn, BEM CSS, Bootstrap, Bulma. +- Languages: Profecient English, Native Bahasa. + +#### Experience + +- **Provincial Students Competition** / 9th
+ Oct 2017, Jawa Timur, Banyuwangi
+ East Java Provincial Level Competency Contest for Web Design. +- **PT Erporate Solusi Global** / Apprenticeship
+ Oct 2016 - Jan 2017, Yogyakarta, Sleman
+ Working with HTML, CSS, Bootstrap, Javascript. + +#### Education + +- University Of AMIKOM Yogyakarta - Bachelor of CS
+ May 2018 - now. +- SMK Negeri 1 Banyuwangi - Software Engineering
+ April 2015 - 2018. + +--- + +I love participating and organizing communities. Together with some +friends I founded the [Banyuwangi Developer](https://banyuwangidev.org/). + +I’m pragmatic yet curious. I love what is simple, obvious, consistent. I +am passionate about my work. I choose the right idea over my own. I +work well in teams and can take responsibilities. Fun to work with. + +[GitHub](http://github.com/piharpi) / [Contact](https://t.me/piharpi) / [Email](mailto:justharpi@gmail.com) / [mahendrata.now.sh](http://mahendrata.now.sh) diff --git a/thanks.md b/thanks.md index 30f0314..2765c5e 100644 --- a/thanks.md +++ b/thanks.md @@ -6,12 +6,8 @@ excerpt: Thanks to amazing people that i met, who help me out from follishness, comments: false --- -Bismillahirrahmanirrahim, this page for thanks to amazing people that i met, who help me out from follishness, connecting me with another good person, giving some advice when i'm at a bad things, pulling me from ordinary to be great. +Thanks to amazing people that i met, who help me out from follishness, connecting me with another good person, giving some advice when i'm at a bad things, pulling me from ordinary to be great.
-Thanks to my parent, whole teacher, and friends who always supporting me, and special thanks to : - -- Mrs. [Irez]() my teacher at vocational school who always suport me, have owe on she. -- Tama a guy inspiring me to made english content on this site. Hopefully the knowledge that I got from them can be useful, and become a charity for them, Aamiin.