<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MrChoke</title>
    <description>The latest articles on DEV Community by MrChoke (@mrchoke).</description>
    <link>https://dev.to/mrchoke</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F257719%2F6546e05d-4349-4a28-8261-fd5dcf25bab0.jpg</url>
      <title>DEV Community: MrChoke</title>
      <link>https://dev.to/mrchoke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrchoke"/>
    <language>en</language>
    <item>
      <title>GitHub Copilot Custom AutoComplete</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Sun, 23 Jul 2023 22:15:11 +0000</pubDate>
      <link>https://dev.to/mrchoke/github-copilot-custom-autocomplete-1lbj</link>
      <guid>https://dev.to/mrchoke/github-copilot-custom-autocomplete-1lbj</guid>
      <description>&lt;p&gt;การใช้ Github Copilot ช่วยทุ่นแรงในการเขียนโค้ดที่เป็นรูปแบบซ้ำ ๆ เช่นการเตรียมข้อมูล Seed สำหรับ migrate database แค่เราเอาข้อมูลที่แบ่งเป็น fields มาแปะไว้ให้ Copilot เรียนรู้มันก็จะจัดการให้เราแบบรวดเร็ว&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo จาก YouTube
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-ZXQWgd_bTQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;จากตัวอย่างจำลองการ insert ข้อมูลลง table แบบหลาย ๆ row ซึ่งจะมีรูปแบบที่ซ้ำ ๆ กัน โดยได้นำข้อมูลมาแปะขั่วคราวไว้ใน comment ของ code แล้วก็ให้ Copilot ทำการเติมเต็มให้เท่าที่ลองมาจะทำงานค่อนข้างแม่นมาก และ รวดเร็ว คือแปะปุ๊บมันก็เติมให้เลยแทบไม่มีการให้รอเลย ก็ลองเอาไปเล่นกันดูครับ&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>githubcopilot</category>
      <category>autocomplete</category>
    </item>
    <item>
      <title>Fix: Svelte Devtools on Chrome/Brave</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Thu, 28 Jul 2022 14:44:32 +0000</pubDate>
      <link>https://dev.to/mrchoke/fix-svelte-devtools-on-chromebrave-2bj0</link>
      <guid>https://dev.to/mrchoke/fix-svelte-devtools-on-chromebrave-2bj0</guid>
      <description>&lt;p&gt;สืบเนื่องมาจาก Official Svelte Devtools ไม่ยอมทำงานบน Chrome และ Brave เลยค้นหาดูพบว่ามันเป็น Bug และทางต้นน้ำก็ไม่มี update มาปีกว่าแล้ว มีคน  PR เข้าไปแก้ง่าย ๆ แค่หนึงบรรทัดเลยลองทำตามดูก็กลับมาทำงานได้ ใครประสบปัญหาอยู่ก็ลองทำดูได้ครับ ขั้นตอนดังนี้&lt;/p&gt;

&lt;h2&gt;
  
  
  Git Clone
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/sveltejs/svelte-devtools.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Edit
&lt;/h2&gt;

&lt;p&gt;หลังจากนั้นให้แก้ไข &lt;code&gt;dest/devtools/index.js&lt;/code&gt; โดยการลบ &lt;code&gt;/&lt;/code&gt; บรรทัดที่ 6 ออก&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- '/devtools/panel.html',
+ 'devtools/panel.html',
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;ให้ลบของเก่าออกแล้วทำการติดตั้งแบบ &lt;code&gt;Load Unpacked&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QFnyg9wU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja7wbopv34m412j8qpd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QFnyg9wU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ja7wbopv34m412j8qpd5.png" alt="Chrome Extension installation" width="412" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็จะปรากฎ Extension ดังนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SbKVLzx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6a7sqqj4t2vskjmij7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SbKVLzx1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6a7sqqj4t2vskjmij7h.png" alt="Chrome Extension" width="436" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use
&lt;/h2&gt;

&lt;p&gt;หลังจากนั้นก็สามารถใช้งานได้ตามปกติแล้ว&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KB862sTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppu6jgz9cxs6xjsu5vtk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KB862sTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppu6jgz9cxs6xjsu5vtk.png" alt="Svelte Devtools" width="880" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ต้นฉบับ:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/sveltejs/svelte-devtools/pull/78"&gt;https://github.com/sveltejs/svelte-devtools/pull/78&lt;/a&gt; &lt;/p&gt;

</description>
      <category>svelte</category>
      <category>devtools</category>
      <category>chrome</category>
      <category>brave</category>
    </item>
    <item>
      <title>macOS Monterey DNS</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Sun, 27 Feb 2022 05:28:22 +0000</pubDate>
      <link>https://dev.to/mrchoke/macos-monterey-dns-3dnm</link>
      <guid>https://dev.to/mrchoke/macos-monterey-dns-3dnm</guid>
      <description>&lt;p&gt;เข้าใจเสมอว่าแก้ DNS ของ macOS สามารถแก้ใน /etc/resolv.conf ได้เลย แต่ล่าสุดพบว่ามันไม่ได้ให้ความสำคัญแล้ว ถ้าให้ได้ผลต้องตั้งใน UI ให้เรียบร้อย แต่ถ้ายังอยากใช้ command line เราก็ยังใช้ได้ดังนี้&lt;/p&gt;

&lt;h2&gt;
  
  
  ตรวจสอบอุปกรณ์
&lt;/h2&gt;

&lt;p&gt;ก่อนที่เราจะตั้งต่าต้องรู้ก่อนว่าปัจจุบันเราต่อ network ผ่านอุปกรณ์ไหน และ มีอุปกรณ์อะไรบ้างในระบบ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-listallnetworkservices&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ผลที่ได้จะประมาณนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Ethernet
USB 10/100/1000 LAN
Thunderbolt Bridge
Wi-Fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  เรียกดูค่าปัจจุบัน
&lt;/h2&gt;

&lt;p&gt;ถ้าต่อ WiFi ก็แสดงดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-getdnsservers&lt;/span&gt; Wi-Fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือ ถ้าใช้สายแลน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-getdnsservers&lt;/span&gt; Ethernet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ผลที่ได้จะประมาณนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-getdnsservers&lt;/span&gt; Ethernet
10.222.21.14
10.222.21.15
10.18.12.222
10.18.12.223
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  การตั้งค่า
&lt;/h2&gt;

&lt;p&gt;หากต้องการล้มกระดานแล้วใช้ DNS ที่ต้องการตั้งครั้งนี้ก็ใช้คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-setdnsservers&lt;/span&gt; Ethernet 10.26.21.14 10.26.21.15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แต่ถ้าต้องการเพิ่มเข้าไปก็ให้ get ค่าเดิม แล้วต่อท้ายเข้าไป เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-getdnsservers&lt;/span&gt; Ethernet
10.222.21.14
10.222.21.15

networksetup &lt;span class="nt"&gt;-setdnsservers&lt;/span&gt; Ethernet 10.222.21.14 10.222.21.15 10.18.12.222 10.18.12.223
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือถ้าต้องการ clear ไปเลยก็&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networksetup &lt;span class="nt"&gt;-setdnsservers&lt;/span&gt; Ethernet Emty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ลองเอาไปประยุกต์ใช้กันดูครับ&lt;/p&gt;

</description>
      <category>monterey</category>
      <category>macos</category>
      <category>dns</category>
    </item>
    <item>
      <title>การใช้ Pydantic Model กับ Form Data ใน FastAPI</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Fri, 25 Feb 2022 03:44:07 +0000</pubDate>
      <link>https://dev.to/mrchoke/kaaraich-pydantic-model-kab-form-data-ain-fastapi-b0k</link>
      <guid>https://dev.to/mrchoke/kaaraich-pydantic-model-kab-form-data-ain-fastapi-b0k</guid>
      <description>&lt;p&gt;ปกติถ้าหากจำนวน Fields ใน Form มีไม่มากก็ไม่มีปัญหาเราสามารถเขียนแบบปกติได้ เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/abc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;abc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(...),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;single&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แต่ถ้า Fields มีเยอะ ๆ สัก 10 Fields ขึ้นไป Code ก็จะเริ่มดูยากยาวมาก การใช้ Pydantic model เข้ามาช่วยก็จะจัดการง่ายขึ้น ปกติเราใช้ Pydantic model  ใน Body แบบ JSON กันอยู่แล้วแต่สำหรับ Form Data จะมีลูกเล่นนิดหนึ่ง ค้นหาใน internet ไปเจอวิธีที่คิดว่าง่ายที่สุดละเลยบันทึกไว้สักหน่อย&lt;/p&gt;

&lt;h3&gt;
  
  
  ต้นฉบับที่ผมนำมาใช้
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/a/65547551" rel="noopener noreferrer"&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ตัวอย่าง model.py
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Form&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;form_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__signature__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__signature__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_empty&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(...))&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__signature__&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;

&lt;span class="nd"&gt;@form_body&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;passport_no&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;hn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;patient_guid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;นาย&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;prefix_eng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;first_name_eng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;middle_name_eng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;last_name_eng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;gender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;birth_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;mobile_phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;installed_line_connect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;moo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;road&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;chw_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;amp_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;tmb_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;address_full_thai&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;address_full_english&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;nationality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ในส่วนของ Form มันจะมีหลัก ๆ อยู่สามแบบคือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;บังคับ&lt;/li&gt;
&lt;li&gt;มีค่า Default&lt;/li&gt;
&lt;li&gt;มีก็ได้ไม่มีก็ได้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ผมเลยปรับในตัว Decorators เพิ่มเติมให้มันปรับตาม Model ที่เรากำหนดไว้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_empty&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="p"&gt;(...))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ตัวอย่าง Router
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Profile&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UploadFile&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/abc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;abc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Profile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Profile&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UploadFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(...)):&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ตอน Render ก็จะได้ประมาณนี้
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz3xlxpfzjzo3lekx25q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz3xlxpfzjzo3lekx25q.png" alt="Swagger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowv4d0v6awnu5s90da7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowv4d0v6awnu5s90da7y.png" alt="Swagger input with default"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ลองเอาไปประยุกต์ใช้กันดูครับ&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>pydantic</category>
      <category>formdata</category>
      <category>python</category>
    </item>
    <item>
      <title>การเลือก WebCam บน Google Colab ในกรณีมีมากกว่า 1 ตัว</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Sun, 20 Feb 2022 20:22:39 +0000</pubDate>
      <link>https://dev.to/mrchoke/kaareluuek-webcam-bn-google-colab-ainkrniimiimaakkwaa-1-taw-1ndc</link>
      <guid>https://dev.to/mrchoke/kaareluuek-webcam-bn-google-colab-ainkrniimiimaakkwaa-1-taw-1ndc</guid>
      <description>&lt;p&gt;ปกติ Colab ได้เตรียม Snippet เกี่ยวกับการใช้ WebCam มาให้เราแล้วแค่เลือก Code มาใช้แบบง่าย ๆ เลย&lt;/p&gt;

&lt;p&gt;พอดีผมทดสอบ API แล้วใช้ Colab ในการทดสอบ และ แสดงตัวอย่างให้กับ Dev คนอื่น ๆ เลยแก้ไข script นิดหน่อยให้สามารถเลือกกล้องได้ถ้าเราเสียบกล้องมากกว่า 1 ตัว&lt;/p&gt;

&lt;h4&gt;
  
  
  Code ตัวอย่าง
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://colab.research.google.com/drive/1PGWbP5ZEtoCAlYBCqtusCWV0kMAmxnT9?usp=sharing"&gt;Google Colaboratory&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mrchoke"&gt;
        mrchoke
      &lt;/a&gt; / &lt;a href="https://github.com/mrchoke/select_webcam_in_colab"&gt;
        select_webcam_in_colab
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Select WebCam in Google Colab
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
select_webcam_in_colab&lt;/h1&gt;
&lt;p&gt;Select WebCam in Google Colab&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mrchoke/select_webcam_in_colab"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h4&gt;
  
  
  JavaScript
&lt;/h4&gt;

&lt;p&gt;จริง ๆ ผมใช้ JavaScript ที่ใช้งานเป็นประจำอยู่แล้ว ซึ่งสามารถนำไปประยุกต์ใช้กับ JavaScript Framework อื่น ๆ ได้ด้วย&lt;/p&gt;

&lt;h4&gt;
  
  
  ตัวอย่าง
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// define variables&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// current camera id&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// current stream&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// all camera&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// parent div playground&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;camera_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// camera dropdown&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;camera_label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// current selected camera&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// video object&lt;/span&gt;

&lt;span class="c1"&gt;// scan all cameras&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;scan_cameras&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera_found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enumerateDevices&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;deviceInfos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;deviceInfos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videoinput&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;camera_found&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;camera_label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Camera: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
              &lt;span class="nx"&gt;camera_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deviceId&lt;/span&gt;
              &lt;span class="nx"&gt;camera_found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deviceInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

      &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera_label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// change camera by id&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;change_camera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;camera_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;camera_label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Camera: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deviceId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;start_camera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// stop all active camera&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;stop_camera&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getVideoTracks&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;track&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// start camera by selected id&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;start_camera&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stop_camera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;video&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;deviceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camera_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="na"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}});&lt;/span&gt;
 &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;srcObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// create camera list dropdown&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;create_camera_select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;camera_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Select Camera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;        

 &lt;span class="nx"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nx"&gt;camera_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;`Camera &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deviceId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;

 &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera_list&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;camera_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;change_camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// take photo&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;takePhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;scan_cameras&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;create_camera_select&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;capture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Capture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;start_camera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setIframeHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Wait for Capture to be clicked.&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stop_camera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sjKVxyt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8chwm94rx90qe2dxdve6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sjKVxyt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8chwm94rx90qe2dxdve6.png" alt="ตัวอย่างการเลือกกล้อง WebCam" width="748" height="716"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ตัวอย่างการเลือกกล้อง WebCam&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ลองเอาไปประยุกต์ใช้กันดูนะครับ น่าจะได้กับการเลือกไมค์บันทึกเสียงได้ด้วยแต่ผมไม่เคยลอง คือหลักการเดียวกันเลย&lt;/p&gt;




</description>
      <category>googlecolab</category>
      <category>webcam</category>
    </item>
    <item>
      <title>docker compose not docker-compose</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Mon, 19 Apr 2021 00:33:40 +0000</pubDate>
      <link>https://dev.to/mrchoke/docker-compose-not-docker-compose-nph</link>
      <guid>https://dev.to/mrchoke/docker-compose-not-docker-compose-nph</guid>
      <description>&lt;p&gt;docker-compose กำลังจะถูก deprecate แล้วใช้ docker compose แทน มาดูว่าใช้ยังไงกัน&lt;/p&gt;

&lt;p&gt;สืบเนื่องมาจาก blog ของ &lt;strong&gt;&lt;em&gt;คุณปุ๋ย&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.somkiat.cc/docker-compose-to-docker-compose/" rel="noopener noreferrer"&gt;https://www.somkiat.cc/docker-compose-to-docker-compose/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ทำให้เกิดอยากลองใช้บ้างซึ่งพบว่า&lt;/p&gt;

&lt;p&gt;บน Docker Desktop macOS สามารถใช้คำสั่งนี้ได้เลย (ลองบน M1) เลยลองบน Ubuntu บ้างพบว่ายังใช้ไม่ได้ เลยตามไปสืบค้นดูพบว่า Project คือ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/docker/compose-cli" rel="noopener noreferrer"&gt;docker/compose-cli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ทำมานานพอสมควรถ้าอ้างตามเอกสารนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/docker/compose-cli/blob/main/INSTALL.md" rel="noopener noreferrer"&gt;docker/compose-cli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker Desktop macOS และ Windows จะถูก built-in ไปแล้วเลยใช้ได้ทันทีเหมือน buildx เลย&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;ตาม link ด้านบนวิธีการติดตั้ง (ผมติดตั้งบน Ubuntu)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -L https://raw.githubusercontent.com/docker/compose-cli/main/scripts/install/install_linux.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เมื่อติดตั้งสำเร็จจะมีคำสั่ง docker เพิ่มขึ้นมาใน path&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/local/bin/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ลองทดสอบดูว่าตอนนี้คำสั่ง docker ถูกเรียกจาก path ไหน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;which docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้ายังเรียกไปที่&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/bin/docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ก็ให้ปิด shell แล้วเปิดใหม่ อ้อ!! ดูลำดับ path ของ PATH ด้วยนะครับว่า /usr/local/bin ต้องอยู่ก่อน /usr/bin&lt;/p&gt;

&lt;p&gt;คราวนี้เราก็สามารถใช้คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ได้แล้วจ้า….&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A08Mfbr7xQ8pOEh9FeYwpFA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A08Mfbr7xQ8pOEh9FeYwpFA.png"&gt;&lt;/a&gt;docker compose&lt;/p&gt;




</description>
      <category>composecli</category>
      <category>ubuntu</category>
      <category>dockercompose</category>
    </item>
    <item>
      <title>Use latexindent on macOS Big Sur</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Wed, 14 Apr 2021 19:23:56 +0000</pubDate>
      <link>https://dev.to/mrchoke/use-latexindent-on-macos-big-sur-45gm</link>
      <guid>https://dev.to/mrchoke/use-latexindent-on-macos-big-sur-45gm</guid>
      <description>&lt;p&gt;ตัวช่วยจัด indent source ของ LaTeX คือ latexindent แต่บน macOS จะต้องติดตั้ง cpan modules เพิ่มเติมนิดหน่อย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can't locate File/HomeDir.pm in [@INC](http://twitter.com/INC) (you may need to install the File::HomeDir module) ([@INC](http://twitter.com/INC) contains: /usr/local/texlive/2021/texmf-dist/scripts/latexindent /Library/Perl/5.30/darwin-thread-multi-2level /Library/Perl/5.30 /Network/Library/Perl/5.30/darwin-thread-multi-2level /Network/Library/Perl/5.30 /Library/Perl/Updates/5.30.2 /System/Library/Perl/5.30/darwin-thread-multi-2level /System/Library/Perl/5.30 /System/Library/Perl/Extras/5.30/darwin-thread-multi-2level /System/Library/Perl/Extras/5.30) at /usr/local/texlive/2021/texmf-dist/scripts/latexindent/LatexIndent/GetYamlSettings.pm line 22.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าเจอ error นี้ให้ติดตั้ง modules ต่างๆ ดังนี้&lt;/p&gt;

&lt;p&gt;เริ่มแรกให้กำหนด CPATH ให้ชี้ให้ถูกต้อง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export CPATH=/Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk/System/Library/Perl/5.30/darwin-thread-multi-2level/CORE:$CPATH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หลังจากนั้นก็ให้ติดตั้ง CPAN Modules&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cpan install File:HomeDir
cpan install Unicode::GCString
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ปล. ผมเลือก sudo ตอนที่ CPAN ถามนะครับ&lt;/p&gt;

</description>
      <category>latexindent</category>
      <category>perl</category>
      <category>macos</category>
      <category>latex</category>
    </item>
    <item>
      <title>เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP2</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Thu, 25 Mar 2021 22:54:05 +0000</pubDate>
      <link>https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep2-2cgo</link>
      <guid>https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep2-2cgo</guid>
      <description>&lt;h3&gt;
  
  
  เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP2
&lt;/h3&gt;

&lt;p&gt;หลังจากสามารถจัดการและใช้งาน Docker Container ได้แล้วคราวนี้ลองมาเขียน LaTeX กับ VSCode กันดูครับ ถ้าใครไม่เคยเขียนมาก่อนก็คงต้องทำการบ้านมาบ้าง เพราะผมไม่ได้ลงรายละเอียดทั้งหมด&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep1-18aj"&gt;เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP1&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Attach Container
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F934%2F1%2AIjHZcRbiKZXsK-f0PirBCw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F934%2F1%2AIjHZcRbiKZXsK-f0PirBCw.png"&gt;&lt;/a&gt;Attach to New Window&lt;/p&gt;

&lt;p&gt;เลือกรูป Computer บน Side Bar ด้านซ้าย แล้วก็ Click ขวาบนชื่อ Container ที่เราต้องการใช้งาน (สั่ง run ไว้ก่อนหน้านี้แล้ว) แล้วเลือก &lt;code&gt;Attach in New Window&lt;/code&gt; ก็จะปรากฎหน้าต่างใหม่ขึ้นมาดังรูปถัดไป&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAP240OqZUZaye7l67ow5-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AAP240OqZUZaye7l67ow5-Q.png"&gt;&lt;/a&gt;Workspace ใหม่&lt;/p&gt;

&lt;p&gt;ซึ่งจะมี Terminal ของ Container มาให้ด้วยให้เราสร้าง Folder สำหรับทำเขียน LaTeX ด้วยคำสั่งดังนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaIGthVEtrPkNPmqN10FEzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaIGthVEtrPkNPmqN10FEzg.png"&gt;&lt;/a&gt;สร้าง Folder&lt;/p&gt;

&lt;p&gt;เนื่องจากตอนเราสร้าง container ได้มีการ mount volume ไว้ใน /root/data ดังนั้นให้เราเข้าไปใน /root/data แล้วสร้าง folder ขึ้นมา 1 folder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /root/data/latex1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จะสั่งแบบในรูปหรือสั่งตามตัวอย่างก็ได้&lt;/p&gt;

&lt;h3&gt;
  
  
  เปิด Folder ใน Workspace
&lt;/h3&gt;

&lt;p&gt;เปิดจาก terminal ง่ายๆ ด้วยคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code /root/data/latex1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือจะใช้ mouse click ที่รูป icon files บน Side Bar ด้านซ้าย และ Click ที่ปุ่ม Open Folder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcSEPrOV_f5HarrkVv6uoGQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AcSEPrOV_f5HarrkVv6uoGQ.png"&gt;&lt;/a&gt;Click Open Folder&lt;/p&gt;

&lt;p&gt;ใส่ path หรือจะ Click เลือกไปเรื่อยๆ ก็ได้ดังรูปด้านล่าง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwFiGwYY5I-Gfe6IspkOB3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwFiGwYY5I-Gfe6IspkOB3g.png"&gt;&lt;/a&gt;เลือก Folder ที่เราสร้างไว้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1012%2F1%2AAgUFH0RwTc2Ub8E53YbwTw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1012%2F1%2AAgUFH0RwTc2Ub8E53YbwTw.png"&gt;&lt;/a&gt;สร้าง File ใหม่&lt;/p&gt;

&lt;p&gt;เมื่อเปิด Folder เรียบร้อยให้ Click ที่ icon new file หรือ Click ขวาบนพื้นที่ว่างในช่อง แล้วเลือก New File จาก Menu ดังรูปด้านบน&lt;/p&gt;

&lt;p&gt;ตั้งชื่อ file1.tex&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbrW_sT4WeTPnSo6Tsymsqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AbrW_sT4WeTPnSo6Tsymsqg.png"&gt;&lt;/a&gt;New File&lt;/p&gt;

&lt;p&gt;ใส่คำสั่ง LaTeX แรกดังตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\title&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;My First &lt;span class="k"&gt;\LaTeX&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; Document&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\author&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;MrChoke&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\date&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\today&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
   &lt;span class="k"&gt;\maketitle&lt;/span&gt;
   Hello &lt;span class="k"&gt;\LaTeX&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; world!
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;อ่านเกี่ยวกับ LaTeX เพิ่มเติมได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/ff54de4b800cb059c6627c3b4733d06d/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/ff54de4b800cb059c6627c3b4733d06d/href" rel="noopener noreferrer"&gt;https://medium.com/media/ff54de4b800cb059c6627c3b4733d06d/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaiTwdtXIbhBIG98zhmyhSA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AaiTwdtXIbhBIG98zhmyhSA.png"&gt;&lt;/a&gt;คำสั่ง LaTeX&lt;/p&gt;

&lt;p&gt;หลังจากนี้เราสามารถสั่งให้ Build คำสั่งนี้ได้แล้วโดยการ Click ที่ปุ่มสีเขียวด้านบนขวา&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F278%2F1%2A7n11aG_uvz9FWUufbo2c5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F278%2F1%2A7n11aG_uvz9FWUufbo2c5w.png"&gt;&lt;/a&gt;ปุ่มคำสั่งของ LaTeX Workshop Extension&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7i3WJ7ct04M7eJrm-YLlug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7i3WJ7ct04M7eJrm-YLlug.png"&gt;&lt;/a&gt;หลังจาก Build&lt;/p&gt;

&lt;p&gt;ถ้าหาก Build สำเร็จจะมี files ต่างๆ เกิดขึ้นทางด้านซ้ายมือ โดยเฉพาะ PDF File คือเป้าหมายของเราถ้ามี Error ตัว Extension ก็จะแจ้งเตือนเรามา ก็ต้องไล่อ่านว่าเกิดจากอะไร&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFM46W1RCzKfcOzmN9sYOeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFM46W1RCzKfcOzmN9sYOeQ.png"&gt;&lt;/a&gt;PDF View&lt;/p&gt;

&lt;p&gt;ถ้าเราต้องการแสดงผล PDF ก็ให้ Click ที่ปุ่มถัดจากปุ่ม Build สีเขียว ที่มีรูปแว่นขยาย ก็จะได้เหมือนรูปด้านบน หลังจากนี้ถ้าเราแก้ไขคำสั่ง LaTeX แล้ว save มันก็จะทำการ Build ให้อัตโนมัติและแสดงผล PDF ให้ทันทีด้วยเช่นกัน&lt;/p&gt;

&lt;p&gt;สำหรับค่า defualt จากตัวอย่างด้านบนตอนสั่ง build จะใช้ engine pdfLaTeX นะครับ&lt;/p&gt;

&lt;h3&gt;
  
  
  ภาษาไทย
&lt;/h3&gt;

&lt;p&gt;ถ้าเราเขียนเอกสารภาษาอังกฤษก็สบายหน่อยเพราะตัวอย่างข้างบนก็เพียงพอแล้วแต่ถ้าเราจะใช้ภาษาไทยใน LaTeX ละเราต้องทำอย่างไร และ ต้องรู้อะไรบ้าง&lt;/p&gt;

&lt;h4&gt;
  
  
  เลือก Engine
&lt;/h4&gt;

&lt;p&gt;การใช้ LaTeX Engine ที่นิยมหลักๆ ก็จะมี&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pdfLaTeX&lt;/li&gt;
&lt;li&gt;XeLaTeX&lt;/li&gt;
&lt;li&gt;LuaLaTeX&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  pdfLaTeX
&lt;/h4&gt;

&lt;p&gt;โครงการภาษาไทยสำหรับ LaTeX หรือ ThaiLaTeX เป็นโครงการแรกๆ ที่ Contribute สภาวะแวดล้อมการใช้งานภาษาไทยเข้าไป อ่านรายละเอียดได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://linux.thai.net/projects/thailatex" rel="noopener noreferrer"&gt;https://linux.thai.net/projects/thailatex&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ซึ่งหลัก ๆ เป็นการกำหนดสภาวะแวดล้อมภาษาไทยให้ pdfLaTeX เนื่องจาก pdfLaTeX ค่อนข้างล้าสมัยการใช้ fonts ก็มีข้อจำกัดไม่สามารถใช้ fonts ใหม่ๆ อย่าง OpenType ได้การตัดคำก็ต้องทำเองก่อนจะทำการ Build Project การ shapping สระ และ วรรณยุกต์ก็ยังต้องใช้แบบเก่า&lt;/p&gt;

&lt;p&gt;มาดูตัวอย่างการใช้ภาษาไทยด้วย pdfLaTeX กันครับ&lt;/p&gt;

&lt;h4&gt;
  
  
  pdfLaTeX — Thai LaTeX
&lt;/h4&gt;

&lt;p&gt;ตัวอย่างคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[thai]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;babel&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8x]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;inputenc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fonts-tlwg&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
สวัสดีชาวโลก
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AN_MJMmew89kKe-mJc52RjA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AN_MJMmew89kKe-mJc52RjA.png"&gt;&lt;/a&gt;ตัวอย่าง Thai LaTeX กับ pdfLaTeX&lt;/p&gt;

&lt;p&gt;ตั้งแต่บรรทัดที่ 2–4 เป็นสิ่งจำเป็นที่ต้องประกาศเสมอไม่งั้นจะใช้งานภาษาไทยไม่ถูกต้อง&lt;/p&gt;

&lt;h4&gt;
  
  
  FONTS TLWG
&lt;/h4&gt;

&lt;p&gt;Fonts ภาษาไทยหลักที่ bundle ไปกับ TeX Live ก็จะมีชุดของ TLWG (Thai Linux Working Group) ดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[thai]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;babel&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8x]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;inputenc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fonts-tlwg&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;kinnari&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Kinnari สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;garuda&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Garuda สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;norasi&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Norasi สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;laksaman&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Laksaman สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;purisa&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Purisa สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;loma&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Loma สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;sawasdee&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Sawasdee สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;ttype&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Ttype สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;ttypist&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; TTypist สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;umpush&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Umpush สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontfamily&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;waree&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\selectfont&lt;/span&gt; Waree สวัสดีชาวโลก
&lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;

&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlBc1s3KNPRbj2qtyHM4j7Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlBc1s3KNPRbj2qtyHM4j7Q.png"&gt;&lt;/a&gt;fonts-tlwg&lt;/p&gt;

&lt;h4&gt;
  
  
  การเลือก Default Font
&lt;/h4&gt;

&lt;p&gt;ปกติถ้าเราใช้ Thai LaTeX font ที่ถูกใช้คือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Norasi สำหรับ Roman Font&lt;/li&gt;
&lt;li&gt;Garuda สำหรับ Sans Serif Font&lt;/li&gt;
&lt;li&gt;TlwgTypist สำหรับ Type Writer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;แต่ถ้าเราจะเลือก font ตัวอื่นในรายการด้านบนให้เราประกาศใน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fonts-tlwg&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;โดยการกำหนด option ดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[fontname]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fonts-tlwg&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[thai]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;babel&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8x]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;inputenc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[purisa]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fonts-tlwg&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
เป็นมนุษย์สุดประเสริฐเลิศคุณค่า กว่าบรรดาฝูงสัตว์เดรัจฉาน
จงฝ่าฟันพัฒนาวิชาการ อย่าล้างผลาญฤๅเข่นฆ่าบีฑาใคร
ไม่ถือโทษโกรธแช่งซัดฮึดฮัดด่า หัดอภัยเหมือนกีฬาอัชฌาสัย
ปฏิบัติประพฤติกฎกำหนดใจ พูดจาให้จ๊ะๆ จ๋า น่าฟังเอยฯ

ธรรมคุณหนุนความดีฑีฆรัตน์ สรรพสัตว์วัฏวจรถอนวิถี
อริยสัจตรัสสังโยคโลกโมฬี ดังกุมภีร์ผลาญชิวหาบีฑาทนต์
ฟังฉัตรทองของประเสริฐเลิศวิเศษ ฝ่ายต้นเหตุฎรงกรณ์อุดรผล
ยินสถานฌานสมาอารยะชน พึงซ่อนกลปรนนิบัตินิวัฒน์แฮฯ
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACcoIWinyVJE-eSWDa8z_Qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACcoIWinyVJE-eSWDa8z_Qw.png"&gt;&lt;/a&gt;Purisa&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATOMiHgDeXRxSIpyDtrlnzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATOMiHgDeXRxSIpyDtrlnzw.png"&gt;&lt;/a&gt;Laksaman&lt;/p&gt;

&lt;p&gt;อ่านเพิ่มเติมได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/tlwg/fonts-tlwg/master/latex/README.latex" rel="noopener noreferrer"&gt;https://raw.githubusercontent.com/tlwg/fonts-tlwg/master/latex/README.latex&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  การตัดคำ
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6FnegsMxUHjt3Imsglqkxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6FnegsMxUHjt3Imsglqkxg.png"&gt;&lt;/a&gt;without word/line break&lt;/p&gt;

&lt;p&gt;สังเกตว่าการตัดคำและบรรทัดยังแปลกๆ มีการใส่ hyphen ยังไม่ถูกต้องนัก ใน TeX Live Docker image ผมใส่ swath ไปให้แล้วเราสามารถสั่งตัดคำได้เลยโดยสั่งดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swath &lt;span class="nt"&gt;-f&lt;/span&gt; latex &lt;span class="nt"&gt;-u&lt;/span&gt; u,u &amp;lt; original.tex &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; processed.tex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จากคำสั่งด้านบน&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;-f latex กำหนด format เป็น LaTeX&lt;/li&gt;
&lt;li&gt;-u u,u encoding แบบ utf-8 to utf-8 ถ้าสมัยก่อนอาจจะต้องใข้ TIS-620 แต่ปัจจุบันเรา process เป็น UTF-8 ได้เลย&lt;/li&gt;
&lt;li&gt;&amp;lt; original.tex คือ file ต้นฉบับที่นำเข้า&lt;/li&gt;
&lt;li&gt;&amp;gt; processed.tex คือ นำออก file จากผลที่ประมวลผลเรียบร้อยแล้ว&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;หลังจากนั้นเราก็นำ file ที่ตัดคำแล้วไป build ต่อ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5wPPbS6HDznhu7QiVNfnMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5wPPbS6HDznhu7QiVNfnMg.png"&gt;&lt;/a&gt;LaTeX Source ที่ถูกตัดคำเรียบร้อยแล้ว&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlNAnIuJDCj8KLop_xn8fmQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlNAnIuJDCj8KLop_xn8fmQ.png"&gt;&lt;/a&gt;ผลของการตัดบรรทัด และใส่ Hyphen ได้ถูกต้องขึ้น&lt;/p&gt;

&lt;p&gt;จากตัวอย่าง pdfLaTeX จะเห็นว่าวิธีการยังค่อนข้างซับซ้อนยังต้องมีการตัดคำก่อนที่จะ process และ fonts ที่ใช้ยังเป็นแบบ Type1 การนำ fonts ของระบบหรือ fonts ภายนอกมาใช้ยากมาก&lt;/p&gt;

&lt;h4&gt;
  
  
  XeLaTeX, LuaLaTeX
&lt;/h4&gt;

&lt;p&gt;ทางเลือกที่คนนิยมใช้กันในปัจจุบันคือ XeLaTeX ส่วน LuaLaTeX ผมยังไม่เคยได้ลองแต่เห็นหลายคนบอกว่าคล้ายๆ กัน คือใช้ FontSpec เหมือนกัน และ เกิดมาเพื่อประมวลผลแบบ UTF-8 และที่สำคัญคือมีการใช้ ICU ในการตัดคำซึ่งสนับสนุนหลากหลายภาษารวมทั้งภาษาไทยด้วย&lt;/p&gt;

&lt;h4&gt;
  
  
  สร้าง Workspace ใหม่
&lt;/h4&gt;

&lt;p&gt;สร้าง Folder ใหม่ใน /root/data ชื่อ latex2 ทำใน terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /root/data/latex2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เปิด หน้าต่างใหม่ด้วยคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code /root/data/latex2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  สร้าง Build Tools และ Recipes
&lt;/h4&gt;

&lt;p&gt;ค่าปกติในการ Build LaTeX ของ VSCode LaTeX Workshop Extension คือ pdfLaTeX ส่วน XeLaTeX ไม่ได้จัดเตรียมไว้ให้ การตั้งค่า Extension ทำได้หลายระดับมีตั้งแต่&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เฉพาะ Workspace&lt;/li&gt;
&lt;li&gt;เฉพาะใน Container หรือ SSH&lt;/li&gt;
&lt;li&gt;ตั้งเป็นค่าของเราระดับ USER ก็ได้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ถ้าเราเขียนหลายแบบก็อาจจะแยกเฉพาะ Workspace ก็ได้ให้เปิด&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VSCode Setting → Workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วค้นหาคำว่า&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;latex tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2xyLPCZ0PaAxHDMcOaShJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A2xyLPCZ0PaAxHDMcOaShJg.png"&gt;&lt;/a&gt;Recipes &amp;amp; Tools&lt;/p&gt;

&lt;p&gt;ให้ Click ที่ Edit in settings.json ของ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Latex-workshop -&amp;gt; Latex: Tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วเพิ่ม Block ใหม่โดย Copy จาก lualatex&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xelatexmk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latexmk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-synctex=1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-interaction=nonstopmode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-file-line-error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-xelatex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"-outdir=%OUTDIR%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"%DOC%"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ให้เปลี่ยนชื่อ เป็น xelatexmk และ เปลี่ยน args จาก -lualatex เป็น -xelatex&lt;/p&gt;

&lt;p&gt;save แล้วปิดหน้าต่าง settings.json ไป&lt;/p&gt;

&lt;p&gt;แล้วกลับไป Click ที่ Edit in settings.json ของ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Latex-workshop -&amp;gt; Latex: Recipes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ให้ Copy ฺBlock ของ latexmk (lualatex) แล้วเปลี่ยนให้ตรงกับที่เรากำหนดไว้ใน Tools&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latexmk (xelatex)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"tools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"xelatexmk"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตั้งให้ใช้ Recipe ล่าสุดในการ Build Project&lt;/p&gt;

&lt;p&gt;ให้ค้นหา Setting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;latex recipe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เปลี่ยนจาก first เป็น lastUsed&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxdAtnXEJ1XvEk-BPgG92_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AxdAtnXEJ1XvEk-BPgG92_w.png"&gt;&lt;/a&gt;ให้ใช้ Recipe ล่าสุดเสมอ&lt;/p&gt;

&lt;p&gt;ถ้าไม่ตั้งแบบนี้มันจะใช้ Recipe อันแรกสุดเสมอ เมื่อเพิ่มค่าต่างๆ ครบแล้วให้ทำการ reload หน้าต่างใหม่อีกครั้ง&lt;/p&gt;

&lt;h4&gt;
  
  
  Reload Window
&lt;/h4&gt;

&lt;p&gt;ให้เปิด Command Palette จากเมนู หรือจะกด Shotcut ก็&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View --&amp;gt; Command Palette
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วค้นหาคำว่า&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD3PW7XVX7Lf9cKtwCEbaQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AD3PW7XVX7Lf9cKtwCEbaQg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เลือก Restart Extension Host แล้วกด Reload Window หรือจะปิด-เปิด VSCode ใหม่ก็ได้&lt;/p&gt;

&lt;p&gt;อย่าลืมว่าถ้าเราตั้งค่าในระดับ Workspace ถ้าเราสร้าง Workspace ใหม่เราก็ต้องตั้งค่าเหล่านี้ใหม่ทุกครั้ง หรืออาจจะ copy .vscode ใน folder ไปก็ได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F806%2F1%2AuaaE9lDLlWfRpUeSwqKOsA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F806%2F1%2AuaaE9lDLlWfRpUeSwqKOsA.png"&gt;&lt;/a&gt;Config ของ VSCode ในระดับ Workspace&lt;/p&gt;

&lt;h4&gt;
  
  
  First XeLaTeX
&lt;/h4&gt;

&lt;p&gt;มาลองเขียน XeLaTeX แรกกัน&lt;/p&gt;

&lt;p&gt;สร้าง file1.tex โดย Copy คำสั่งมาจากตัวอย่างแรกของ pdfLaTeX&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\title&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;My First &lt;span class="k"&gt;\LaTeX&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; Document&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\author&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;MrChoke&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\date&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\today&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
   &lt;span class="k"&gt;\maketitle&lt;/span&gt;
   Hello &lt;span class="k"&gt;\LaTeX&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; world!
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หลังจากนั้นให้ Click ที่ Icon TeX บน Side Bar ด้านซ้าย&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKvNTrf3ldPMcJD20xFPPdA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKvNTrf3ldPMcJD20xFPPdA.png"&gt;&lt;/a&gt;LaTeX WorkShop Extension&lt;/p&gt;

&lt;p&gt;ให้ขยายคำสั่ง Build LaTeX project คำสั่งแรกปุ่ม play สีเขียว&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AziyM_tqMALwsmWR4mX9WBg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AziyM_tqMALwsmWR4mX9WBg.png"&gt;&lt;/a&gt;Recipe ต่างๆ สำหรับการ Build Project&lt;/p&gt;

&lt;p&gt;เราจะเห็นคำสั่งต่างๆ สำหรับการ Build Project ให้สังเกตตรง Recipe โดยปกติเวลาเราสั่งให้ Build มันจะเลือกคำสั่งแรกซึ่งเป็น Recipe: latexmk หรือ pdfLaTeX นั่นเองก่อนหน้านี้เราได้จัดเตรียม latexmk ให้ Build XeLaTeX ไว้แล้วจะเห็นใน Recipe ที่ 4 หรือถ้าใครจะ Build LuaLaTeX ก็เลือกจากตรงนี้เหมือนกันครับ ตรงนี้ให้ Click เลือก XeLaTeX ต้องระวังนิดหนึ่งคือก่อน Click ต้องให้ file ที่เราจะ Build ถูก Focus เสมอนั่นคือให้ Click file ก่อนแล้ว Click Build&lt;/p&gt;

&lt;h4&gt;
  
  
  Check
&lt;/h4&gt;

&lt;p&gt;รู้ได้ยังไงว่า Build สำเร็จ ?&lt;/p&gt;

&lt;p&gt;ให้กลับไปที่หน้า Explorer แล้วดูว่ามี file pdf ถูกสร้างขึ้นมาหรือไม่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1leEe7MTkSSj3ekoWHmhpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A1leEe7MTkSSj3ekoWHmhpw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็ลอง Click แสดง pdf ตรง icon มุมขวาบนข้างปุ่ม Build สีเขียว&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F278%2F1%2A7n11aG_uvz9FWUufbo2c5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F278%2F1%2A7n11aG_uvz9FWUufbo2c5w.png"&gt;&lt;/a&gt;ปุ่มคำสั่งของ LaTeX Workshop Extension&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ab1OQlxMBjiigUuF3xvTj4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ab1OQlxMBjiigUuF3xvTj4A.png"&gt;&lt;/a&gt;PDF ที่ได้จาก XeTeX&lt;/p&gt;

&lt;p&gt;เรารู้ได้อย่างไรว่า Extension ใช้ Engine อะไร Build ให้เรา ?&lt;/p&gt;

&lt;p&gt;หลายคนคงสงสัยว่าที่ Build มานั้นใช้ XeLaTeX จริงหรือเปล่า ผมแนะนำอีกอย่างคือการดู Output ของ Extension ให้เลือกเมนู&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;View --&amp;gt; Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วเลือกดู LaTeX Workshop หรือ จะดู LaTeX Compiler ก็แล้วแต่เราจะสนใจนะครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F472%2F1%2AoS25IHXbjXxF-3Xw-2weHw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F472%2F1%2AoS25IHXbjXxF-3Xw-2weHw.png"&gt;&lt;/a&gt;Output ต่างๆ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlfcrcL4kBKVKtUftJC3C1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlfcrcL4kBKVKtUftJC3C1w.png"&gt;&lt;/a&gt;Output&lt;/p&gt;

&lt;p&gt;ถ้าเราสังเกตก็จะเห็นบรรทัดคำสั่ง หรือ Recipe ที่เราสั่งรูปด้านบนก็จะบอกว่าเป็น XeLaTeX&lt;/p&gt;

&lt;p&gt;นอกจากนั้นการวิเคราะห์ log ของ LaTeX เองก็จะช่วยแก้ปัญหาต่างๆ ได้ดูโดยเลือกเปิด file นามสกุล log ที่มีชื่อเดียวกับ LaTeX ของเรา&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6zD2Vvwuge61KlB_cj8CPA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6zD2Vvwuge61KlB_cj8CPA.png"&gt;&lt;/a&gt;file log&lt;/p&gt;

&lt;h4&gt;
  
  
  XeLaTeX กับภาษาไทย
&lt;/h4&gt;

&lt;p&gt;อย่างที่เคยเกริ่นไปก่อนหน้านี้ว่า XeLaTeX นั้นเกิดมาหลังและสนับสนุน UTF-8 , OpenType และ TrueType Font ตั้งแต่แรกอยู่แล้วการใช้งานพวกนี้ก็ถือว่าง่าย&lt;/p&gt;

&lt;h4&gt;
  
  
  ข้อดี
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;สนับสนุน UTF-8,Unicode&lt;/li&gt;
&lt;li&gt;TrueType , OpenType&lt;/li&gt;
&lt;li&gt;สามารถใช้ Fonts นอกเหนือจากที่มีใน TeX Live ได้ คือสามารถใช้ fonts ของระบบได้เลย และ สามารถ copy fonts มาวางไว้กับ source code ได้ด้วย&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ข้อเสีย
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;จากข้อดีข้างบนถ้าคุยกับคนใช้ LaTeX จริงๆ จังๆ เขาอาจจะมองว่าเป็นสิ่งที่อาจจะทำให้เสียความเป็น LaTeX ได้เพราะตอนส่ง source code ให้กันอาจจะลืม Copy Font ให้ไปด้วยเพราะไม่รู้ว่า Font ที่ใช้ ไม่ได้อยู่ใน TeX Live ก็จะเป็นปัญหาคล้ายๆ Microsoft Word ที่แสดงผลผิดพลาดถ้าต้นทางและปลายทางใช้ font ไม่เหมือนกันเป็นต้น&lt;/li&gt;
&lt;li&gt;ณ ปัจจุบัน TeX Live 2021 มี fonts ไทยไปด้วยทั้ง Type1 และ OpenType Font แต่การตั้งค่าให้ Fontspec ใช้งานได้ผู้ใช้ยังต้องออกแรงเองอยู่ คือต้องประกาศเพิ่มเติมถึงจะใช้ได้ หลายคนจึงนิยมใช้ font ที่หามาเอง หรือ font ที่อยู่ในระบบปฎิบัติการ ก็อาจจะเกิดปัญหาตามมาเมื่อส่งมอบ source code ไปให้คนอื่น&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fonts ไทย
&lt;/h3&gt;

&lt;h4&gt;
  
  
  fonts-tlwg
&lt;/h4&gt;

&lt;p&gt;fonts-tlwg มีอยู่แล้วใน TeX Live ที่ติดตั้งแบบทั้งหมด หรือ จะเลือกติดตั้งเพิ่มเติมภายหลังก็ได้การใช้งาน font ใน XeLaTeX จะใช้ package fontspec ซึ่งจะต้องมีการประกาศ font เสียก่อนทำได้หลายแบบ ก่อนอื่นให้ copy file2.tex จากตัวอย่างแรกมาก่อน แล้วแก้ดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fontspec&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
สวัสดีชาวโลก
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วลองสั่ง build ด้วย XeLaTeX Recipes จะไม่มีอะไร error แต่เมื่อสั่ง preview pdf จะไม่เห็นข้อความใด ๆ เลย&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArKtL3Z8y0jHzBNtDj3oEmQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ArKtL3Z8y0jHzBNtDj3oEmQ.png"&gt;&lt;/a&gt;ไม่มี output&lt;/p&gt;

&lt;p&gt;ทีนี้เราลองสั่งเพิ่มเข้าไปหนึ่งบรรทัดคือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Laksaman.otf&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วลอง Build ใหม่อีกรอบก็จะมีข้อความขึ้นมา&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATQ8ZSAPRcA7dTHnCvnRTdw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATQ8ZSAPRcA7dTHnCvnRTdw.png"&gt;&lt;/a&gt;Output ภาษาไทย&lt;/p&gt;

&lt;p&gt;ข้างบนเป็นตัวอย่างหนึ่งที่ง่ายๆ ในการใช้ font แต่เราต้องรู้ชื่อ file font ด้วยนะไม่งั้นมันจะหาไม่ถูก แล้ว fonts-tlwg มี font อะไรบ้างละ ?&lt;/p&gt;

&lt;p&gt;fonts-tlwg ที่มากับ TeX Live จะเก็บใน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;texmf-dist/fonts/opentype/public/fonts-tlwg/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้า Docker Image ของผมจะอยู่ที่&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/usr/local/texlive/2021/texmf-dist/fonts/opentype/public/fonts-tlwg/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;รายชื่อ Files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;Garuda-BoldOblique.otf
Garuda-Bold.otf
Garuda-Oblique.otf
Garuda.otf
Kinnari-BoldItalic.otf
Kinnari-BoldOblique.otf
Kinnari-Bold.otf
Kinnari-Italic.otf
Kinnari-Oblique.otf
Kinnari.otf
Laksaman-BoldItalic.otf
Laksaman-Bold.otf
Laksaman-Italic.otf
Laksaman.otf
Loma-BoldOblique.otf
Loma-Bold.otf
Loma-Oblique.otf
Loma.otf
Norasi-BoldItalic.otf
Norasi-BoldOblique.otf
Norasi-Bold.otf
Norasi-Italic.otf
Norasi-Oblique.otf
Norasi.otf
Purisa-BoldOblique.otf
Purisa-Bold.otf
Purisa-Oblique.otf
Purisa.otf
Sawasdee-BoldOblique.otf
Sawasdee-Bold.otf
Sawasdee-Oblique.otf
Sawasdee.otf
TlwgMono-BoldOblique.otf
TlwgMono-Bold.otf
TlwgMono-Oblique.otf
TlwgMono.otf
TlwgTypewriter-BoldOblique.otf
TlwgTypewriter-Bold.otf
TlwgTypewriter-Oblique.otf
TlwgTypewriter.otf
TlwgTypist-BoldOblique.otf
TlwgTypist-Bold.otf
TlwgTypist-Oblique.otf
TlwgTypist.otf
TlwgTypo-BoldOblique.otf
TlwgTypo-Bold.otf
TlwgTypo-Oblique.otf
TlwgTypo.otf
Umpush-BoldOblique.otf
Umpush-Bold.otf
Umpush-LightOblique.otf
Umpush-Light.otf
Umpush-Oblique.otf
Umpush.otf
Waree-BoldOblique.otf
Waree-Bold.otf
Waree-Oblique.otf
Waree.otf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าสังเกตในตัวอย่างเราจะใช้ font Laksaman.otf ซึ่งเป็น font แบบ Nomal แบบเดียวไม่มีตัวหน้า ตัวเอียงให้ใช้ ลองสั่งดูครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACtFCoXU8jl2l8-eo13AzXA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ACtFCoXU8jl2l8-eo13AzXA.png"&gt;&lt;/a&gt;จะแสดงเป็นตัวธรรมดาทั้งหมด&lt;/p&gt;

&lt;p&gt;fontspec จะมี Options สำหรับการกำหนดค่า font ให้ง่ายขึ้นมาดูตัวอย่าง เพิ่มเติมให้กับ \setmainfont กัน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Extension = .otf ,
  ItalicFont = *-Italic ,
  BoldFont = *-Bold ,
  BoldItalicFont = *-BoldItalic 
]&lt;span class="p"&gt;{&lt;/span&gt;Laksaman&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOXd8BJDALunXxOmsmnKNog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOXd8BJDALunXxOmsmnKNog.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;การกำหนด Font Shape Options นี้ยังสามารถใช้กับ font ที่เรานำมาใช้เอง โดยการ Copy ชุด fonts มาใส่ใน folder project ของเราแล้วประกาศให้ครบตามนี้แต่อย่าลืมว่าแต่ละ font จะมีไม่เหมือนกันบางตัวไม่มีตัวหนา ไม่มีตัวเอียง หรือ จะมีแบบอื่นเพิ่มขึ้นมาเช่น -Oblique , -Regular, -Light เป็นต้นก็ต้องกำหนดให้ถูกต้อง&lt;/p&gt;

&lt;p&gt;ตัวอย่าง Font Shape&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;BoldFont = ⟨font name⟩
ItalicFont = ⟨font name⟩
BoldItalicFont = ⟨font name⟩
SlantedFont = ⟨font name⟩
BoldSlantedFont = ⟨font name⟩
SmallCapsFont = ⟨font name⟩
UprightFont = ⟨font name⟩
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Shaping
&lt;/h4&gt;

&lt;p&gt;ตอนนี้ดูเหมือนจะแสดงภาษาไทยได้แล้วแต่สิ่งที่สำคัญของภาษาไทยอีกอย่างที่เราควรรู้และใส่ใจคือการจัดระดับสระวรรณยุกต์ หรือ Shaping ลองดูตัวอย่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fontspec&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Extension = .otf ,
  ItalicFont = *-Italic ,
  BoldFont = *-Bold ,
  BoldItalicFont = *-BoldItalic 
]&lt;span class="p"&gt;{&lt;/span&gt;Laksaman&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;

ป่า ป้า ป๊ะ ป๋า ญู ฐู ฏู ญ ฐ - -- --- `fi' ``ff"

&lt;span class="k"&gt;\textbf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;ป่า ป้า ป๊ะ ป๋า ญู ฐู ฏู ญ ฐ - -- --- `fi' ``ff"&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\textit&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;ป่า ป้า ป๊ะ ป๋า ญู ฐู ฏู ญ ฐ - -- --- `fi' ``ff" &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\textbf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\textit&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;ป่า ป้า ป๊ะ ป๋า ญู ฐู ฏู ญ ฐ - -- --- `fi' ``ff"&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlXC3NHpOa9UScU35C0QM6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AlXC3NHpOa9UScU35C0QM6w.png"&gt;&lt;/a&gt;สระวรรณยุกต์ภาษาไทยไม่สวย&lt;/p&gt;

&lt;p&gt;จากตัวอย่างเมื่อเราพิมพ์ข้อความภาษาไทยที่มีสระและวรรณยุกต์หลายระดับจะแสดงผลไม่สวยงามอย่าเพิ่งตกใจเมื่อเราใช้ OpenType หรือ TrueType Fonts จะมี Option Script ให้เราเลือกว่าจะใช้ Script แบบไหนใน Fonts-Tlwg ที่เป็น OpenType มี Script Thai ให้เลือกได้เลย วิธีตรวจสอบว่า fonts ที่เราใช้มี Script อะไรบ้างจะใช้คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;otfinfo -s fontname.[ttf,otf]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQGQCWApIkxWrZCMkdYpWEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AQGQCWApIkxWrZCMkdYpWEQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ลองกำหนด Script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Script = Thai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGvkAb0T9A8VAWxGqi3IN1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGvkAb0T9A8VAWxGqi3IN1w.png"&gt;&lt;/a&gt;Script = Thai&lt;/p&gt;

&lt;p&gt;ผลที่ได้คือภาษาไทยจัดระดับสระวรรณยุกต์ได้สวยงาม แต่!!! สิ่งที่ต้องสังเกตุอีกอย่างหนึ่งคือ การแสดง Ligatures ของภาษาอังกฤษจะไม่สวยงามแทนเพราะมันต้องใช้ Script = Latin นั่นเองวิธีแก้แบบบัวไม่ให้ช้ำน้ำไม่ให้ขุ่น ให้แสดงสวยงามทั้งสองภาษาคือให้ใช้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Script = Default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkLHBoCEEgfb4GdARv8N-Lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AkLHBoCEEgfb4GdARv8N-Lg.png"&gt;&lt;/a&gt;Script = Default&lt;/p&gt;

&lt;p&gt;มาดูผลเปรียบเทียบกันแบบชัดๆ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A__xbLOlYYyrETO91qUMuJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A__xbLOlYYyrETO91qUMuJg.png"&gt;&lt;/a&gt;ไม่กำหนด Script จะเท่ากับ Script = Latin&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWAWwr106-YpTQs0HklsgWQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AWAWwr106-YpTQs0HklsgWQ.png"&gt;&lt;/a&gt;Script = Thai&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5epVutnyY_8GGEw2JUaaKQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5epVutnyY_8GGEw2JUaaKQ.png"&gt;&lt;/a&gt;Script = Default&lt;/p&gt;

&lt;p&gt;ผู้เชี่ยวชาญหลายท่านยังแนะนำอีก Option คือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;Ligatures=TeX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือ จะใช้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;Mapping=tex-text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สอง options นี้เลือกตัวใดตัวหนึ่งก็ได้จะทำให้การแสดงผลเกี่ยวกับพวก -, — , — เป็นไปตามแบบของ TeX ทำให้สวยงามขึ้น&lt;/p&gt;

&lt;h3&gt;
  
  
  การตัดคำ
&lt;/h3&gt;

&lt;p&gt;XeLaTeX จะใช้ lib ของ ICU ในการตัดคำลองมาดูกันว่าเมื่อเทียบกับ pdfLaTeX ที่ใช้ swath ในการตัดคำจะเป็นยังไงบ้าง&lt;/p&gt;

&lt;p&gt;Copy จาก file4.tex จากตัวอย่าง pdfLaTeX มาแล้วแก้ไขดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;article&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;fontspec&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Extension = .otf ,
  ItalicFont = *-Italic ,
  BoldFont = *-Bold ,
  BoldItalicFont = *-BoldItalic ,
  Script = Default,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;Laksaman&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;\begin{document}&lt;/span&gt;
เป็นมนุษย์สุดประเสริฐเลิศคุณค่า กว่าบรรดาฝูงสัตว์เดรัจฉาน
จงฝ่าฟันพัฒนาวิชาการ อย่าล้างผลาญฤๅเข่นฆ่าบีฑาใคร
ไม่ถือโทษโกรธแช่งซัดฮึดฮัดด่า หัดอภัยเหมือนกีฬาอัชฌาสัย
ปฏิบัติประพฤติกฎกำหนดใจ พูดจาให้จ๊ะๆ จ๋า น่าฟังเอยฯ

ธรรมคุณหนุนความดีฑีฆรัตน์ สรรพสัตว์วัฏวจรถอนวิถี
อริยสัจตรัสสังโยคโลกโมฬี ดังกุมภีร์ผลาญชิวหาบีฑาทนต์
ฟังฉัตรทองของประเสริฐเลิศวิเศษ ฝ่ายต้นเหตุฎรงกรณ์อุดรผล
ยินสถานฌานสมาอารยะชน พึงซ่อนกลปรนนิบัตินิวัฒน์แฮฯ
&lt;span class="nt"&gt;\end{document}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เมื่อลอง Build ดู&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiAOX9kH1NCQ9b3fW1Kn6Vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AiAOX9kH1NCQ9b3fW1Kn6Vg.png"&gt;&lt;/a&gt;ข้อความภาษาไทยยาวๆ&lt;/p&gt;

&lt;p&gt;จะเห็นว่าตอนนี้ยังไม่มีการตัดคำและบรรทัดที่ถูกต้อง XeLaTeX มีคำสั่งกำหนดภาษาสำหรับการตัดบรรทัดไว้ให้คือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\XeTeXlinebreaklocale&lt;/span&gt; "th"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ค่า “th” คือบอกว่าจะใช้ Locale ของ Thai นั่นเอง อาจจะใช้ “th_TH” หรือ “thai” ก็ได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APLg-HHqzX76FDu53uh-eEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2APLg-HHqzX76FDu53uh-eEQ.png"&gt;&lt;/a&gt;เพิ่มคำสั่งในการตัดคำ&lt;/p&gt;

&lt;p&gt;เมื่อเรากำหนดคำสั่งให้ตัดบรรทัด (โดยดูจากการตัดคำ) ก็จะดูดีขึ้นแต่ถ้าสังเกตขอบทั้งซ้ายขวายังไม่มีการจัดให้พอดี หรือที่เรียกว่า Justify จริงๆ มันก็ Justify นะแหละแต่มันไม่กล้าแบ่งคำ และ การกระจายช่องว่างที่เหมาะสมนั่นเอง จึงมีคำสั่งอีกคำสั่งที่ช่วยจัดให้การกระจายได้สวยงามขึ้นคือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\XeTeXlinebreakskip&lt;/span&gt; = 0pt plus 1pt&lt;span class="k"&gt;\relax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AP_J04Gf0TSQvKHsN4ohypg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AP_J04Gf0TSQvKHsN4ohypg.png"&gt;&lt;/a&gt;การ Tune การตัดบรรทัดเพิ่มเติม&lt;/p&gt;

&lt;p&gt;เมื่อเราทำการ tune การตัดบรรทัดพบว่าดูดีขึ้นมาก ขอบซ้ายขวาตรงดิ่งสวยงาม แต่ถ้าสังเกตดีๆ จะพบว่ามีการแทรกช่องว่างระหว่างคำเล็กน้อยถ้าเทียบกับ pdfLaTeX ก่อนหน้านี้ จากการทดลองพบว่าถ้าจะให้เหมือนกับ pdfLaTeX แป่ะ ๆ ต้องใช้ package polyglossia ช่วยอันนี้ผมเองไม่แน่ใจเรื่องกลไกว่ามันไปทำยังไงถึงทำให้การจัดหน้า ตัดบรรทัดออกมาได้เหมือนกันขนาดนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AijPfASXc8QUX7MZ0Oav4-Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AijPfASXc8QUX7MZ0Oav4-Q.png"&gt;&lt;/a&gt;ใช้ polyglossia&lt;/p&gt;

&lt;p&gt;ลองเทียบกันแบบจะๆ ดู&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aecct4L3P9-zXO2_1MuOixw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Aecct4L3P9-zXO2_1MuOixw.png"&gt;&lt;/a&gt;pdfLaTeX + swath&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKF1S4w4jigdziGBj85ZzqA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AKF1S4w4jigdziGBj85ZzqA.png"&gt;&lt;/a&gt;XeLaTeX + Polyglossia + thai locale&lt;/p&gt;

&lt;h3&gt;
  
  
  การใช้ Font นอก
&lt;/h3&gt;

&lt;p&gt;ปกติถ้าเราใช้ font จากในระบบของ TeX Live ก็เพียงพอสำหรับการเขียนตำรา เขียนบทความต่างๆ นอกเสียจากมีการกำหนดชนิด font ของผู้รับตีพิมพ์ ผมจะลองเอา font จาก Windows และ Fonts จาก Internet มาใช้ดูว่าจะแสดงผลได้สวยงามครบถ้วนเหมือนชุด Fonts-Tlwg หรือไม่&lt;/p&gt;

&lt;h4&gt;
  
  
  Angsana New (TTF)
&lt;/h4&gt;

&lt;p&gt;ตัวแรกผมลอง Angsana New แบบ TrueType Font เท่าที่ดูค่อนข้างเก่ามากมี font script Thai ตัวเดียวด้วย&lt;/p&gt;

&lt;p&gt;ผมสร้าง folder ชื่อ fonts ไว้ใน ที่เดียวกับ source code มี Angsana New มี files ทั้งหมด 4 แบบคือ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;angsa.ttf angsab.ttf angsai.ttf angsaz.ttf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;fontspec ผมกำหนดดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Path = fonts/,
  Extension = .ttf ,
  UprightFont = angsa,
  ItalicFont = angsai ,
  BoldFont = angsab ,
  BoldItalicFont = angsaz ,
  Script = Thai,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;Angsana New&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ad8JVoiMW8Kk9KVmJmLb-lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ad8JVoiMW8Kk9KVmJmLb-lg.png"&gt;&lt;/a&gt;Angsana NEW&lt;/p&gt;

&lt;p&gt;เนื่องจาก fonts ภาษาไทยส่วนมากขนาดจะเล็กเมื่อเทียบกับ fonts ภาษาอังกฤษ และ fonts-tlwg ที่ถูก scale ให้เท่ากับ fonts ภาษาอังกฤษแล้ว ใน option ผมจะ scale ขึ้นไปให้เท่าๆ กับ Laksaman ตามแบบด้านล่าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;Scale=1.45
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3d0m8Tod_9PpAVSYC-vJVA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3d0m8Tod_9PpAVSYC-vJVA.png"&gt;&lt;/a&gt;Angsana New + Scaled&lt;/p&gt;

&lt;p&gt;ผลที่ได้น่าพอใจคือใกล้เคียงกับ Laksaman&lt;/p&gt;

&lt;h4&gt;
  
  
  Tahoma (TTF)
&lt;/h4&gt;

&lt;p&gt;สำหรับ Tahoma จะเป็น font ที่มี scale เท่ากับ fonts ภาษาอังกฤษอื่นๆ จึงไม่จำเป็นต้อง scale และ มี Script หลายภาษา แต่จะไม่มีค่า Default ดังนั้นตอนเรียกใช้อาจจะต้องแยกว่าจะเรียกแบบ Thai หรือ Latin&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Scale=1,
  Path = fonts/,
  Extension = .ttf ,
  UprightFont = tahoma,
  BoldFont = tahomabd ,
  Script = Thai,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;Tahoma&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6sUzg6hc6dQ1FN13WoVB-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A6sUzg6hc6dQ1FN13WoVB-g.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Angsana New (TTC)
&lt;/h4&gt;

&lt;p&gt;นอกจาก font ที่มีนามสกุลเป็น ttf แล้ว windows ยังใช้ fonts ที่มีนามสกุลว่า ttc หรือ TrueType Collections คือ font เดียวมีครบทุก face นั่นเองแต่ info ยังคงเหมือน Angsana New ที่แยกเป็น ttf ครับคือมี script เดียวคือ Thai&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Scale=1.45,
  Path = fonts/,
  UprightFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=0&lt;span class="p"&gt;}&lt;/span&gt; ,
  BoldFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=1&lt;span class="p"&gt;}&lt;/span&gt; ,
  ItalicFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=2&lt;span class="p"&gt;}&lt;/span&gt; ,
  BoldItalicFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=3&lt;span class="p"&gt;}&lt;/span&gt; ,
  Script = Thai,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;angsana.ttc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGbyqeaySAPVGhtlGwxOItA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AGbyqeaySAPVGhtlGwxOItA.png"&gt;&lt;/a&gt;Angsana New TTC&lt;/p&gt;

&lt;h4&gt;
  
  
  Browallia New (TTC)
&lt;/h4&gt;

&lt;p&gt;อีกตัวอย่างแบบ TTC ของ font Browallia ซึ่งก็เหมือนกับ Angsana New&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Scale=1.45,
  Path = fonts/,
  UprightFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=0&lt;span class="p"&gt;}&lt;/span&gt; ,
  BoldFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=1&lt;span class="p"&gt;}&lt;/span&gt; ,
  ItalicFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=2&lt;span class="p"&gt;}&lt;/span&gt; ,
  BoldItalicFeatures = &lt;span class="p"&gt;{&lt;/span&gt;FontIndex=3&lt;span class="p"&gt;}&lt;/span&gt; ,
  Script = Thai,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;browalia.ttc&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmTkBPWpB0Ts0U0jKdTl0rw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AmTkBPWpB0Ts0U0jKdTl0rw.png"&gt;&lt;/a&gt;Browalloa New TTC&lt;/p&gt;

&lt;h4&gt;
  
  
  Trirong (Google Font TTF)
&lt;/h4&gt;

&lt;p&gt;ลอง Download Font ไทยจาก Google มาลองดูบ้าง ผมสุ่มเอา Font Trirong มาทดสอบดูพบว่ามันมี Face ให้เลือกใช้เยอะมากซึ่งเราสามารถตั้งค่าเอามาใช้แบบละเอียดได้เช่น Black, Light ExtraBold เป็นต้น (ต้องขออ่านคู่มือเพิ่มเติม)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\setmainfont&lt;/span&gt;[
  Path = fonts/Trirong/ ,
  Extension = .ttf ,
  UprightFont = *-Light,
  ItalicFont = *-Italic ,
  BoldFont = *-Bold ,
  BoldItalicFont = *-BoldItalic ,
  Script = Default,
  Mapping=tex-text
]&lt;span class="p"&gt;{&lt;/span&gt;Trirong&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AY4Y7tK0H4g1dCj25Nb1X_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AY4Y7tK0H4g1dCj25Nb1X_w.png"&gt;&lt;/a&gt;Google Trirong&lt;/p&gt;

&lt;p&gt;การเลือกว่าจะจัดชุด font face ก็ขึ้นอยู่กับที่เราเลือกนะ เช่น เราอยากได้แค่เบาๆ ก็อาจจะใช้ UprightFont แบบ Light หรือ เพิ่มขึ้นหน่อยก็ Regular , Nornal หรือ Medium เป็นต้นลองเล่นกันดูครับ ส่วน font นี้มี script แบบ Default ให้ด้วยก็ตั้งค่าง่ายหน่อย&lt;/p&gt;

&lt;h3&gt;
  
  
  การใช้ Fonts หลาย ๆ แบบในเอกสาร
&lt;/h3&gt;

&lt;p&gt;ใน Fonts-Tlwg มีหลาย Fonts ให้เลือกใช้ถ้าเราต้องการใช้หลายๆ แบบวิธี set แบบด้านบนอาจจะยุ่งอยากและไม่สามารถ Reuse ได้มีผู้เชี่ยวชาญท่านหนึ่งได้ทำตัวอย่างไว้ให้ผมเลยขอนำมาแนะนำต่อละกัน&lt;/p&gt;

&lt;p&gt;** ต้นฉบับ (&lt;a href="https://github.com/abhabongse/fonts-tlwg/blob/067c1e4f2625604fe31337c9bd2203f634c98560/latex/fonts-tlwg.sty" rel="noopener noreferrer"&gt;https://github.com/abhabongse/fonts-tlwg/blob/067c1e4f2625604fe31337c9bd2203f634c98560/latex/fonts-tlwg.sty&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Fontspec สามารถประกาศ Features ต่างๆ ไว้ก่อนได้แล้วนำไป Reuse และ ปรับค่า เพิ่มค่าได้ตามต้องการเช่น fonts ในชุด fonts-tlwg เราสามารถประกาศสั้นๆ แบบรวมทุก fonts ดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\defaultfontfeatures&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  Extension = .otf ,
  Mapping = tex-text,
  Script = Default
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;% Font families with regular, oblique, bold, and bold-oblique.&lt;/span&gt;
&lt;span class="k"&gt;\defaultfontfeatures&lt;/span&gt;[Garuda,Loma,Purisa,Sawasdee,TlwgMono,TlwgTypewriter,&lt;span class="c"&gt;%&lt;/span&gt;
TlwgTypist,TlwgTypo,Umpush,Waree]&lt;span class="p"&gt;{&lt;/span&gt;
ItalicFont = *-Oblique ,
BoldFont = *-Bold ,
BoldItalicFont = *-BoldOblique ,
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;% TlwgMono don't has Script Default&lt;/span&gt;
&lt;span class="k"&gt;\defaultfontfeatures&lt;/span&gt;+[TlwgMono]&lt;span class="p"&gt;{&lt;/span&gt;Script=Thai&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;% Font families with regular, italic, bold, and bold-italic.&lt;/span&gt;
&lt;span class="k"&gt;\defaultfontfeatures&lt;/span&gt;&lt;span class="na"&gt;[Laksaman]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
ItalicFont = *-Italic ,
BoldFont = *-Bold ,
BoldItalicFont = *-BoldItalic ,
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;% Font families with regular, italic, oblique, bold, &lt;/span&gt;
&lt;span class="c"&gt;% bold-italic, and bold-oblique.&lt;/span&gt;
&lt;span class="k"&gt;\defaultfontfeatures&lt;/span&gt;&lt;span class="na"&gt;[Kinnari,Norasi]&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
ItalicFont = *-Italic ,
SlantedFont = *-Oblique ,
BoldFont = *-Bold ,
BoldItalicFont = *-BoldItalic ,
BoldSlantedFont = *-BoldOblique ,
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\setdefaultlanguage&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;thai&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\XeTeXlinebreaklocale&lt;/span&gt; "th"
&lt;span class="k"&gt;\XeTeXlinebreakskip&lt;/span&gt; = 0pt plus 1pt &lt;span class="k"&gt;\relax&lt;/span&gt;

&lt;span class="k"&gt;\newfontfamily\thaifont&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Norasi&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\thaifontsf&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Garuda&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\thaifonttt&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;TlwgTypist&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จากตัวอย่างข้างบนเป็นการกำหนด fonts หลักของเอกสาร 3 แบบโดยเราจะใช้ Polyglossia เป็นตัวช่วยในการจัดการให้โดยจะมี&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Roman font \textrm \rmfamily →  &lt;strong&gt;Norasi&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;SanSerif font \textsf \sffamily →  &lt;strong&gt;Garuda&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;TypeWriter font \texttt \ttfamily → &lt;strong&gt;Tlwg Typist&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ตัวอย่างการแสดงผล&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{description}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt;&lt;span class="na"&gt;[Roman]&lt;/span&gt; การพิมพ์ภาษาไทย -- English
  &lt;span class="k"&gt;\item&lt;/span&gt;&lt;span class="na"&gt;[\sffamily{}Sans]&lt;/span&gt; &lt;span class="k"&gt;\sffamily&lt;/span&gt; การพิมพ์ภาษาไทย -- English
  &lt;span class="k"&gt;\item&lt;/span&gt;&lt;span class="na"&gt;[\ttfamily{}Typewriter]&lt;/span&gt; &lt;span class="k"&gt;\ttfamily&lt;/span&gt; การพิมพ์ภาษาไทย -- English
&lt;span class="nt"&gt;\end{description}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARBOseaNg0_lq8-oTjzCUOw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ARBOseaNg0_lq8-oTjzCUOw.png"&gt;&lt;/a&gt;Fonts Roman, Sans และ TypeWriter&lt;/p&gt;

&lt;p&gt;การแสดง fonts อื่นๆ ที่ไม่ใช่สามแบบนี้จะเราสามารถเรียกใช้ได้หลายแบบ แบบที่แนะนำคือการใช้คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\newfontfamily&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เช่นประกาศ fonts ต่างๆ&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="k"&gt;\newfontfamily\garuda&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Garuda&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\norasi&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Norasi&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\kinnari&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Kinnari&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\laksaman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Laksaman&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\loma&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Loma&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\purisa&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Purisa&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\sawasdee&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Sawasdee&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\tlwgtypist&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;TlwgTypist&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\tlwgtypo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;TlwgTypo&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\tlwgmono&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;TlwgMono&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\tlwgtypewriter&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;TlwgTypewriter&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newfontfamily\umpush&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Umpush&lt;span class="p"&gt;}&lt;/span&gt;[
  FontFace = &lt;span class="p"&gt;{&lt;/span&gt;l&lt;span class="p"&gt;}{&lt;/span&gt;n&lt;span class="p"&gt;}{&lt;/span&gt; Font = *-Light &lt;span class="p"&gt;}&lt;/span&gt;,
  FontFace = &lt;span class="p"&gt;{&lt;/span&gt;l&lt;span class="p"&gt;}{&lt;/span&gt;it&lt;span class="p"&gt;}{&lt;/span&gt; Font = *-LightOblique &lt;span class="p"&gt;}&lt;/span&gt;
]
&lt;span class="k"&gt;\newfontfamily\waree&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;Waree&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เรียกใช้งาน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\kinnari&lt;/span&gt; Kinnari สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\garuda&lt;/span&gt; Garuda สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\norasi&lt;/span&gt; Norasi สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\laksaman&lt;/span&gt; Laksaman สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\purisa&lt;/span&gt; Purisa สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\loma&lt;/span&gt; Loma สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\sawasdee&lt;/span&gt; Sawasdee สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\tlwgtypewriter&lt;/span&gt; TlwgTypewriter สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\tlwgtypist&lt;/span&gt; TlwgtTypist สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush&lt;/span&gt; Umpush สวัสดีชาวโลก
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\waree&lt;/span&gt; Waree สวัสดีชาวโลก
&lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ผล&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOyw4kPj62ZaXStmw4bzPfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AOyw4kPj62ZaXStmw4bzPfw.png"&gt;&lt;/a&gt;Fonts ต่างๆของ TLWG&lt;/p&gt;

&lt;p&gt;ถ้าสังเกตจะเห็นว่า font Umpush จะมีการกำหนดค่าพิเศษกว่าแบบอื่น คือจะมี fontseries Light และ Light Oblique เพิ่มเข้ามาซึ่งไม่สามารถกำหนดได้ใน \defaultfontfeatures แต่สามารถใช้วิธีในตัวอย่าง หรือ จะใช้วิธีก่อนหน้านี้คือ \setmainfont \setsansfont \setmonofont ก็ได้ถ้าไม่ใช้ PolyGlossia จัดการ fonts ให้&lt;/p&gt;

&lt;h4&gt;
  
  
  วิธีเรียกใช้ fontsereis และ fontshape
&lt;/h4&gt;

&lt;p&gt;ปกติเราจะใช้ macro เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{description}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt;&lt;span class="na"&gt;[\textbf{ตัวหนา}]&lt;/span&gt; &lt;span class="k"&gt;\bfseries&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt;&lt;span class="na"&gt;[\textit{ตัวเอียง}]&lt;/span&gt; &lt;span class="k"&gt;\itshape&lt;/span&gt; ปาป่าป้าป๊าป๋า
&lt;span class="nt"&gt;\end{description}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F606%2F1%2APKrtDOrK3WQZl8e_4EUmXQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F606%2F1%2APKrtDOrK3WQZl8e_4EUmXQ.png"&gt;&lt;/a&gt;ตัวหนา ตัวเอียง&lt;/p&gt;

&lt;p&gt;หรือจะใช้ \fontseries{}\fontshape{}\selectfont ก็ได้เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;m&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;n&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;m&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;it&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;b&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;n&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;b&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;it&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
&lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F726%2F1%2AWvXzaQ7IMT3JeAlb0hbT6Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F726%2F1%2AWvXzaQ7IMT3JeAlb0hbT6Q.png"&gt;&lt;/a&gt;รูปแบบหนาเอียงธรรมดา&lt;/p&gt;

&lt;p&gt;ส่วน Umpush จะมีเพิ่มมาคือ \fontseries{l}\fontshape{n} และ \fontseries{l}\fontshape{it}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tex"&gt;&lt;code&gt;&lt;span class="nt"&gt;\begin{itemize}&lt;/span&gt;
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;l&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;n&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;m&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;n&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;l&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;it&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;m&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;it&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;b&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;n&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
  &lt;span class="k"&gt;\item&lt;/span&gt; &lt;span class="k"&gt;\umpush\fontseries&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;b&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\fontshape&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;it&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\selectfont&lt;/span&gt; ปาป่าป้าป๊าป๋า
&lt;span class="nt"&gt;\end{itemize}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F956%2F1%2AEVNyu9pmeFESqxOLumIpdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F956%2F1%2AEVNyu9pmeFESqxOLumIpdg.png"&gt;&lt;/a&gt;Umpush&lt;/p&gt;

&lt;p&gt;ปิดท้ายด้วยตัวอย่างการใช้งาน Fonts รูปแบบต่างๆ ซึ่งต้นฉบับมาจากของพี่เทพพิทักษ์&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abz8pePxiSqGhV5rEYE-8fw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Abz8pePxiSqGhV5rEYE-8fw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PDF ตัวอย่าง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mrchoke/latex-workshop-medium/raw/main/latex2/file11.pdf" rel="noopener noreferrer"&gt;https://github.com/mrchoke/latex-workshop-medium/raw/main/latex2/file11.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ต้นฉบับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tlwg/fonts-tlwg/blob/master/latex/examples/teststd.tex" rel="noopener noreferrer"&gt;tlwg/fonts-tlwg&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Code ที่ใช้ประกอบทั้งหมด
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/mrchoke/latex-workshop-medium" rel="noopener noreferrer"&gt;mrchoke/latex-workshop-medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ถ้ามีเวลาจะมาทดสอบและบันทึกการเรียนรูปใน EP ต่อ ๆ ไปครับ เนื่องจากการเขียนเป็นรูปแบบการบันทึกการทดสอบอาจจะขาดตกบกพร่อง หรือ ผิดพลาดไปบ้างผมยินดีรับฟังคำชี้แนะ เพื่อการปรับแก้ให้สมบูรณ์ยิ่งขึ้น ขอบคุณครับ&lt;/p&gt;

</description>
      <category>tlwg</category>
      <category>latex</category>
      <category>thai</category>
      <category>vscode</category>
    </item>
    <item>
      <title>เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP1</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Thu, 25 Mar 2021 22:52:47 +0000</pubDate>
      <link>https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep1-18aj</link>
      <guid>https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep1-18aj</guid>
      <description>&lt;h3&gt;
  
  
  เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP1
&lt;/h3&gt;

&lt;p&gt;บันทึกการเขียน LaTeX ด้วย VSCode โดยใช้ TeX Live Docker Image และ การใช้ Visual Studio Code Remote — (SSH,Container) และ Visual Studio Code LaTeX Workshop Extension&lt;/p&gt;

&lt;p&gt;โดยปกติผมรู้จัก LaTeX มานานแต่ไม่เคยเข้าถึงมันเลย ใช้แค่ระดับทดสอบไม่ได้ใช้จริงจังเป็นกิจวัตรดังนั้นหลายๆ อย่างก็ไม่ค่อยรู้เรื่อง ช่วงนี้ก็นำเอามาใช้งาน เช่นตัวช่วยสร้าง PDF และ ลองเขียนโน้นนี่ไปเรื่อย ปกติเครื่องมือที่ใช้เขียน LaTeX มีหลายตัว แต่ในบันทึกครั้งนี้ผมจะใช้ VSCode + Visual Studio Code Remote — (SSH,Container) Extension+ Visual Studio Code LaTeX Workshop Extension และ TeX Live Docker Image ซึ่งสามารถใช้ได้ทั้งบนเครื่องส่วนตัว และ การตั้งเป็น Server ให้เพื่อนร่วมทีมเข้ามาใช้งานร่วมกันได้&lt;/p&gt;

&lt;p&gt;EP1 จะเป็นเรื่องการเตรียม Docker Container นะครับ ส่วน EP 2 จะแนะนำการเขียน LaTeX เบื้องต้น&lt;/p&gt;

&lt;p&gt;บันทึกนี้มีอยู่สองสามวิธีค่อยๆ อ่านนะครับอาจจะงงๆ ไปบ้างแต่ถ้าเข้าใจก็จะใช้มันสนุกมาก ถ้าใช้งานปกติใช้ แบบ Remote — Container จะง่ายสุด แต่ถ้าใช้หลายๆ คนบน Server แบบ Remote — Container มันอาจจะยุ่งยากหน่อยเรื่อง docker context เราอาจจะใช้แบบ SSH เข้ามาช่วยก็ได้&lt;/p&gt;

&lt;h3&gt;
  
  
  Run TeX Live Docker Container
&lt;/h3&gt;

&lt;p&gt;สำหรับ Docker Image ที่ใช้ผมสร้างไว้ใช้เองรายละเอียดอ่านด้านล่างของบทความ&lt;/p&gt;

&lt;h4&gt;
  
  
  TeX Live Only Image
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -itd \
  --hostname texlive \
  --name texlive \
  -v ${PWD}/datas:/root/data \
  mrchoke/texlive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ข้างบนจะใช้ options ดังนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hostname จะตั้งหรือไม่ก็ได้แต่ถ้าตั้งไว้ตอน ssh เข้าไป prompt ก็จะขึ้นชื่อแทน hash ของ ID&lt;/li&gt;
&lt;li&gt;name จะตั้งหรือไม่ก็ได้ถ้าตั้งก็จะง่ายตอนจัดการเช่น ps ดูก็เข้าใจง่าย จะสั่ง stop start restart หรือ delete ด้วยชื่อก็ง่ายหน่อย&lt;/li&gt;
&lt;li&gt;v mount volume เข้าไปเพื่อจะได้จัดการ files งานของเราได้ง่ายเวลาลบ container ทิ้ง files จะได้ไม่หาย (สำหรับ Windows 10 ให้ใช้บน PowerShell ${PWD} ถึงจะทำงานได้ถูกต้อง)&lt;/li&gt;
&lt;li&gt;mrchoke/texlive เป็น image ที่ผม publish ไว้ที่ hub.docker&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  With SSH
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -itd \
  --hostname texlive \
  --name texlive \
  -v ${PWD}/datas:/root/data \
  -p 2222:22 \
  mrchoke/texlive:2021-ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;p ในกรณีที่ run docker เพื่อแชร์กับเพื่อนๆ ให้ bind port 22 มายัง host เพื่อจะได้ ssh เข้าไปได้ตรงนี้ถ้ากำหนด 2222:22 ก็จะ bind ที่ 0.0.0.0 ใครก็ได้สามารถเข้ามายังเครื่องเราได้ถ้าเป็น public server ก็ต้องระวังให้ดีซึ่งเราสามารถ กำหนดเป็น 127.0.0.1:2222:22 หรือ 192.168.0.1:2222:22 ก็แล้วแต่เราจะเข้มงวดการเข้าถึงขนาดไหน แต่ถ้าใช้คนเดียวไม่จำเป็นต้อง bind นะครับเราสามารถใช้ Remote Container Extension เข้ามาได้เลย&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  With authorized_keys
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -itd \
  --hostname texlive \
  --name texlive \
  -v ${PWD}/datas:/root/data \
  -v ${PWD}/.ssh:/root/.ssh \
  -p 2222:22 \
  mrchoke/texlive:2021-ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือถ้าใครต้องการใช้ ssh-key ในการ login ก็สามารถ mount .ssh ที่มี file authorized_keys เข้าไปใน /root ของ container ก็ได้&lt;/p&gt;

&lt;p&gt;ลองตรวจสอบว่า docker สามารถ run ได้สำเร็จหรือไม่&lt;/p&gt;

&lt;h4&gt;
  
  
  TeX Live Only
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7615fbdb871 mrchoke/texlive “/bin/sh” 6 seconds ago Up 5 seconds texlive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  With SSH
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
24ad39e3cae9 mrchoke/texlive:2021-ssh "/usr/sbin/sshd -D" 4 seconds ago Up 3 seconds 0.0.0.0:2222-&amp;gt;22/tcp texlive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ข้อดี — ข้อเสีย
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;TeX Live Only&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ใช้บนเครื่องเราได้เลยไม่ต้องเปิด port เพิ่มเติม exec เข้าไปใช้งานได้ปกติ&lt;/li&gt;
&lt;li&gt;เชื่อมต่อกับ VSCode Remote — Container ได้เลยสะดวกมาก&lt;/li&gt;
&lt;li&gt;ใช้งานร่วมกันอาจจะต้องใช้ผ่าน git ในการจัดการอาจจะ conflict กันได้ถ้าจัดการแบ่งงานกันไม่ดี&lt;/li&gt;
&lt;li&gt;ถ้าใช้บน Server ทางฝั่ง Client ต้องใช้ Docker context ซึ่งอาจจะยุ่งยากไปบ้าง&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With SSH&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;กรณีใช้งานร่วมกันหลายคนบน Server เราสามารถสร้าง user เข้ามาใช้งานใน container ที่เราสร้างขึ้นไม่ยุ่งกับ user บนระบบจริง&lt;/li&gt;
&lt;li&gt;กรณีเขียนร่วมกันเข้าไปที่เดียวกันได้เลยแต่ต้องแบ่งกันเขียนเป็นส่วนๆ ไปจะได้ไม่ทับกัน&lt;/li&gt;
&lt;li&gt;กรณีใช้ VSCode เข้าไปยัง Server ก็ใช้ผ่าน Remote — SSH ได้เลยสะดวกกว่าแบบ Docker Context&lt;/li&gt;
&lt;li&gt;มันเหมือน Linux Server เครื่องหนึ่งดีๆ นี่เอง&lt;/li&gt;
&lt;li&gt;ถ้าทำบนระบบที่ public ก็ต้องระวังผู้ไม่หวังดีบุกรุกเพราะความปลอดภัยไม่ได้ตั้งไว้สูง&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote (SSH,Container)
&lt;/h3&gt;

&lt;p&gt;หลังจาก Start Container เรียบร้อยแล้วเราสามารถเข้าไปยัง container ได้ 3 รูปแบบคือ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;docker exec เข้าไปใช้งาน
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it texlive bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ใช้ port ที่ bind ไว้ตอน run ครั้งแรก&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -p 2222 root@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;หรือ ในกรณีเข้าไปยัง server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -p 2222 root@server-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าไม่ได้ใช้ ssh-key ก็ใส่รหัสผ่าน default &lt;strong&gt;123456&lt;/strong&gt; แต่ถ้าจะเปลี่ยนรหัสผ่านก็สามารถใช้คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it texlive passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Visual Studio Code Remote — (SSH,Container)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ซึ่งจะใช้ความสามารถของ VSCode Remote Extension จะกล่าวในหัวข้อถัดไป&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code Remote — (SSH,Container)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  VSCode Remote — Container (localhost)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A625ZZjfs2QqXnX7GSo8mMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A625ZZjfs2QqXnX7GSo8mMg.png"&gt;&lt;/a&gt;Remote Container Extension&lt;/p&gt;

&lt;p&gt;วิธีนี้ไม่จำเป็นต้อง bind port ssh ออกมานะครับ เพราะเราจะใช้ VSCode เข้าไปใช้งาน Container โดยตรงบนเครื่องของเราเอง โดย Click ที่ icon รูป computer บน Side Bar ด้านซ้านมือ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F130%2F1%2ABipVfW4Gkz-wc-wIQSUw6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F130%2F1%2ABipVfW4Gkz-wc-wIQSUw6g.png"&gt;&lt;/a&gt;Remote icon&lt;/p&gt;

&lt;p&gt;หลังจากนั้นให้ click เลือก Target ของ Remote Extension&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F640%2F1%2AtCciMRnXwzHq_Yj80P5rfQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F640%2F1%2AtCciMRnXwzHq_Yj80P5rfQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;มันจะมีสองแบบคือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Containers&lt;/li&gt;
&lt;li&gt;SSH Targets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;วิธีนี้ให้เลือก Containers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F872%2F1%2AasS8FqSZwgmGfmUY1GWx4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F872%2F1%2AasS8FqSZwgmGfmUY1GWx4A.png"&gt;&lt;/a&gt;Remote Extension Container&lt;/p&gt;

&lt;p&gt;ถ้าเรา start container ไว้ก็ควรจะเห็นเหมือนในภาพตัวอย่างด้านบนให้เรา Click ขวาบนชื่อ container ที่เราต้องการจะเข้าไปใช้งาน&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F838%2F1%2A8WEYJhcHV8e4suBh7fgj8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F838%2F1%2A8WEYJhcHV8e4suBh7fgj8g.png"&gt;&lt;/a&gt;Click ขวา&lt;/p&gt;

&lt;p&gt;และให้เลือก Attach to Container หลังจากนั้นก็จะมีหน้าต่างใหม่เปิดขึ้นมาพร้อมเข้าไปยัง directory ที่เราได้ทำการ mount ไว้ตอนสั่ง run คือ /root/data นั่นเอง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUpzuZkriWzSfVPnS9ik1jA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AUpzuZkriWzSfVPnS9ik1jA.png"&gt;&lt;/a&gt;หน้าต่าง VSCode ที่ Remote ไปยัง Docker Container&lt;/p&gt;

&lt;h4&gt;
  
  
  VSCode Remote — Container (Over SSH)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F989%2F1%2A278diKD__g7TGSs-vUSeTw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F989%2F1%2A278diKD__g7TGSs-vUSeTw.jpeg"&gt;&lt;/a&gt;VSCode Remote — Container&lt;/p&gt;

&lt;p&gt;สำหรับการใช้ Remote — Container สามารถใช้งานข้ามเครื่องได้โดยการใช้ความสามารถของ Docker ผ่าน DOKCER_CONTEXT หมายความว่า&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เราต้องเปิด Docker ทั้งฝั่ง Client และ Server&lt;/li&gt;
&lt;li&gt;เราต้องสามารถ SSH เข้าไปยัง Server ได้&lt;/li&gt;
&lt;li&gt;มีสิทธิใช้งาน Docker ได้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;วิธีการง่ายๆ คือ เราสั่ง docker run texlive image ไว้ที่ฝั่ง Server แล้วเลือก DOCKER_CONTEXT ขี้ไปที่เครื่อง Server หลังจากนั้น ตัว Extension ก็จะสามารถ attach มาใช้งานเปรียบเสมือนอยู่บนเครื่องเราเอง&lt;/p&gt;

&lt;h4&gt;
  
  
  Create Docker Context
&lt;/h4&gt;

&lt;p&gt;สร้าง Docker Context สำหรับการเชื่อมต่อไปยัง Server ผ่านทาง SSH&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker context create texlive --docker "host=ssh://mrchoke@192.168.1.17"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;texlive คือชื่อของ context ที่สร้างขึ้นมาจะใช้ชื่ออะไรก็ได้&lt;/li&gt;
&lt;li&gt;— docker บอก option สำหรับการเชื่อมต่อซึ่งตัวอย่างจะเป็น ssh:// ตามด้วย user และ hostname/IP ถ้า port ไม่ใช้ 22 ก็ให้ใส่เพิ่มหลัง IP ได้ เช่น "host=ssh://&lt;a href="mailto:mrchoke@192.168.1.17"&gt;mrchoke@192.168.1.17&lt;/a&gt;:2222"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ลองตรวจสอบดูครับว่าตอนนี้มี context อะไรอยู่บ้าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker context ls
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
texlive moby ssh://mrchoke@192.168.1.17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จะเห็นรานการทั้งหมดของ context ซึ่งตัวปัจจุบันที่ใช้อยู่จะมีเครื่องหมาย * อยู่หลังชื่อปกติจะเป็น defualt&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;การเลือกใช้ context&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ทำได้สองแบบคือ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;แบบชั่วคราว&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ให้ใช้ตัวแปร DOCKER_CONTEXT เลือก context ที่ต้องการ วิธีนี้ต้องพิมพ์แบบนี้ทุกครั้งหน้าคำสั่ง docker ซึ่งจะยุ่งยากแต่เหมาะกับการใช้แบบครั้งคราว&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOCKER_CONTEXT=texlive docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;แบบ Global&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;วิธีนี้สามารถสั่งด้วย command โดยตรงก็ได้ หรือ จะใช้ docker extension ของ VSCode เลือกก็ได้ หลังจากเลือกแล้วทุกครั้งที่สั่งคำสั่ง docker สิ่งที่เห็นคือทางฝั่ง server ที่ context ชี้ไป&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker context use texlive
docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F870%2F1%2AqCZQjK2k86ci284LWm28MQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F870%2F1%2AqCZQjK2k86ci284LWm28MQ.png"&gt;&lt;/a&gt;ใช้ VSCode Docker Extension&lt;/p&gt;

&lt;p&gt;*** สำหรับเครื่อง Server ที่ติดตั้ง docker ไว้ใน path อื่นนอกเหนือจาก /usr/bin ฝั่ง client จะไม่สามารถหาคำสั่ง docker ได้ต้องตั้งค่า sshd เพิ่มเติมคือให้แก้ไข&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;โดยเพิ่ม หรือ แก้ PermitUserEnvironment ให้เป็น yes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PermitUserEnvironment yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;แล้วกำหนด PATH ใน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.ssh/environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เช่นใน macOS docker จะอยู่ใน /usr/local/bin/docker ก็ให้ตั้ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PATH=/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2AUDiiPHREamsIXjyyYJf7VA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2AUDiiPHREamsIXjyyYJf7VA.png"&gt;&lt;/a&gt;Docker Extension get ข้อมูลไม่ได้&lt;/p&gt;

&lt;p&gt;จากที่ทดลองเล่นตัว Docker Extension มันจะดึงข้อมูลทางฝั่ง Server มาไม่ค่อยได้ จะ error เหมือนรูปด้านบน แต่ตัว Remote — Container จะเห็นปกติ แต่ก็มีเอ๋อบ้างบางครั้งนะครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2AEzjHwmak5y-Q9RWzOMWACA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F882%2F1%2AEzjHwmak5y-Q9RWzOMWACA.png"&gt;&lt;/a&gt;VSCode Remote — Container Extension&lt;/p&gt;

&lt;p&gt;ถ้าได้แบบรูปด้านบนก็สามารถใช้งานเหมือน container อยู่บนเครื่องตัวเองได้เลยครับ&lt;/p&gt;

&lt;h4&gt;
  
  
  Visual Studio Code Remote — SSH
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F989%2F1%2AnuXFLw0md4pHhPscMQvT1w.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F989%2F1%2AnuXFLw0md4pHhPscMQvT1w.jpeg"&gt;&lt;/a&gt;VSCode Remote — SSH&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5kuHhsDt2ULrnu45-GUZkQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A5kuHhsDt2ULrnu45-GUZkQ.png"&gt;&lt;/a&gt;Remote SSH&lt;/p&gt;

&lt;p&gt;ส่วน Remote — SSH นั้นเราต้องสั่ง run พร้อมกับ bind port ออกมาด้วยนะครับตัวอย่างของผมจะ bind ไว้ที่ 2222 ซึ่งสมมติว่าผมจะ remote ไปยังเครื่อง server ละกันจริงๆ เครื่องตัวเองนั้นแหละ ฮาๆ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F896%2F1%2Ah7wVr1QH3kRY-P1A0GYCaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F896%2F1%2Ah7wVr1QH3kRY-P1A0GYCaw.png"&gt;&lt;/a&gt;SSH Targets&lt;/p&gt;

&lt;p&gt;ให้เลือกการเชื่อมต่อแบบ SSH ด้านบนก่อนนะครับ หลังจากนั้นให้กดเครื่องหมาย +&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Avsw2DjECAG8NOjokyFqHqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Avsw2DjECAG8NOjokyFqHqw.png"&gt;&lt;/a&gt;ssh command&lt;/p&gt;

&lt;p&gt;ให้ใส่คำสั่งเหมือนกับที่เราสั่งบน terminal ปกติได้เลยจากตัวอย่างเช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -p2222 root@localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตรงนี้ถ้าเป็นเครื่อง server ก็ให้ใส่ IP หรือชื่อ Host แทน localhost&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Au6vITQ5oCspo0mglOTx7iw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Au6vITQ5oCspo0mglOTx7iw.png"&gt;&lt;/a&gt;เก็บ config ไว้ที่ไหน&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็จะถามว่าจะให้ save config นี้ไว้ที่ไหนวิธีที่ง่ายที่สุดคือตัวเลือกแรกคือให้เก็บไว้ใน .ssh/config ใน HOME ของเราเอง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F872%2F1%2AywhtRLy5DJRiOf2fkjrVOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F872%2F1%2AywhtRLy5DJRiOf2fkjrVOQ.png"&gt;&lt;/a&gt;รายชื่อ SSH Targets&lt;/p&gt;

&lt;p&gt;หลังจากที่เราป้อนคำสั่งแล้วจะมีรายชื่อเพิ่มขึ้นมาคือ localhost นั่นเอง รายชื่อตรงนี้เราสามารถเข้าไปจัดการได้โดยตรงใน file .ssh/config สามารถตั้งชื่อให้ได้ หรือจะเพิ่มรายการเข้าไปเองโดยตรงก็ได้เช่นกัน&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7pH5JxyLqHgR2gKs_bLKHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7pH5JxyLqHgR2gKs_bLKHg.png"&gt;&lt;/a&gt;Connect to Host&lt;/p&gt;

&lt;p&gt;หลังจากนั้นให้ Click ขวาบนชื่อ SSH Targets ที่เราต้องการจะ Connect เลือกว่าจะเปิดในหน้าต่างปัจจุบันหรือหน้าต่างใหม่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A795umqev-6TWzPezRJa-fA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A795umqev-6TWzPezRJa-fA.png"&gt;&lt;/a&gt;Confirm การเข้าครั้งแรก&lt;/p&gt;

&lt;p&gt;ถ้าเราเข้าครั้งแรกจะมีการให้ confirm ก่อนโดยเลือก Continue&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADWI8cqPKGuCy33P15ySYjQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ADWI8cqPKGuCy33P15ySYjQ.png"&gt;&lt;/a&gt;Password&lt;/p&gt;

&lt;p&gt;ถ้าไม่ได้ใช้ ssh-key ก็ให้ใส่รหัสผ่าน ถ้า default ก็ใส่ 123456 ถ้าเปลี่ยนรหัสผ่านไปแล้วก็ให้ใส่ที่ตั้งไว้ แต่ถ้าตั้ง ssh-key ก็จะไม่มีหน้าต่างนี้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F494%2F1%2AE6D4hRq_iHnMwg828X7LMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F494%2F1%2AE6D4hRq_iHnMwg828X7LMg.png"&gt;&lt;/a&gt;สถานะมุมขวาล่าง&lt;/p&gt;

&lt;p&gt;การ Connect ไปยัง SSH Server ครั้งแรกจะช้าหน่อยเพราะมีการติดตั้ง VSCode Server ก่อน แต่ถ้าครั้งต่อไปก็จะเร็วกว่า นอกจากจะมีการ Upgrade Version ของ VSCode&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABCUVDmmf6J8_cS4J2UQx7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ABCUVDmmf6J8_cS4J2UQx7w.png"&gt;&lt;/a&gt;Connect สำเร็จ&lt;/p&gt;

&lt;p&gt;ถ้า Connect สำเร็จก็จะขึ้นหน้าต่างดังรูปด้านบนซึ่งจะมีหน้าต่าง Terminal ด้านล่างให้ด้วยเราสามารถพิมพ์คำสั่งของ Linux ในนี้ได้เลย&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code LaTeX Workshop Extension
&lt;/h3&gt;

&lt;p&gt;หลังจากนี้ให้ติดตั้ง Visual Studio Code LaTeX Workshop Extension เพิ่มทางฝั่ง Remote ทำเหมือนกันทั้ง SSH และ Container&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3972Su0XQg99I0bwowmFlw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A3972Su0XQg99I0bwowmFlw.png"&gt;&lt;/a&gt;Visual Studio Code LaTeX Workshop Extension&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Folder
&lt;/h3&gt;

&lt;p&gt;เมื่อติดตั้ง Extension เสร็จพร้อมใช้งานแล้วถ้าเป็น Remote SSH เราต้องเปิด Folder ก่อนส่วน Remote Container จะเปิดให้แล้วตั้งแต่แรก วิธีเปิดก็ Click ที่ icon files บน Side Bar ด้านซ้าย&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F672%2F1%2A2MehhzYfRS8CPCIoPv65jQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F672%2F1%2A2MehhzYfRS8CPCIoPv65jQ.png"&gt;&lt;/a&gt;Open Folder&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApLpwUmrSUNixx77_rDg7fQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApLpwUmrSUNixx77_rDg7fQ.png"&gt;&lt;/a&gt;ช่องเลือก&lt;/p&gt;

&lt;p&gt;โดยปกติแล้วจะมีช่องให้เลือกโดยเริ่มใน Home Directory ของ root ตอนสั่ง run ผมได้ mount ไว้ที่ /root/data ก็ให้ click ที่ Folder data ได้เลยครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEjF_LLzK7bPKWCVKJmzxdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AEjF_LLzK7bPKWCVKJmzxdg.png"&gt;&lt;/a&gt;เลือก&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvXiW6dwLUOwSO8v00FVeBw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AvXiW6dwLUOwSO8v00FVeBw.png"&gt;&lt;/a&gt;Work Space&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็จะปรากฎหน้าต่าง Work Space สำหรับการทำงานขึ้นมาโดยชื่อในช่อง Explore ด้านซ้ายจะเป็น Folder ที่เราเลือกไว้เมื่อตะกี้&lt;/p&gt;

&lt;p&gt;EP2 จะแนะนำการใช้งาน pdfLaTeX และ XeLaTeX เบื้องต้นต่อไปครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mrchoke/latex-vscode-tex-live-docker-image-ep2-2cgo"&gt;เขียน LaTeX ด้วย VSCode และ TeX Live Docker Image — EP2&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  TeX Live Docker Image
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/r/mrchoke/texlive" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เป็น Image ที่ผม Build ไว้ใช้เองสำหรับการเขียนเอกสารซึ่งจะมี Python พ่วงเข้าไปด้วย สามารถดู Dockerfile ได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mrchoke/texlive" rel="noopener noreferrer"&gt;mrchoke/texlive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;วิธี Build ที่ publish ไว้ใน docker hub ผมใช้ buildx โดยให้ใช้ได้ทั้ง amd64 และ arm64 หมายถึงสามารถใช้บน Docker บนเครื่อง Apple M1 ได้ด้วย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker buildx build --platform linux/arm64,linux/amd64 -t mrchoke/texlive:2021 -t mrchoke/texlive:2021.1 -t mrchoke/texlive:latest --push .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ปกติการติดตั้ง TeX Live ฉบับเต็มจะใช้เนื้อที่ราวๆ 8 GB ในตัว Image ข้างบนผมจะตัดพวก Doc กับ Src ออกเนื้อที่จะลดลงมาเกือบๆ 50% อยู่ที่ราวๆ 4.5 GB&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>thailatex</category>
      <category>latex</category>
      <category>docker</category>
    </item>
    <item>
      <title>How To Format NTFS in Big Sur</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Mon, 25 Jan 2021 17:34:30 +0000</pubDate>
      <link>https://dev.to/mrchoke/how-to-format-ntfs-in-big-sur-51e7</link>
      <guid>https://dev.to/mrchoke/how-to-format-ntfs-in-big-sur-51e7</guid>
      <description>&lt;p&gt;บังเอิญไล่ไปไล่มาไปเจอ Source Code ของ NTFS ที่ใช้ใน macOS มันมีส่วนของ newfs อยู่เหมือนกับ FAT, exFAT และ APFS แต่คำสั่งหายไปเลยเป็นที่มาบันทึกนี้&lt;/p&gt;

&lt;p&gt;จากบทความก่อนหน้าคือการ Read / Write NTFS บน Big Sur&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/nectec/ntfs-read-write-in-big-sur-intel-and-m1-free-7097a2cc8233"&gt;NTFS Read/Write in Big Sur (Intel and M1 ) — Free&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;แต่มันคาใจว่า mount อ่านเขียนได้แต่ทำไมถึงสร้างไม่ได้ก็ไล่ไปเจอ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opensource.apple.com/source/ntfs/ntfs-105.40.1/"&gt;Source Browser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;มาไล่ดูใน macOS ไม่พบคำสั่ง newfs_ntfs แต่มีคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BootCampFormatter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;และเมื่อลองสั่งดูมันก็คือคำสั่ง newfs_ntfs นั่นเอง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LdZLzgG---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aw044S809cpVU-8NqR1Ve8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LdZLzgG---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Aw044S809cpVU-8NqR1Ve8A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  วิธี Format เป็น NTFS
&lt;/h4&gt;

&lt;p&gt;ในตัว Disk Utility มันจะไม่ยอมให้ Format เป็น NTFS แต่สามารถสร้างเป็น ExFAT ได้ ซึ่ง ID ของ Partition จะเป็นตัวเดียวกันคือ 07 ดังนั้นตอนแรกก็ให้ fotmat disk เป็น ExFAT ก่อนแล้วค่อยมา format อีกรอบด้วยคำสั่งข้างบน&lt;/p&gt;

&lt;p&gt;สมมติของเดิมเป็น FAT&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7SNBQUk6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AiGpYN8QHtTgQisCI5MPX4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7SNBQUk6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AiGpYN8QHtTgQisCI5MPX4g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ก็ให้ Click ขวาเลือกแล้ว Erase&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sHZXSqTo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/748/1%2AH3vxb9_1lYkm7v3tASyFxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sHZXSqTo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/748/1%2AH3vxb9_1lYkm7v3tASyFxQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เลือกเป็น ExFAT&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K3DW5ATU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/527/1%2AV-hY0TobNeofHRuGlfWLVA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K3DW5ATU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/527/1%2AV-hY0TobNeofHRuGlfWLVA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--now7UsMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/589/1%2AFO0WEuqxDGMWE0YQZAI7hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--now7UsMl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/589/1%2AFO0WEuqxDGMWE0YQZAI7hw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aGteYg0O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ax1gniP1nH2dVIuyef2Kjlw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aGteYg0O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ax1gniP1nH2dVIuyef2Kjlw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หลังจากนั้นให้ unmount&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wNuzCEEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/635/1%2A27EEHuyT5i9RjwrA7KkPbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wNuzCEEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/635/1%2A27EEHuyT5i9RjwrA7KkPbg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เมื่อได้เรียบร้อยก็เปิด terminal ขึ้นมาแล้วพิมพ์คำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo /System/Library/Filesystems/ntfs.fs/Contents/Resources/BootCampFormatter -v NTFS /dev/disk4s1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FBrPgtrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMB2ZIj6ohNznKMaSGehoxA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FBrPgtrz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AMB2ZIj6ohNznKMaSGehoxA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;โดยเปลี่ยนที่อยู่อุปกรณ์ให้ตรงกับ disk ที่จะ format ซึ่งสามารถดูใน Disk Utility ด้านบนก็ได้ของผมจะเป็น /dev/disk4s1 นั่นเอง&lt;/p&gt;

&lt;p&gt;เมื่อ format เสร็จแล้วลอง mount ดูครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gSbau2oD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/739/1%2AZv-RP5XODj6uV1pSgS0jcQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gSbau2oD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/739/1%2AZv-RP5XODj6uV1pSgS0jcQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ4CRP0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_DMNTFMHwqwFF-jlh0B6Dw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HJ4CRP0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_DMNTFMHwqwFF-jlh0B6Dw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ตอนนี้เราก็ได้ NTFS เรียบร้อยถ้าจะ mount แบบ Read / Write ก็ให้อ่านบทความด้านบนนะครับ&lt;/p&gt;

&lt;p&gt;แต่ทั้งนี้เพื่อความไม่ลำบากก็สามารถใช้ ExFAT แทนได้ซึ่งเราจะไม่ลำบากและใช้ App Disk Utility ได้เลยแต่ถ้าใครทิ้ง NTFS ไม่ได้และไม่มีเครื่อง Windows สำหรับ Format ก็ใช้วิธีนี้ได้ครับไม่ต้องติดตั้งอะไรเพิ่มแต่ลำบากหน่อย&lt;/p&gt;

</description>
      <category>macos</category>
      <category>format</category>
      <category>bigsur</category>
      <category>ntfs</category>
    </item>
    <item>
      <title>NTFS Read/Write in Big Sur (Intel and M1 ) — Free</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Tue, 29 Dec 2020 10:52:34 +0000</pubDate>
      <link>https://dev.to/mrchoke/ntfs-read-write-in-big-sur-intel-and-m1-free-558m</link>
      <guid>https://dev.to/mrchoke/ntfs-read-write-in-big-sur-intel-and-m1-free-558m</guid>
      <description>&lt;h3&gt;
  
  
  NTFS Read/Write in Big Sur (Intel and M1 ) — Free
&lt;/h3&gt;

&lt;p&gt;อ่านเขียน NTFS บน Big Surใช้ได้ทั้ง Intel และ M1 แบบไม่มีค่าใช้จ่ายใดๆ พร้อมตีบวก skill นิดหน่อย ฮาๆ 😛&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZi1CX2hl5BEwMHga4ubNDQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AZi1CX2hl5BEwMHga4ubNDQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;วิธีนี้เคยเขียนไว้ครั้งหนึ่งแต่ค่อนข้าง Manual ไปหน่อยครั้งนี้จะเพิ่มเป็นแบบ กึ่งๆ auto ละกัน บทความเดิมอ่านได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/nectec/catalina-ntfs-rw-no-extra-packages-b1b5b6bd18db" rel="noopener noreferrer"&gt;Catalina NTFS rw (no extra packages)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  เริ่ม
&lt;/h3&gt;

&lt;p&gt;ปกติเมื่อเราเสียบ External แบบ NTFS Big Sur จะ Mount ให้อัตโนมัติแต่มันจะเขียนไม่ได้หลายคนก็พาลกลัวไม่กล้าใช้ Mac ไปเลยก็มี สมมติผมเสียบ USB เข้าไปมันก็จะ ปรากฎอยู่บน Finder หรือ ไม่ก็ Desktop (ทั้งนี้เราก็ต้องตั้งค่าให้มันแสดงด้วยนะ)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F301%2F1%2Acl3CZHN35dacUvD6Rr0m3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F301%2F1%2Acl3CZHN35dacUvD6Rr0m3g.png"&gt;&lt;/a&gt;Finder Sidebar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F648%2F1%2AYwGGEdPYdF_Fs_481gPM3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F648%2F1%2AYwGGEdPYdF_Fs_481gPM3w.png"&gt;&lt;/a&gt;Desktop&lt;/p&gt;

&lt;p&gt;ถ้าดูให้ลึกลงไปอีกนิดก็เปิด terminal ขึ้นมาครับคำสั่งแรกก็&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;diskutil list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuSCkeBEbFWgD0Bn-GJe73w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AuSCkeBEbFWgD0Bn-GJe73w.png"&gt;&lt;/a&gt;diskutil list&lt;/p&gt;

&lt;p&gt;คำสั่งนี้ใช้ดูว่าบนเครื่องเรามี Storage หรือ Hard disk อะไรบ้างมีกี่ลูก กี่ partitions ข้อมูลตรงนี้เราจำเป็นต้องดูเพื่อนำไปใช้งานในบทความนี้ด้วยหลักๆ คือ มองหา USB ของเราให้เจอก่อนหลังจากนั้นก็ดูข้อมูลดังนี้&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ชนิดของ Partition แบบ Windows_NTFS&lt;/li&gt;
&lt;li&gt;ชื่อของ Partition ปกติตอน format เราควรตั้งชื่อให้มันหน่อยตอนเสียบ macOS หรือ Linux จะใช้ชื่อนี้แสดงให้เราดูตอนใช้งาน&lt;/li&gt;
&lt;li&gt;ชื่อของอุปกรณ์ตัวอย่างจะเป็น disk2 และ partition หมายเลข 1 กลายเป็น disk2s1 และ path เต็มๆ ของมันคือ /dev/disk2s1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;เมื่อเราได้ข้อมูลมาแล้วจะดูข้อมูลลึกลงไปอีกก็สามารถใช้คำสั่งดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;diskutil info /dev/disk2s1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATd5Tfq4BrtwQq_HGx7CoeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ATd5Tfq4BrtwQq_HGx7CoeA.png"&gt;&lt;/a&gt;diskutil info&lt;/p&gt;

&lt;p&gt;ข้อมูลที่เราสนใจหลักๆ มี 3 ส่วนเช่นเคย คือ&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ชื่อ เราจะใช้ชื่อนี้แหละในการตั้งค่าจำไว้นะ&lt;/li&gt;
&lt;li&gt;Mount Point หรือ Path ที่ระบบเอา USB ของเราไปเชื่อมต่อและเราสามารถเข้าไปใช้งานได้ แต่ถ้าใช้ finder บางทีเราไม่จำเป็นต้องรู้ก็ได้ แต่ถ้ารู้ก็ดีกว่า แก้ปัญหาบางอย่างได้ลึกขึ้น&lt;/li&gt;
&lt;li&gt;ค่าที่บอกว่าตอนนี้สามารถอ่านเขียนได้ไหมซึ่งปกติ NTFS เสียบเข้าไปแล้วจะอ่านได้อย่างเดียวตามในรูป&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  เริ่มลุยกัน
&lt;/h3&gt;

&lt;p&gt;ก่อนที่จะเริ่มให้เราทำการ eject USB ของเราออกเสียก่อน อาจจะใข้ mouse click ที่ finder ก็ได้หรือจะใช้คำสั่งก็ได้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;diskutil eject /dev/disk2s1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApIXJNwh1Lx9EsbKIW5JNEQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApIXJNwh1Lx9EsbKIW5JNEQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;คราวนี้ก็สร้าง folder ว่างๆ ไว้บน Desktop ซึ่งตั้งให้สื่อกับ USB ของคุณนะ ของผมตั้งง่ายๆ ตามชื่อคือ NTFS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F919%2F1%2A5kwXJ41uHEWeI7G-6wOOHg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F919%2F1%2A5kwXJ41uHEWeI7G-6wOOHg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F916%2F1%2ALuKghu3hwn6wecLsM9CNyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F916%2F1%2ALuKghu3hwn6wecLsM9CNyw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หรือใครจะใช้ terminal สร้างก็ได้นะง่ายดีด้วย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/Desktop/NTFS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เมื่อสร้างเสร็จคราวนี้ให้เราสร้างคำสั่งเพื่อให้มัน mount อัตโนมัติทุกครั้งที่เราเสียบเจ้า USB อันนี้เข้าไป&lt;/p&gt;

&lt;p&gt;พิมพ์คำสั่งดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano -w /etc/fstab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ระบบมันจะถามรหัสผ่านให้เราใส่รหัสของเราบนเครื่อง Mac นี้นะครับ&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็ให้พิมพ์บรรทัดคำสั่งลงไป&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LABEL=NTFS /Users/mrchoke/Desktop/NTFS ntfs rw,auto,nobrowse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFlZgadxMUsU7Ba_a5HTEiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AFlZgadxMUsU7Ba_a5HTEiw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;โดยให้เปลี่ยนค่าให้ตรงกับของเรานะเช่น LABEL=xxx ตามชื่อเรา และ ส่วนของ path&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/Users/xxx/Desktop/yyyy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ก็เปลี่ยนเป็นชื่อ (xxx)เป็น user ของเรา และ ส่วนสุดท้าย (yyy) ก็ตามที่เราจะตั้งให้มัน&lt;/p&gt;

&lt;p&gt;หลังจากนั้นก็ให้ save โดยกดตามขั้นตอนดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Control X

กด y

กด Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYTiF6XYlXs3ooKKfm2H8vA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYTiF6XYlXs3ooKKfm2H8vA.png"&gt;&lt;/a&gt;กด y&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Agabl1G5y4Y0uUsfcpJNmTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Agabl1G5y4Y0uUsfcpJNmTA.png"&gt;&lt;/a&gt;กด Enter&lt;/p&gt;

&lt;h4&gt;
  
  
  ทดสอบกันเลย
&lt;/h4&gt;

&lt;p&gt;ตอนนี้เราก็ลองเอา USB เสียบเข้าไปเลย&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2Auu6uH_uwssdUt_kWNFKXmA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2Auu6uH_uwssdUt_kWNFKXmA.png"&gt;&lt;/a&gt;ICON เปลี่ยนเป็นรูป Disk&lt;/p&gt;

&lt;p&gt;ถ้าเราพิมพ์ไม่พลาดอะไรรูป ICON ของ folder จะเปลี่ยนไปจาก Folder สีฟ้าเป็นรูป Hard Disk สีเทาๆ ตามรูปด้านบนตอนนี้เราก็สามารถใช้งานได้แล้ว click เข้าไปเลย ลองสร้างลองลบข้อมูลได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2Auu6uH_uwssdUt_kWNFKXmA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2Auu6uH_uwssdUt_kWNFKXmA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F918%2F1%2AnC2pWbO17-DRePg6ShWl0Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F918%2F1%2AnC2pWbO17-DRePg6ShWl0Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2A9zj6vTf_Gkw1X13v34-2NQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F914%2F1%2A9zj6vTf_Gkw1X13v34-2NQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F918%2F1%2ASWrRFt1UWVm0wTOGZaVDxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F918%2F1%2ASWrRFt1UWVm0wTOGZaVDxw.png"&gt;&lt;/a&gt;สร้าง ลบข้อมูลได้แสดงว่าสำเร็จ&lt;/p&gt;

&lt;h3&gt;
  
  
  เลิกใช้งาน
&lt;/h3&gt;

&lt;p&gt;ถ้าเราจะถอด USB ออกต้องทำยังไง ก็แค่ Click บน ICON รูป Hard Disk ของมันแล้วเลือก Eject หรือจะ Click พื้นที่ว่างๆ ใน Finder ขณะที่เปิดเข้าใช้งานมันก็ได้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F920%2F1%2AUwFwxvSFpc_pIjn33gl9lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F920%2F1%2AUwFwxvSFpc_pIjn33gl9lg.png"&gt;&lt;/a&gt;Eject&lt;/p&gt;

&lt;p&gt;ถ้าใครจะดู Info ว่าถ้ามันอ่านเขียนได้จะเป็นอย่างไร ก่อน Eject ก็ใช้คำสั่ง info ตามข้างบนอีกครั้ง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApDXjqitJSQC9gp_KG24sMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2ApDXjqitJSQC9gp_KG24sMA.png"&gt;&lt;/a&gt;หลังจากที่เราแก้ไขค่า fstab&lt;/p&gt;

&lt;p&gt;จะเห็นว่า Mount Point จะเปลี่ยนไปตามที่เราตั้งไว้ และ ค่า Read-Only ก็กลายเป็น No เรียบร้อย&lt;/p&gt;

&lt;p&gt;ปล. วิธีแบบนี้จะเฉพาะหน่อยคือ USB อันไหนอันนั้น และ Partition ไหน Partition นั้นนอกจากเราจะตั้งชื่อให้เหมือนกัน แต่ก็ใช้พร้อมกันไม่ได้อีก ลองเอาไปใช้กันดูครับ ไม่ต้องเสียตั้งสักบาท นอกจากจะทำ Disk พัง ฮาๆ (อะ ล้อเล่งๆๆ)&lt;/p&gt;

</description>
      <category>write</category>
      <category>bigsur</category>
      <category>ntfs</category>
      <category>free</category>
    </item>
    <item>
      <title>Windows 10 Python Virtual Environment</title>
      <dc:creator>MrChoke</dc:creator>
      <pubDate>Mon, 28 Dec 2020 04:39:42 +0000</pubDate>
      <link>https://dev.to/mrchoke/windows-10-python-virtual-environment-30h3</link>
      <guid>https://dev.to/mrchoke/windows-10-python-virtual-environment-30h3</guid>
      <description>&lt;p&gt;แอบเล่น Python บน Windows 10 บันทึกไว้สักหน่อย&lt;/p&gt;

&lt;p&gt;ผมใช้ PowerShell นะครับ ซึ่งปกติน่าจะถูกปิดการใช้งาน Script ไว้เพื่อความปลอดภัย ถ้าจะใช้ Python venv แบบไม่ต้องลงตัวช่วยก็ให้เปิดเสียก่อน โดยการเปิด PowerShell ในสิทธิของ Administrator แล้วสั่งคำสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set-executionpolicy RemoteSigned
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เพื่อความปลอดภัยให้ศึกษาเพิ่มเติมได้ที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-7.1"&gt;Set-ExecutionPolicy (Microsoft.PowerShell.Security) - PowerShell&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เมื่อเปิดการใช้งาน Script เสร็จแล้วก็ให้เปิด PowerShell ในสิทธิปกติแล้วสร้าง Director สำหรับ Project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เข้าไปยัง Directory ที่สร้างแล้วทำการสร้าง Virtual Environment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m venv env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราจะเก็บ modules ต่างๆ ใน directory ชื่อ env แต่ก่อนอื่นต้องทำการ activate Environment นี้เสียก่อน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.\env\Scripts\Activate.ps1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ให้สังเกต (env) ข้างหน้า Command Prompt ถ้าสั่งสำเร็จ ซึ่งใน () นี้จะเป็นชื่อของ Directory ที่เราสร้าง Environment ไว้นั่นเอง&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j55A7_r---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/452/1%2AC8vYv5oM1RyEol-FcmwJfw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j55A7_r---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/452/1%2AC8vYv5oM1RyEol-FcmwJfw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ตอนนี้เราก็สามารถใช้งาน python ในสภาพแวดล้อมที่สร้างขึ้นมาได้แล้ว ลองตรวจสอบว่า python ชี้ไปถูกต้องหรือไม่&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Get-Command python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ihzw24f---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANjpukPJ9RD-RultwAPjtxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ihzw24f---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ANjpukPJ9RD-RultwAPjtxQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ตอนนี้สามารถติดตั้ง package ต่างๆ ด้วยคำสั่ง pip ได้ตามต้องการ เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install -U pip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เป็นการ upgrade pip&lt;/p&gt;

&lt;p&gt;หรือจะติดตั้ง opencv&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install opencv-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AiwTXIzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxerRtP15-eW2N4wjg3cR-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AiwTXIzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxerRtP15-eW2N4wjg3cR-w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ณ วันที่ผมเขียน OpenCV ตัวล่าสุดจะมีปัญหากับ numpy ตัวล่าสุดวิธีแก้ปัญหาคือให้ drop numpy ลงไป version หนึ่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install numpy==1.19.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--knmsKnr7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/885/1%2As5Up7-5enJ-0It7Yi7aV3A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--knmsKnr7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/885/1%2As5Up7-5enJ-0It7Yi7aV3A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VSCode&lt;/p&gt;

&lt;p&gt;ถ้าจะใช้ VSCode เขียน Script ก็เรียกใช้งานได้เลย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DjAhFlKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AzaIOaT2Q2Lnrk4Tg8gVztA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DjAhFlKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AzaIOaT2Q2Lnrk4Tg8gVztA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เมื่อเราสร้าง file ที่มีนามสกุล py vscode ก็จะถามเราว่าจะติดตั้ง extension python หรือไม่ก็ติดตั้งไปครับ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rpUOk42v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxhmetTstqG9UfqUnEQvTsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rpUOk42v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxhmetTstqG9UfqUnEQvTsw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เมื่อติดตั้งเสร็จจะมีให้เลือก python version ตรงมุมล่างซ้าย&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RbYEZyY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/415/1%2AlkbV4uYaoVn9GMHoqujN0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RbYEZyY8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/415/1%2AlkbV4uYaoVn9GMHoqujN0A.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click แล้วเลือกไปยัง env ที่เราสร้างไว้&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TGmL2HLp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADQwKGyJjZJIj3XUaCCE42g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TGmL2HLp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADQwKGyJjZJIj3XUaCCE42g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ObtDq-l7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/383/1%2AjMk23ctEEY6hiTX9TvjRTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ObtDq-l7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/383/1%2AjMk23ctEEY6hiTX9TvjRTQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หลังจากนี้ VSCode อาจจะถามให้ติดตั้ง Extension อื่นๆ อีก เช่น Linter ก็ให้ติดตั้งไป&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gJIGTYQj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/507/1%2A151WLCj8aW-OkGqIwRJYQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gJIGTYQj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/507/1%2A151WLCj8aW-OkGqIwRJYQg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หรือถ้าจะใช้ VSCode run Notebook ก็สามารถทำได้เช่นกัน โดยการ Click ขวาที่ชื่อ file แล้วเลือก&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-_QbvWr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/571/1%2AYeOrEQS5Euq7bPK7lNxaGg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q-_QbvWr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/571/1%2AYeOrEQS5Euq7bPK7lNxaGg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jQBbKMId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/535/1%2A_dClQosXPeLYvTUjBDqvJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jQBbKMId--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/535/1%2A_dClQosXPeLYvTUjBDqvJg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E08lvK2p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ACyP8SsB_RnYS1DOlwLoQSg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E08lvK2p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ACyP8SsB_RnYS1DOlwLoQSg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;มีอีกตัวก็ Pylance ที่ควรมีไว้สำหรับช่วยในการเขียน&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ONqEmXxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/765/1%2ADuYPBQtiBXE9rplsjED-dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ONqEmXxX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/765/1%2ADuYPBQtiBXE9rplsjED-dg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;หลักๆ ก็ประมาณนี้เท่าที่นึกออก การใช้ Virtual Environment จะว่ายากก็ยากจะว่าง่ายก็ง่าย ถ้าไม่มีอะไรซับซ้อนวิธีนี้จะกระชับไม่ต้องลงอะไรเพิ่มเติม แต่ถ้ามี dependency ที่ต้องมีการ compile ใหม่วิธีนี้อาจจะเหนื่อยหน่อยก็ใช้ anaconda ช่วยเอา&lt;/p&gt;

</description>
      <category>python</category>
      <category>venv</category>
      <category>windows</category>
      <category>powershell</category>
    </item>
  </channel>
</rss>
