mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
Merge branch 'LCTT:master' into patch-2
This commit is contained in:
commit
aff74f9b5a
@ -0,0 +1,104 @@
|
||||
[#]: subject: "5 open source alternatives to 微软 Exchange"
|
||||
[#]: via: "https://opensource.com/article/21/11/open-source-alternatives-微软-exchange"
|
||||
[#]: author: "Heike Jurzik https://opensource.com/users/hej"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "XiaotingHuang22"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15705-1.html"
|
||||
|
||||
可以替代微软 Exchange 的 5 个开源软件
|
||||
======
|
||||
|
||||
> 不再将就于微软 Exchange 这一专有软件,试一试这些基于 Linux 系统的电子邮件和群件服务吧。
|
||||
|
||||
![][0]
|
||||
|
||||
几十年来,微软 Exchange 一直统治着电子邮件和群件服务市场。作为领头羊,它主宰着企业界,无处不在的 Outlook 邮件客户端已成为群件的事实标准。由于 Exchange 与微软的 Office 产品紧密联系,无论是桌面客户端还是移动客户端,微软用户都可以轻松使用各种生产力软件和功能。
|
||||
|
||||
然而,许多公司对于将数据存储在微软的云中也心存疑虑。在本文中,我将介绍一些开源替代产品及其优势。这不仅与如何不再受供应商控制和降低成本有关,更关乎使用具有开放标准和不同安全级别的软件 —— 用于组件服务器本身及其背后的操作系统。
|
||||
|
||||
本文中介绍的这五个替代产品都是基于 Linux 的。 虽然 grommunio、Kopano、Nextcloud、ownCloud 和 OX App Suite 在功能上差异很大,吸引到的企业类型各不相同,但它们都提供免费版本,并可选择购买付费支持服务和附加组件。所有产品都可以在本地或云端运行。最重要的是,所有供应商都为其软件提供 SaaS(<ruby>软件即服务<rt>Software as a Service</rt></ruby>)解决方案。
|
||||
|
||||
### grommunio
|
||||
|
||||
[grommunio][2],以前被称为 grammm,在 AGPLv3 许可下发布的。它由奥地利同名公司开发和支持。与 Exchange 不同,grommunio 提供符合标准的邮件服务器,以及功能齐全的群件解决方案,具有电子邮件、联系人、日历、任务、文件共享等功能。grommunio 适用于各种开源和专有邮件客户端,如 Windows Mail、Outlook、Android、Apple Mail/iOS、Thunderbird 等,并支持旧的 RPC over HTTP 协议和 Outlook 标准协议 MAPI over HTTP。除此之外还包含:用于移动设备的 Exchange ActiveSync 和各种标准协议,如 CalDAV(日历)、CardDAV(地址簿)、IMAP、POP3、SMTP 和 LDAP,以及活动目录(用于同步用户帐户)。
|
||||
|
||||
外部对接的开源应用程序还提供了一些微软的 API 或协议不支持的功能。例如,开发人员合并了 [Jitsi][3](视频和音频电话软件)、[Mattermost][4](聊天软件)以及文件共享和同步([ownCloud][5])。除此之外,grommunio 还配备了基本的移动设备管理软件(MDM)。
|
||||
|
||||
grommunio 的设计面向各种不同的用户,并且与 Exchange 一样,它支持数据库分片(数据库在多个主机之间的水平分布)。灵活的存储后端允许管理员通过添加其他服务器或云帐户来扩展他们的设置。grommunio 仅将 MySQL 数据库用于元数据,而所有“内容”(例如邮件和群件对象)都存储在每个用户的 SQLite 数据库中。有关底层架构的更多信息,请查看 [该制造商的网站][6]。
|
||||
|
||||
其社区版是免费的,其中包括所有的 grommunio 功能并支持多达五个用户帐户。
|
||||
|
||||
### Kopano
|
||||
|
||||
来自德国和荷兰的软件制造商 Kopano 出品的 [Kopano][7],也采用 AGPLv3 许可,基于 Zarafa 软件堆栈。与其前身不同,Kopano 的目标不只是成为 Exchange 的替代品。相反,它提供一个完整的群件解决方案,除了电子邮件、联系人、日历、任务、笔记和文档编辑这些标准功能外,它还包括实时通信。Kopano 可以与 [许多其他平台][8]、应用程序和服务交互,其中一些通过插件就能轻松实现。对于视频会议,Kopano 团队基于 WebRTC 开发了自己的开源解决方案:Kopano Meet 提供端到端加密,在 Windows、macOS、Linux、Android 和 iOS 客户端都适用。
|
||||
|
||||
Outlook 客户端通过 ActiveSync(Z-Push 库)或 [Kopano OL Extension][9](KOE)来同步移动数据,KOE 是已经包含了 ActiveSync 的加强版。Kopano 提供本机 Web 客户端(WebApp)、移动设备客户端(Mobility)以及支持 Windows、Linux 和 macOS 的桌面版本(DeskApp)。它可以通过 IMAP、CalDAV 和 CardDAV 连接其他客户端。所有直接连接到 Kopano 服务器的应用程序都使用 SOAP(<ruby>简单对象访问协议<rt>Simple Object Access Protocol</rt></ruby>)中的 MAPI。
|
||||
|
||||
Kopano Groupware 和 Kopano ONE(Kopano Groupware 的特别版)都提供免费的社区版本。 Kopano Meet 还可以作为应用程序或容器下载。
|
||||
|
||||
### Nextcloud
|
||||
|
||||
[Nextcloud][10] 在斯图加特和柏林(德国)都有办事处,采用 AGPLv3 许可。与 ownCloud 或 Dropbox 一样,用户可以通过桌面(Windows、Linux 和 macOS)、网络浏览器或本地应用程序(Android 和 iOS)访问该软件套件。从 18 版本开始,Nextcloud 除了拥有 Nextcloud Files(文件同步和共享)还包括了 Nextcloud Talk(通话、聊天和网络会议)和 Nextcloud Groupware(日历、联系人和邮件),并更名为 Nextcloud Hub。
|
||||
|
||||
用户和群组管理通过 OpenID 或 LDAP 进行。Nextcloud 支持各种存储后端,例如 FTP、S3 和 Dropbox。Nextcloud 可与多种数据库管理系统配合使用,包括 PostgreSQL、MariaDB、SQLite 和 Oracle 数据库。管理员可以通过 [Nextcloud 应用程序商店][11] 中的 200 多个应用程序扩展功能,其中包括实时通信、音频和视频聊天、任务管理、邮件等等。
|
||||
|
||||
Nextcloud 是完全免费的。最重要的是,该公司提供了 Nextcloud Enterprise 版本(针对企业部署进行了预配置、优化和强化)
|
||||
|
||||
### ownCloud
|
||||
|
||||
[ownCloud][12] 是由位于德国纽伦堡的 ownCloud GmbH 公司开发和维护的具有文件同步、共享和内容协作功能的软件。它的客户端-服务器软件的核心和许多社区应用程序都是在 AGPLv3 下发布的。一些扩展功能的企业应用程序以 ownCloud 商业许可证(OCL)的形式授权。
|
||||
|
||||
ownCloud 主要是一款内容协作软件,包括在线办公文档编辑、日历、联系人同步等功能。移动客户端支持 Android 和 iOS,桌面应用可以和 Windows、macOS 和 Linux 的原生文件管理器结合使用。它允许访问 Web 界面,无需安装专用客户端软件。ownCloud 支持 WebDAV、CalDAV 和 CardDAV 协议。LDAP 协议也包含其中,但 ownCloud 也可以连接到支持 OpenID Connect 身份验证标准的其他身份提供者。
|
||||
|
||||
ownCloud 可以整合微软 Office Online Server、Office 365 和微软 Teams,同时为微软 Outlook 和 eM 客户端提供可用插件。如有必要,外部存储功能可连接到不同的存储提供商,例如 Amazon S3、Dropbox、微软 SharePoint、Google Drive、Windows 网络驱动器(SMB)和 FTP。该供应商还为企业客户提供额外的功能,如端到端加密、勒索软件和防病毒保护等(请参阅 [完整功能列表][13])。
|
||||
|
||||
社区版免费且 100% 开源。
|
||||
|
||||
### OX App Suite
|
||||
|
||||
[Open-Xchange][14] 成立于 2005 年,总部位于德国奥尔佩和纽伦堡。今天,OX 在多个欧洲国家、美国和日本设有办事处。[OX App Suite][15] 是一个模块化的电子邮件、通信和协作平台,主要为电信公司、托管公司和其他提供基于云的服务的提供商而设计。
|
||||
|
||||
OX 后端在 GPLv2 协议下发布,前端(UI)在 AGPLv3 下发布。用户可以通过他们喜欢的浏览器(完全个性化的门户)或移动应用程序(Android 和 iOS)访问应用程序套件。或者,原生客户端(移动设备和台式机)也可用于 OX Mail 和 OX Drive。得益于 CardDAV 和 CalDAV 扩展、Exchange Active Sync 和适用于 Android 的 OX Sync App,联系人、日历和任务得以同步。
|
||||
|
||||
OX App Suite 包含用于电子邮件、联系人、日历和任务的应用程序。 还有其他工具和扩展可用,其中一些是开源的,一些功能则要付费,包括 OX Documents(文本文档、电子表格、演示文稿)、OX Drive(管理、共享和同步文件)、OX Guard(电子邮件和文件加密)等等。如需完整列表,请访问 OX 网站的 [一般条款和条件][16]。
|
||||
|
||||
该应用免费提供有限功能的社区版。
|
||||
|
||||
### 开源电子邮件和群件
|
||||
|
||||
电子邮件和群件服务并不是必须花(很多)钱才可获得,当然也没有必要满足于在别人的服务器上托管的专有解决方案。如果你不太热衷于管理职责,那么上述的这五个 Exchange 开源替代品都可以作为 SaaS 解决方案使用。另外,所有供应商都提供专业技术支持,你可以在本地运行软件,一切尽在你的掌握中,但你却不会感觉自己孤军无援。
|
||||
|
||||
(题图由 MJ 生成:Mail Cooperation Groupware Office Open Source hyper realistic, hyper detailed, intricate detail, beautiful lighting, very detailed,Illustration)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/11/open-source-alternatives-微软-exchange
|
||||
|
||||
作者:[Heike Jurzik][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[XiaotingHuang22](https://github.com/XiaotingHuang22)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hej
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_dev_email_chat_video_work_wfm_desk_520.png?itok=6YtME4Hj (Working on a team, busy worklife)
|
||||
[2]: https://grommunio.com/
|
||||
[3]: https://opensource.com/article/20/5/open-source-video-conferencing
|
||||
[4]: https://opensource.com/article/20/7/mattermost
|
||||
[5]: https://opensource.com/article/21/7/owncloud-windows-files
|
||||
[6]: https://grommunio.com/features/architecture/
|
||||
[7]: https://kopano.com/
|
||||
[8]: https://kopano.com/products/interoperability/
|
||||
[9]: https://kb.kopano.io/display/WIKI/Setting+up+the+Kopano+OL+Extension
|
||||
[10]: https://nextcloud.com/
|
||||
[11]: https://apps.nextcloud.com/
|
||||
[12]: https://owncloud.com/
|
||||
[13]: https://owncloud.com/features/
|
||||
[14]: https://www.open-xchange.com/
|
||||
[15]: https://www.open-xchange.com/products/ox-app-suite/
|
||||
[16]: https://www.open-xchange.com/terms-and-conditions/
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/09/114919i7cu0zwk4e663x0c.jpg
|
100
published/20211205 Open source mind mapping with Draw.io.md
Normal file
100
published/20211205 Open source mind mapping with Draw.io.md
Normal file
@ -0,0 +1,100 @@
|
||||
[#]: subject: "Open source mind mapping with Draw.io"
|
||||
[#]: via: "https://opensource.com/article/21/12/open-source-mind-mapping-drawio"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "FYJNEVERFOLLOWS"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15700-1.html"
|
||||
|
||||
使用开源思维导图 Draw.io
|
||||
======
|
||||
|
||||
> 下次你需要头脑风暴、组织想法或计划项目时,不妨试试 Draw.io。
|
||||
|
||||
![][0]
|
||||
|
||||
地图有一些特别之处。我记得小时候打开托尔金《霍比特人》的封面,盯着手绘的中土世界地图,感受简单的图画中蕴含着丰富的可能性。除了描述事物与其他事物之间的关系这一明显目的外,我认为地图在表达可能性方面做得很好。你可以到户外去,沿着这条路或那条路走,如果你这样做了,去想想你将能够看到的所有新的、令人兴奋的事物。
|
||||
|
||||
尽管如此,地图并不一定是有价值和充满可能性的文字。有些地图描述了一个思维过程、计划、算法,甚至是一些随机的想法,这些想法拼命地想要组合成一件潜在的艺术作品,它们被称之为“思维导图”、“流程图”或“创意板”。可以用开源的 [Draw.io][2] 应用程序去很容易地制作。
|
||||
|
||||
### 安装 Draw.io
|
||||
|
||||
Draw.io 是一个开源的在线应用程序,因此你可以将其作为在线应用程序使用,下载 [桌面版本][3],或 [克隆 Git 存储库][4] 并将其托管在你自己的服务器上。
|
||||
|
||||
### 使用 Draw.io 画图
|
||||
|
||||
当你第一次启动 Draw.io 时,你需要选择保存数据的位置。如果你自己托管 Draw.io,你的选择取决于你可以访问哪些 API 密钥。你可以从几个在线存储服务中为在线公共实例进行选择,这取决于你的帐户。如果你不想把你的数据存储在别人的服务器上,你也可以选择把你的工作保存在本地存储上。如果你还不确定,可以单击 “<ruby>稍后决定<rt>Decide later</rt></ruby>” 继续进入应用程序,而无需选择任何内容。
|
||||
|
||||
Draw.io 的交互界面中间有一个很大的工作空间,左边是主工具栏,顶部是工具栏,右边是属性面板。
|
||||
|
||||
![Draw.io interface][5]
|
||||
|
||||
工作流程很简单:
|
||||
|
||||
1. 从左侧工具栏中选择一个形状。
|
||||
2. 在工作空间中编辑形状。
|
||||
3. 添加另一个形状,并连接它们。
|
||||
|
||||
重复这个过程,你就得到了一张图。
|
||||
|
||||
![Draw.io example][7]
|
||||
|
||||
### 项目规划
|
||||
|
||||
当你第一次接受一项大任务时,你通常对你想要的结果有一个非常清晰的想法。假设你想开始一个社区项目来画一幅壁画。你想要的结果是一幅壁画。它很容易定义,你可以或多或少地在脑海中描绘出结果。
|
||||
|
||||
然而,一旦你开始朝着目标前进,你就必须开始弄清楚细节。壁画应该画在哪里?即便知道画在哪,你如何获得在公共墙上作画的许可的?油漆呢?你应该用一种特殊的油漆吗?你会用刷子还是喷枪涂油漆?你需要什么样的专业设备来喷漆?画一幅壁画需要多少人和多长时间?画家工作时的支持服务怎么样?最后,这幅画是关于什么的?一个想法很快就会变得势不可挡,因为你离实现它越近。
|
||||
|
||||
这不仅仅适用于绘制壁画、制作戏剧或电影。它几乎适用于任何不平凡的努力。这正是像 Draw.io 这样的应用程序可以帮助绘制的。
|
||||
|
||||
以下是如何使用 Draw.io 创建项目流程图:
|
||||
|
||||
1. 从头脑风暴开始。没有什么想法是太小或太大的。为每个想法制作一个框,然后双击 Draw.io 工作空间中的框以输入文本。
|
||||
2. 一旦在工作空间中你产生了可能想到的所有想法,就可以将它们拖放到相关的组中。我们的目标是创建一些小任务云或集群,因为它们是同一过程的一部分,所以或多或少会一起进行。
|
||||
3. 一旦你确定了相关任务的集群,就为这些任务命名。例如,如果你正在绘制壁画,那么任务可能是 “许可”、“设计”、“购买”、“绘制”,这反映出你需要首先获得当地政府的许可,然后设计壁画,然后购买用品,最后绘制壁画。每个任务都有组成部分,但大体上,你现在已经确定了项目的工作流程。
|
||||
4. 用箭头连接主要任务。并不是所有的过程都是完全线性的。例如,在你获得市议会的许可后,一旦你设计了你打算画的东西,你可能必须回到他们那里进行最终批准。这很正常。这是一个循环,有一些来回,但最终,你会突破这个循环,进入下一阶段。
|
||||
5. 掌握好你的流程图,完成每一项任务,直到你达到最终目标。
|
||||
|
||||
### 思维导图
|
||||
|
||||
思维导图往往不是关于进步,而是关于保持某种状态或对许多想法进行展望。例如,假设你已经决定减少生活中的浪费。你对自己能做什么有一些想法,但你想组织和保存你的想法,这样你就不会忘记它们。
|
||||
|
||||
以下是如何使用 Draw.io 创建思维导图:
|
||||
|
||||
1. 从头脑风暴开始。没有什么想法是太琐碎或太大的。为每个想法制作一个框,然后双击 Draw.io 工作空间中的框以输入文本。也可以通过选择框并单击右侧属性面板中的色样,为框指定背景色。
|
||||
2. 将你的想法分组或分类。
|
||||
3. 可以选择将想法与彼此直接相关的箭头连接起来。
|
||||
|
||||
![Draw.io waste reduction example][8]
|
||||
|
||||
### 保存你的图表
|
||||
|
||||
你可以将图表保存为 PNG、JPG 图像、Draw.io XML 或纯 XML 文件。如果将其另存为 XML,则可以在 Draw.io 中再次打开它进行进一步编辑。导出的图像非常适合与他人共享。
|
||||
|
||||
### 使用 Draw.io
|
||||
|
||||
有很多很棒的绘图应用程序,但我不经常制作图表,所以可以随时使用 Draw.io。它的界面简单易用,结果干净专业。下次当你需要头脑风暴、组织想法或计划项目时,可以试试 Draw.io。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/12/open-source-mind-mapping-drawio
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[FYJNEVERFOLLOWS](https://github.com/FYJNEVERFOLLOWS)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/career_journey_road_gps_path_map_520.png?itok=PpL6jJgY (Looking at a map for career journey)
|
||||
[2]: http://draw.io
|
||||
[3]: https://github.com/jgraph/drawio-desktop
|
||||
[4]: https://github.com/jgraph/drawio
|
||||
[5]: https://opensource.com/sites/default/files/uploads/draw-io-ui.png (Draw.io interface)
|
||||
[6]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[7]: https://opensource.com/sites/default/files/uploads/draw-io-example.jpg (Draw.io example)
|
||||
[8]: https://opensource.com/sites/default/files/uploads/draw-io-export.jpg (Draw.io waste reduction example)
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/07/144214m945y0naawn5zb95.jpg
|
@ -0,0 +1,91 @@
|
||||
[#]: subject: "Open Source Software: Is There an Easy Path to Success?"
|
||||
[#]: via: "https://www.opensourceforu.com/2022/07/open-source-software-is-there-an-easy-path-to-success/"
|
||||
[#]: author: "Jules Graybill https://www.opensourceforu.com/author/jules-graybill/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "CanYellow"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15702-1.html"
|
||||
|
||||
开源软件:存在成功的捷径吗?
|
||||
======
|
||||
|
||||
> 开发开源软件背后的工作是相当庞大的。那么我们如何保证开源项目的成功呢?存在捷径吗?本文认为是没有的。
|
||||
|
||||
![][0]
|
||||
|
||||
今天,开源已经风靡世界。很多大型企业在快速成功的诱惑下被推向开源。但真实情况是世界上并不存在成功的捷径。你无法做到通过一次努力就能让所有的开源项目正常运行。
|
||||
|
||||
事实上,上述公司早期遇到的许多挑战都不是技术上的,而是人员与文化上的。
|
||||
|
||||
开发一个能够在市场上获得成功的开源项目需要在开源的许多层面上下功夫。而维持这样的成功是一个持续的过程。所有这一切的关键在于找到以下这个非常基本的问题的正确答案:开源究竟是什么。
|
||||
|
||||
### 开源是代码
|
||||
|
||||
对于很多新用户而言,他们可能并不完全了解开源的不同层面,答案相当简单:开源就是软件!这当然没有错,毕竟我们多数人就是这样使用它的。不过,相比仅仅被视作软件而言,开源远不止这些。
|
||||
|
||||
任何开源项目的实质仍然是代码本身。代码是使一个开源项目有别于其他项目,并使其对用户有益的根本。当你从事开源工作的时候,代码和软件一样都是产品的一部分。
|
||||
|
||||
从零开始开发一个开源项目或者 <ruby>复刻<rt>fork</rt></ruby> 一个现有项目,即便是在面对一个庞大而复杂的代码库时,也需要编写成千上万行代码。尤其是在创建一个现有项目的复刻的情况下,在移除任何在先的许可证、宣传材料或者其他任何可能已经失去作用的文件时必须小心翼翼(LCTT 校注:部分开源项目不允许你改变其原有的许可证)。终究是一个项目的功能吸引了它的用户群并维持项目的持续发展。当最终用户在考虑是否使用开源软件的时候,他们会阅读项目的源代码,而他们在其中所看到的应当是那些能够建立他们的信心的内容。
|
||||
|
||||
### 开源是社区
|
||||
|
||||
如何参与到社区中也是产品构建的一部分。创建一个社区并维护一个健康的社区关系是开源的核心之一,但对于大部分的领导者而言也往往是最坚难的任务,很少有人能很好地维护它。你可以尝试建立基金会或者提供赞助,但是最终还是由人们自行决定是否想要加入社区。
|
||||
|
||||
重要的是与社区保持一定程度的透明度,并不断保持。社区成员可以在它想要的任何阶段参与进来。除了需要进行的工作之外,诸如安全设置、签发证书、注册商标等,尽可能多的将你所做的工作展示给社区是相当重要的,这有助于取得社区信任。归根到底,你需要对社区负责,你的项目成也社区,败也社区。这可能会导致你的项目开发更谨慎、更缓慢并且向社区公开,不过项目最终会进展顺利。
|
||||
|
||||
如此地公开你正在进行的工作似乎有些令人生怯,尤其是当你担心更新推迟或者是出现漏洞的影响的时候。不过,让社区成员知悉你的进展,不仅有助帮助你建立与社区之间的信任关系,而且能够让社区成员感到被认可。
|
||||
|
||||
另一方面,公开你的工作流也可以获得来自社区成员的监督,他们经常有自己的见解并向你反馈。记录这些反馈是很重要的,这使得你的开源项目如实地反映社区需求。他们是项目的最终用户,而他们的反馈则反映了他们如何看待你的项目的长期发展,以及你的项目最终将有多么成功或者主流。
|
||||
|
||||
举例而言,当我们在考虑一个新功能的时候,我们在 <ruby>征求意见文档<rt>Request for Comments</rt></ruby>(RFC)中发布一个征集意见的请求,我们会收到大量的反馈,我们必须认真思考应当如何吸收这些反馈。
|
||||
|
||||
因为开源是一个大型的合作项目,社区对支持开源项目的主动支持,使项目成为了最好的项目。并非所有的问题都要解决,但只要你有在倾听社区的呼声,社区就会有参与感。
|
||||
|
||||
参与到社区中也存在一些隐患。社区内部、项目维护与社区之间均可能存在不同意见,尤其是在涉及治理的问题上。治理对于一个开源项目来说是相当重要的。这也就是为什么拥有一份清晰的文档化的治理条例对于项目以及社区均是如此重要。
|
||||
|
||||
社区治理是一个关键的而又难啃的骨头。社区授权本身需要相当大的信任。对于一个拥有成千上万行代码的项目,在社区中寻找能够有效领导社区的人物是不容易的。不过开源项目经常是由更小的子项目组成的,这些子项目最好由社区中的某个人进行管理。这有助于社区更紧密地参与到项目中。
|
||||
|
||||
建立社区的过程不是一帆风顺的。让我列举一一些有助于维持社区与我的团队之间平衡的技巧。
|
||||
|
||||
**声明你的原则:** 尤其是在开源项目的早期,在项目代码仍在完善,很多事情还不完美的时候,项目之外的人员很难真正理解你所做的决定。向他们说明你做出决定所依据的原则,有助于你在思考过程上保持坦率,从而让社区不会错误地干扰你的事务。这一经验非常有效,在你做出决定时坚持遵循其中一项原则并展示出来是非常重要的。
|
||||
|
||||
**确定如何进行协作:** 你可以通过 Discord、Slack 或者邮件等途径完成这一工作。但是如果你试图同时使用它们,你将毫不意外的分散项目社区。社区人员将在所有这些途径上互相交流。选择一到两种沟通工具,投身于它们来保证社区的信息同步。
|
||||
|
||||
**珍惜反馈意见:** 倾听来自社区的反馈并付诸行动。即使需要你作出艰难的决定,你也应当向社区展示你是重视社区话语的。
|
||||
|
||||
**维护一套行为准则:** 如果你与社区打交道,你需要定义什么行为是可以接受的。一套落地的行为准则有助于在人们越过红线时警示他们。如果你可以提前制定这些你可以避免很多麻烦。
|
||||
|
||||
**考虑如何分发你的项目:** 存在这样的情况,因为你还没有准备好某一个组件,或者是因为存在一些你不希望所有人都能够访问的项目功能,所以你可能并不希望将你的项目完全向公众公开。关键是制定符合你的要求而不是向用户妥协的分发条款,如此,需要某种功能的用户可以获取所需项目的同时,不需要该功能的用户也不需要在开始使用该项目做出妥协。
|
||||
|
||||
**尽可能地避免投票:** 这是因为部分成员经常会赞成与大部分成员的意见相左的选项,这会使这些人产生一定程度的失望,并让他们觉得被项目所孤立。反之,尽量尝试询问他们想要解决什么问题,并尝试创造一个不需要付出代价的解决方案。
|
||||
|
||||
### 开源是许可
|
||||
|
||||
开源是给予你的用户如何使用你的软件的自由,而许可能够做到这一点。开源项目许可的好处在于,它保证了不论你作为维护者做了什么,你的所有最终用户以及利益相关方总是可以维护一系列的项目复刻版本,这些都是重要的项目复刻。
|
||||
|
||||
许可提供了人们可选择性,如果他们认为有必要,他们可以将项目带到不同的路径中。他们拥有创建副本的权利,这使得许多优秀的软件能够被开发出来。维护者有责任倾听他们的社区成员的声音,并以一个对项目的社区成员有利的方式运营项目。
|
||||
|
||||
我们推荐使用现有的许多可用的许可证,而不是独立制作你自己的许可条款,原因很简单,因为用户以及利益相关方通常都很熟悉常用的许可证,因此你不需要再花费时间在解释许可条款上。这将帮助你将你的精力集中在项目的其他部分上。
|
||||
|
||||
### 最后,开源是一项运动
|
||||
|
||||
开源包括了很多维度,也包含了很多人员。最重要的是,它是关于理解人们想要什么,并创建一个鼓励协作与透明的环境。开源也是关于创建社区,帮助建立走自己想走的开源项目的方式。维护者创造越多的机会让社区自由发挥,开源产品就越好,也越发成功。
|
||||
|
||||
开源是以上所有这些方面,而你的视野越宽阔,你就能越好的利用它。请考虑你如何能够在开源的每一个维度上出类拔萃,因为时至今日,开源的成功之路并无捷径。
|
||||
|
||||
---
|
||||
|
||||
via: https://www.opensourceforu.com/2022/07/open-source-software-is-there-an-easy-path-to-success/
|
||||
|
||||
作者:[Jules Graybill][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[CanYellow](https://github.com/CanYellow)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.opensourceforu.com/author/jules-graybill/
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://www.opensourceforu.com/wp-content/uploads/2022/07/team-work-working-together-1.jpg
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/08/122245uqlbfaxp3flkwf5b.jpg
|
@ -7,14 +7,14 @@
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15697-1.html"
|
||||
|
||||
NixOS 系列 #5:如何在 NixOS 上设置家庭管理员?
|
||||
NixOS 系列 #5:如何在 NixOS 上设置主目录管理器
|
||||
======
|
||||
|
||||
在发表这篇文章之前,我解释了如何为一个单用户系统 [在 NixOS 中安装和删除软件包][1]。
|
||||
|
||||
但是,如果你正在供多个用户使用,有一个很好的方法来分别满足每个用户的需求。
|
||||
|
||||
在本指南中,我将指导你如何在 NixOS 上设置一个家庭管理员,以及如何使用它来安装软件包。
|
||||
在本指南中,我将指导你如何在 NixOS 上设置一个 <ruby>主目录管理器<rt>Home Manager</rt></ruby>,以及如何使用它来安装软件包。
|
||||
|
||||
如果你是新读者,本系列中讨论的一些资源包括:
|
||||
|
||||
@ -22,18 +22,18 @@ NixOS 系列 #5:如何在 NixOS 上设置家庭管理员?
|
||||
- [在虚拟机上安装 NixOS][3]
|
||||
- [安装 NixOS 后要做的事情][4]
|
||||
|
||||
### 在 NixOS 上设置家庭管理员
|
||||
### 在 NixOS 上设置主目录管理器
|
||||
|
||||
在本指南中,我将指导你通过 2 种方式来设置家庭管理员:
|
||||
在本指南中,我将指导你通过 2 种方式来设置主目录管理器:
|
||||
|
||||
- 独立的家庭管理员(使用单独的配置文件)
|
||||
- 独立的主目录管理器(使用单独的配置文件)
|
||||
- 作为一个 NixOS 模块(在 `configuration.nix` 文件中使用它)
|
||||
|
||||
那么,让我们从独立方式开始。
|
||||
|
||||
#### 独立安装的家庭管理员
|
||||
#### 独立安装的主目录管理器
|
||||
|
||||
如果你使用的是 NixOS 的稳定频道,你可以使用以下命令来配置家庭管理器:
|
||||
如果你使用的是 NixOS 的稳定频道,你可以使用以下命令来配置主目录管理器:
|
||||
|
||||
```
|
||||
nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager
|
||||
@ -55,7 +55,7 @@ nix-channel --add https://github.com/nix-community/home-manager/archive/master.t
|
||||
nix-channel --update
|
||||
```
|
||||
|
||||
最后,使用下面的命令来安装家庭管理员:
|
||||
最后,使用下面的命令来安装主目录管理器:
|
||||
|
||||
```
|
||||
nix-shell '<home-manager>' -A install
|
||||
@ -63,19 +63,19 @@ nix-shell '<home-manager>' -A install
|
||||
|
||||
🛠️ 在安装时,可能会出现以下错误:
|
||||
|
||||
![安装家庭管理员时出现构建错误][5]
|
||||
![安装主目录管理器时出现构建错误][5]
|
||||
|
||||
重新启动你的系统并再次使用安装命令,它将开始安装。
|
||||
|
||||
一旦完成,它将显示独立安装的家庭管理员的位置:
|
||||
一旦完成,它将显示独立安装的主目录管理器的位置:
|
||||
|
||||
![家庭管理员在NixOS中的位置][6]
|
||||
![主目录管理器在NixOS中的位置][6]
|
||||
|
||||
#### 将家庭管理员安装为 NixOS 模块
|
||||
#### 将主目录管理器安装为 NixOS 模块
|
||||
|
||||
> ⚠️ 如果你选择将家庭管理员作为 NixOS 模块使用,你将需要 sudo 权限。
|
||||
> ⚠️ 如果你选择将主目录管理器作为 NixOS 模块使用,你将需要 sudo 权限。
|
||||
|
||||
如果你在一个稳定的频道上(在写本文的时候,是 `22.11`),你可以使用下面的命令来添加家庭管理员的稳定频道:
|
||||
如果你在一个稳定的频道上(在写本文的时候,是 `22.11`),你可以使用下面的命令来添加主目录管理器的稳定频道:
|
||||
|
||||
```
|
||||
sudo nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager
|
||||
@ -105,7 +105,7 @@ sudo nano /etc/nixos/configuration.nix
|
||||
<home-manager/nixos>
|
||||
```
|
||||
|
||||
![将家庭管理员安装为 NixOS 模块][7]
|
||||
![将主目录管理器安装为 NixOS 模块][7]
|
||||
|
||||
现在,跳到该行的末尾,在 `}` 前添加以下内容:
|
||||
|
||||
@ -115,7 +115,7 @@ home-manager.users.{username} = { pkgs, ... }: {
|
||||
};
|
||||
```
|
||||
|
||||
![NixOS 配置文件中的家庭管理员模块的格式][8]
|
||||
![NixOS 配置文件中的主目录管理器模块的格式][8]
|
||||
|
||||
上面这一行是为了方便安装和删除软件包而添加的,我接下来会告诉你。
|
||||
|
||||
@ -133,9 +133,9 @@ sudo nixos-rebuild switch
|
||||
|
||||
![错误: 选项 `home-manager.users.user.home.stateVersion` 已被使用但未被定义。][10]
|
||||
|
||||
要解决这个问题,你必须在你的家庭管理器块中添加 `home.stateVersion`。
|
||||
要解决这个问题,你必须在你的主目录管理器块中添加 `home.stateVersion`。
|
||||
|
||||
在写这篇文章时,我正在运行 22.11,所以整个家庭管理员块看起来像这样:
|
||||
在写这篇文章时,我正在运行 22.11,所以整个主目录管理器块看起来像这样:
|
||||
|
||||
```
|
||||
home-manager.users.{username} = { pkgs, ... }: {
|
||||
@ -150,11 +150,11 @@ home-manager.users.{username} = { pkgs, ... }: {
|
||||
|
||||
现在,试着重建配置并再次进行切换,应该可以解决问题。
|
||||
|
||||
### 如何在 NixOS 上使用家庭管理员安装软件包
|
||||
### 如何在 NixOS 上使用主目录管理器安装软件包
|
||||
|
||||
现在你已经安装了家庭管理员,如何用它来安装软件包:
|
||||
现在你已经安装了主目录管理器,如何用它来安装软件包:
|
||||
|
||||
#### 使用独立安装的家庭管理员
|
||||
#### 使用独立安装的主目录管理器
|
||||
|
||||
首先,用下面的方法打开配置文件:
|
||||
|
||||
@ -192,7 +192,7 @@ home.packages = with pkgs; [htop];
|
||||
|
||||
例如,在这里,我想安装 `htop`、`firefox`和 `libreoffice`,所以我的 `home` 块会看起来像这样:
|
||||
|
||||
![在 NixOS 上使用家庭管理员安装多个软件包][12]
|
||||
![在 NixOS 上使用主目录管理器安装多个软件包][12]
|
||||
|
||||
一旦你完成了添加你喜欢的软件包,保存配置文件并使用以下命令来安装软件包:
|
||||
|
||||
@ -208,7 +208,7 @@ home-manager switch
|
||||
sudo nano /etc/nixos/configuration.nix
|
||||
```
|
||||
|
||||
在配置部分,我已经添加了家庭管理员块,所以剩下的就是在 `home.packages = [ ];` 里面添加软件包的名称,格式如图所示:
|
||||
在配置部分,我已经添加了主目录管理器块,所以剩下的就是在 `home.packages = [ ];` 里面添加软件包的名称,格式如图所示:
|
||||
|
||||
```
|
||||
home.packages = [ pkgs.package_name ] ;
|
||||
@ -222,9 +222,9 @@ home.packages = [ pkgs.package_name ] ;
|
||||
pkgs.htop pkgs.firefox pkgs.libreoffice
|
||||
```
|
||||
|
||||
然后我的家庭管理员块会看起来像这样:
|
||||
然后我的主目录管理器块会看起来像这样:
|
||||
|
||||
![作为 NixOS 模块在家庭管理员中安装多个软件包][14]
|
||||
![作为 NixOS 模块在主目录管理器中安装多个软件包][14]
|
||||
|
||||
现在,保存修改并退出文本编辑器。
|
||||
|
||||
|
@ -0,0 +1,68 @@
|
||||
[#]: subject: "Open source tools for mind mapping"
|
||||
[#]: via: "https://opensource.com/article/23/3/open-source-mind-mapping"
|
||||
[#]: author: "Amrita https://opensource.com/users/amrita42"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15708-1.html"
|
||||
|
||||
开源思维导图工具
|
||||
======
|
||||
|
||||
![][0]
|
||||
|
||||
> 使用思维导图与开源工具来做一个有影响力的演示。
|
||||
|
||||
在今天的世界和社交媒体中,许多人没有耐心阅读冗长的文字内容。视觉效果是吸引受众注意力的好方法。
|
||||
|
||||
你知道吗,3M 公司的研究得出结论,视觉的处理速度是文字的 60,000 倍?视觉比文字更有冲击力,能增强创造性思维和记忆。
|
||||
|
||||
### 一图胜千言
|
||||
|
||||
我收集了一些常见的 [Git 命令][1]。我把 Git 命令作为主话题,每个子话题都是一个带有定义的 Git 命令语法。为此,我使用了 Wisemapping。
|
||||
|
||||
![A git command mind map][2]
|
||||
|
||||
不管你以前是否知道 [思维导图][3] 是什么,现在你看到了思维导图,你就可以理解这个概念了。这就是视觉的力量。
|
||||
|
||||
### 如何创建一个思维导图?
|
||||
|
||||
- 从主话题开始,把它放在你的画板中间。
|
||||
- 创建子话题并将它们与主话题联系起来。
|
||||
- 你可以为每个子话题添加细节,如定义、例子等。
|
||||
|
||||
### 3 个你可以用来创建思维导图的开源工具
|
||||
|
||||
看看这三个开源工具,为你的想法创建一个视觉:
|
||||
|
||||
- [Wisemapping][4]
|
||||
- [Freeplane][5]
|
||||
- [Semantik][6]
|
||||
|
||||
维基百科对思维导图的定义是:将信息直观地组织成一个层次结构,显示整体中各部分之间的关系。思维导图从一个中心话题开始,然后建立起关系。它是一种结构化思想和创造有影响力的演示的视觉方式。
|
||||
|
||||
你可以在工作中使用思维导图。例如,我用思维导图来展示一个项目所计划的功能的高层概述。有了这些优秀的开源思维导图应用,你很容易就能开始将你的下一个项目可视化。试试用开源的思维导图吧。
|
||||
|
||||
*(题图:MJ:Thinking Brainstorming Creativity Ideas Discussion Illustrations Blue Gold Simplicity)*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/3/open-source-mind-mapping
|
||||
|
||||
作者:[Amrita][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/amrita42
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://opensource.com/downloads/cheat-sheet-git
|
||||
[2]: https://opensource.com/sites/default/files/2023-03/mindmap.jpg
|
||||
[3]: https://opensource.com/article/21/12/open-source-mind-mapping-drawio
|
||||
[4]: https://www.wisemapping.com/
|
||||
[5]: https://opensource.com/article/19/1/productivity-tool-freeplane
|
||||
[6]: https://waf.io/semantik.html
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/10/114653pwq2z2md5mootf05.jpg
|
@ -3,14 +3,18 @@
|
||||
[#]: author: "Don Watkins https://opensource.com/users/don-watkins"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15703-1.html"
|
||||
|
||||
使用这个开源的会计应用来管理你的小企业
|
||||
======
|
||||
|
||||
[GnuCash][1] 是一个强大而灵活的会计工具,可用于小企业的发票和会计。它的许多功能使它特别适合这一目的,包括跟踪支出和收入、生成报告和管理发票的能力。此外,GnuCash 是免费和开源的,这使得资源有限的小企业也可以使用它。在这篇文章中,我会讨论 GnuCash 的特点,使你可以很容易地在自己的小企业中开始使用它。
|
||||
![][0]
|
||||
|
||||
> 用 GnuCash 跟踪客户和发票的情况。
|
||||
|
||||
[GnuCash][1] 是一个强大而灵活的会计工具,可用于小企业的发票和会计。它的许多功能使它特别适合这一目的,包括跟踪支出和收入、生成报告和管理发票的能力。此外,GnuCash 是自由开源的,这使得资源有限的小企业也可以使用它。在这篇文章中,我会讨论 GnuCash 的特点,使你可以很容易地在自己的小企业中开始使用它。
|
||||
|
||||
几年前,我开始使用 GnuCash 进行个人财务管理,但发现它也可以作为我的小企业的一个有用工具。在我企业的大部分时间里,我一直在使用一个专有的解决方案。我逐渐厌倦了被迫定期升级以获取我的小企业的发票和报表。转而使用 GnuCash,使我能够在不牺牲任何功能的情况下,将我的小企业会计与我的个人财务相结合。
|
||||
|
||||
@ -33,33 +37,33 @@ $ sudo dnf install gnucash
|
||||
GnuCash 带有一个账户设置向导,可以帮助你建立一个普通的商业账户配置。要访问它:
|
||||
|
||||
- 启动 GnuCash。
|
||||
- 点击**文件**菜单,选择**新文件**。
|
||||
- 点击 “<ruby>文件<rt>File</rt></ruby>” 菜单,选择 “<ruby>新文件<rt>New File</rt></ruby>”。
|
||||
|
||||
按照屏幕上出现的 GnuCash 助手来创建你的新商业账户文件。
|
||||
|
||||
屏幕上的说明将指导你完成设置业务的过程。单击“**助手**”窗口右上角的“**下一步**”。系统会提示你输入公司名称、地址、联系信息和你自己选择的公司 ID。你还必须选择默认税表和日期格式。
|
||||
屏幕上的说明将指导你完成设置业务的过程。单击 “<ruby>助手<rt>Assistant</rt></ruby>” 窗口右上角的 “<ruby>下一步<rt>Next</rt></ruby>”。系统会提示你输入公司名称、地址、联系信息和你自己选择的公司 ID。你还必须选择默认税表和日期格式。
|
||||
|
||||
下一个页面提示你选择货币,有大量的货币支持。
|
||||
|
||||
然后提示你选择你要创建的账户。选择创建**企业账户**的选项。你可以随时定制账户列表,GnuCash 提供了[大量的文档][2],帮助你更好地根据个人需求进行定制。
|
||||
然后提示你选择你要创建的账户。选择创建 “<ruby>企业账户<rt>Business Accounts</rt></ruby>” 的选项。你可以随时定制账户列表,GnuCash 提供了 [大量的文档][2],帮助你更好地根据个人需求进行定制。
|
||||
|
||||
完成助手,然后单击 GnuCash **助手**窗口右上角的**应用**。
|
||||
完成助手,然后单击 GnuCash “助手” 窗口右上角的 “<ruby>应用<rt>Apply</rt></ruby>”。
|
||||
|
||||
### 添加客户
|
||||
|
||||
GnuCash 的顶部菜单有一个标有**业务**的菜单项。该菜单上的第一个项目是**客户**,其次是**客户概览**。在这里你可以查看你所有客户的列表。
|
||||
GnuCash 的顶部菜单有一个标有 “<ruby>业务<rt>Business</rt></ruby>” 的菜单项。该菜单上的第一个项目是 “<ruby>客户<rt>Customers</rt></ruby>”,其次是 “<ruby>客户概览<rt>Customers Overview</rt></ruby>”。在这里你可以查看你所有客户的列表。
|
||||
|
||||
下一个项目是**新客户**。这是你输入新客户的地方。对话框为客户信息提供了一个位置,包括帐单信息、运输地址、电子邮件地址、电话号码等。
|
||||
下一个项目是 “<ruby>新客户<rt>New Customer</rt></ruby>”。这是你输入新客户的地方。对话框为客户信息提供了一个位置,包括帐单信息、运输地址、电子邮件地址、电话号码等。
|
||||
|
||||
### 创建一个发票
|
||||
|
||||
添加客户后,你可以开始创建发票的过程。点击**业务**菜单,选择**客户**,然后点击**新发票**。
|
||||
添加客户后,你可以开始创建发票的过程。点击 “业务” 菜单,选择 “客户”,然后点击 “<ruby>新发票<rt>New Invoice</rt></ruby>”。
|
||||
|
||||
付款处理也很简单。这位于**业务**菜单中。选择**客户**,然后**处理付款**。
|
||||
付款处理也很简单。这位于 “业务” 菜单中。选择 “客户”,然后 “<ruby>处理付款<rt>Process Payment</rt></ruby>”。
|
||||
|
||||
### 你在做生意了
|
||||
|
||||
如果你的业务需要,**业务**菜单还包括输入供应商和雇员的选项。有一个菜单项用于销售税和许多其他选项,以确保你符合当地的要求。
|
||||
如果你的业务需要,“业务” 菜单还包括输入供应商和雇员的选项。有一个菜单项用于销售税和许多其他选项,以确保你符合当地的要求。
|
||||
|
||||
使用 GnuCash,你的数据不是以专有格式存储的,所以如果你需要,你可以在将来迁移到任何其他平台。数据存储的开放标准,特别是当这些数据是法律要求的时候,是很重要的,可以让你完全拥有你的商业历史。使用 GnuCash 使你能控制你的小企业。
|
||||
|
||||
@ -70,7 +74,7 @@ via: https://opensource.com/article/23/3/open-source-accounting-run-business
|
||||
作者:[Don Watkins][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -78,3 +82,4 @@ via: https://opensource.com/article/23/3/open-source-accounting-run-business
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://www.gnucash.org/
|
||||
[2]: https://www.gnucash.org/docs/v4/C/gnucash-guide/bus_setup.html
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/08/150133rfxheuuce1ufi99c.jpg
|
@ -3,37 +3,39 @@
|
||||
[#]: author: "Pratham Patel https://itsfoss.com/author/pratham/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "mcfd"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15709-1.html"
|
||||
|
||||
Rust 基础系列 #1: 创建并运行你的首个 Rust 程序
|
||||
======
|
||||
|
||||
![][1]
|
||||
![][0]
|
||||
|
||||
Rust 是被开发者和科技公司所采用最快的系统编程语言之一。它也被每天使用它的开发者评为**最受欢迎的编程语言**之一。其[已经][2]**[连续七年][2]**[受到这种欢迎了][2]!
|
||||
> 在 Rust 编程系列的第一篇中,你将学习如何用 Rust 编写和执行你的第一个程序。
|
||||
|
||||
Rust 是最快风靡开发者和科技公司的系统编程语言之一。日常使用它的开发者将其评为**最受欢迎的编程语言**之一,而它 [已经连续七年获此殊荣了][2]!
|
||||
|
||||
它是如此的受欢迎,以致于现在有两股巨大的推力将其带入 Linux 生态系统中:
|
||||
|
||||
- 包括 [Rust 将作为 Linux 内核的第二支持语言][3]
|
||||
- [将 Rust 作为 Linux 内核的二级支持语言][3]
|
||||
- System76 [正在使用 Rust 重写他们自己的桌面环境][4]
|
||||
|
||||
而这仅仅是在 Linux 生态系统中。安卓的蓝牙实现 [Gabeldorsche][5] 现在也是由 Rust 编写的。
|
||||
而这还仅仅是在 Linux 生态系统中。安卓上的蓝牙软件 [Gabeldorsche][5] 现在也是由 Rust 编写的。
|
||||
|
||||
你是否看到了 Rust 的流行趋势?你大概率可能想学习使用 Rust 进行编程。
|
||||
你是否也看到了 Rust 的流行趋势?那么你或许也想学习使用 Rust 进行编程。
|
||||
|
||||
### 为什么你要考虑 Rust 而不是其他编程语言?
|
||||
|
||||
首先,Rust 是一门 **类型安全的编程语言** 并且 **拥有极其严格的编译期检查**。因此,你首先会 “被迫” 写不出不安全的代码(好吧,通常)。
|
||||
首先,Rust 是一门 **类型安全的编程语言** 并且 **拥有极其严格的编译期检查**。因此,你首先会 “被迫” 写不出不安全的代码(好吧,通常是这样)。
|
||||
|
||||
Rust 编程语言有以下 "目标":
|
||||
Rust 编程语言有以下 “目标”:
|
||||
|
||||
- **性能**:Rust 的二进制文件和 C 语言的二进制文件一样快,有时甚至超过了 C++ 的二进制文件!
|
||||
- **性能**:Rust 的二进制文件和 C 语言的二进制文件一样快,有时甚至超过了 C++ 的二进制文件!
|
||||
- **内存安全**:Rust 非常重视内存安全。
|
||||
- **并发**:对内存安全的关注消除了很多类似竞争的情况,并帮助你在程序中无畏并发。
|
||||
- **并发性**:对内存安全的关注消除了很多类似竞争的情况,并帮助你在程序中无畏并发。
|
||||
|
||||
以下是在 C/C++ 等语言中可能犯的一些错误(但不是 Rust):
|
||||
以下是在 C/C++ 等语言中可能犯的一些错误(但 Rust 不会):
|
||||
|
||||
- 释放后使用
|
||||
- 双重释放
|
||||
@ -43,9 +45,9 @@ Rust 编程语言有以下 "目标":
|
||||
- 使用未经初始化的变量
|
||||
- 线程不安全的多线程
|
||||
|
||||
看看 [Apple][6], [Microsoft][7], [Google][8], [0day][9] 等大公司因这类错误而引起的问题吧。
|
||||
看看 [苹果][6]、[微软][7]、[谷歌][8] 等大公司因这类 [0day][9] 错误而引起的问题吧。
|
||||
|
||||
现在你可能知道了为什么要选择 Rust 语言而不是其他编程语言,让我们开始学习 Rust 语言的系列教程吧!
|
||||
现在你可能知道了为什么要选择 Rust 语言而不是其他编程语言,让我们开始学习 Rust 语言的系列教程吧!
|
||||
|
||||
### 目标受众
|
||||
|
||||
@ -58,7 +60,7 @@ Rust 编程语言有以下 "目标":
|
||||
### 安装 Rust 工具链
|
||||
|
||||
我希望你能在本地安装 [Rust 工具链][10]。你可以通过运行以下命令来做到这一点:
|
||||
(LCTT 译注:如果你使用 Linux 发行版,请不要直接安装软件源里的 Rust 工具链,尽管这样看起来很便捷)
|
||||
(LCTT 译注:如果你使用 Linux 发行版,请不要直接安装软件源里的 Rust 工具链,尽管这样看起来很便捷。)
|
||||
|
||||
```
|
||||
curl --proto '=https' --tlsv1.3 -sSf https://sh.rustup.rs | sh
|
||||
@ -72,21 +74,23 @@ curl --proto '=https' --tlsv1.3 -sSf https://sh.rustup.rs | sh
|
||||
rustup component add rust-src rust-analyzer rust-analysis
|
||||
```
|
||||
|
||||
💡
|
||||
你还需要 [安装 gcc][14]。否则,你可能会遇到“链接器 `cc` 未找到”的错误。该软件包在不同的发行版中都被称为 gcc。
|
||||
|
||||
如果你不希望在本地安装 Rust 工具链,不用担心。你还可以直接在你的浏览器中运行 Rust 代码!只要到
|
||||
在 Ubuntu 和 Debian 上使用:
|
||||
|
||||
[Rust Playgrounds website][12]
|
||||
```
|
||||
sudo apt install gcc
|
||||
```
|
||||
|
||||
并把所讨论的代码粘贴在此处。
|
||||
> 💡 如果你不希望在本地安装 Rust 工具链,不用担心。你还可以直接在你的浏览器中运行 Rust 代码!只要到 [Rust 试验场][12] 并把所讨论的代码粘贴在那里。
|
||||
|
||||
### Hello Rust!
|
||||
|
||||
自从 Dennis Ritchie 和 Brian Kernighan 用 "Hello world" 程序介绍了 C 语言后,在 UNIX 世界里,对你学习的任何新的编程语言都要这样做,这已经成为一种习惯。
|
||||
自从 <ruby>丹尼斯·里奇<rt>Dennis Ritchie</rt></ruby> 和 <ruby>布莱恩・柯林汉<rt>Brian Kernighan</rt></ruby> 用 “Hello World” 程序介绍了 C 语言后,在 UNIX 世界里,你学习的任何新编程语言第一步都这样做,这已经成为一种习惯。
|
||||
|
||||
因此,让我们也用 Rust 编写我们的 Hello World 程序。
|
||||
|
||||
我将在我的家目录里[新建一个项目目录][13]叫做 `learn-rust-its-foss`。然后,在这里我将新建一个叫 `hello-world` 的目录。最后,在里面新建 `main.rs` 文件:
|
||||
我将在我的家目录里 [新建一个项目目录][13] 叫做 `learn-rust-its-foss`。然后,在这里我将新建一个叫 `hello-world` 的目录。最后,在里面新建 `main.rs` 文件:
|
||||
|
||||
```
|
||||
// 这串代码将打印字符
|
||||
@ -97,37 +101,11 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
📋
|
||||
|
||||
就像 C、C++ 和 Java 源代码文件的扩展名是
|
||||
|
||||
```
|
||||
.c
|
||||
```
|
||||
|
||||
、
|
||||
|
||||
```
|
||||
.cpp
|
||||
```
|
||||
|
||||
和
|
||||
|
||||
```
|
||||
.java
|
||||
```
|
||||
|
||||
Rust 的源文件扩展名是
|
||||
|
||||
```
|
||||
.rs
|
||||
```
|
||||
|
||||
文件扩展名
|
||||
> 📋 就像 C、C++ 和 Java 源代码文件相应的扩展名是 `.c`、`.cpp` 和 `.java`,Rust 的源文件扩展名是 `.rs`。
|
||||
|
||||
作为一个 C/C++ 程序员,你可能已经在 [Linux 上使用 GCC][14],在 macOS 上使用 `Clang`,在 Windows 上使用 MSVC。但是为了编译 Rust 代码,该语言的创造者自己提供了一个官方的 `rustc` 编译器。
|
||||
|
||||
运行 Rust 程序和[执行 C/C++ 程序][15]是一样的。你首先编译代码,然后得到可执行文件,最后再运行这个可执行文件从而来运行代码。
|
||||
运行 Rust 程序和 [执行 C/C++ 程序][15] 是一样的。你首先编译代码,然后得到可执行文件,最后再运行这个可执行文件从而来运行代码。
|
||||
|
||||
```
|
||||
$ ls
|
||||
@ -142,55 +120,47 @@ $ ./main
|
||||
Hello world!
|
||||
```
|
||||
|
||||
很好!
|
||||
很好!
|
||||
|
||||
### 破译 Rust 代码
|
||||
### 解读 Rust 代码
|
||||
|
||||
现在你已经编写、编译并运行了你的第一个 Rust 程序,让我们对 "Hello world" 的代码进行解构并理解每一部分。
|
||||
现在你已经编写、编译并运行了你的第一个 Rust 程序,让我们对 “Hello World” 的代码进行解读,并理解每一部分。
|
||||
|
||||
```
|
||||
fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
`fn` 关键字是用来在 Rust 中声明一个函数的。在它后面 `main` 是这个被声明函数的名字。像许多编译型编程语言一样,`main` 是一个特殊的函数,用来作为你的程序的入口。
|
||||
`fn` 关键字用来在 Rust 中声明一个函数。在它后面 `main` 是这个被声明函数的名字。像许多编译型编程语言一样,`main` 是一个特殊的函数,用来作为你的程序的入口。
|
||||
|
||||
任何写在 `main` 函数里的代码(在大括号 `{``}` 中)将在程序被启动时运行。
|
||||
任何写在 `main` 函数里的代码(在大括号 `{` `}` 之间)将在程序被启动时运行。
|
||||
|
||||
#### println 宏
|
||||
|
||||
在 `main` 函数中, 有一个语句(LCTT 译注:语句 区别于 表达式):
|
||||
在 `main` 函数中, 有一个语句(LCTT 译注:“语句” 区别于 “表达式”):
|
||||
|
||||
```
|
||||
println!("Hello world!");
|
||||
```
|
||||
|
||||
就像C语言的标准库有 `printf` 函数一样,Rust语言的标准库有 `println` **macro**。宏类似于函数,但它以**感叹号**来区分。你将在本系列的后面学习宏和函数的知识。
|
||||
就像 C 语言的标准库有 `printf` 函数一样,Rust 语言的标准库有 `println` **宏**。宏类似于函数,但它以**感叹号**(`!`)来区分。你将在本系列的后面学习宏和函数的知识。
|
||||
|
||||
`println` 宏接收一个格式化的字符串,并把它放到程序的标准输出中(在我们的例子中,就是终端)。由于我希望输出一些文本而不是一个变量,我将把文本放在双引号(`"`)内。最后,我用一个分号来结束这个语句,表示语句的结束。
|
||||
`println` 宏接收一个格式化的字符串,并把它放到程序的标准输出中(在我们的例子中,就是终端)。由于我希望输出一些文本而不是一个变量,我将把文本放在双引号(`"`)内。最后,我用一个分号来结束这个语句,表示语句的结束。
|
||||
|
||||
📋
|
||||
|
||||
你只需知道,任何看起来像函数调用但有感叹号的东西
|
||||
|
||||
```
|
||||
!
|
||||
```
|
||||
|
||||
就是 Rust 编程语言中的一个宏。
|
||||
> 📋 你只需知道,任何看起来像函数调用但在开头括号前有感叹号的东西,就是 Rust 编程语言中的一个宏。
|
||||
|
||||
#### 注释
|
||||
|
||||
Rust 遵循已知的 C 编程语言的注释风格。单行注释以两个正斜杠(`//`)开始,多行注释以 `/*` 开始,以 `*/` 结束。
|
||||
Rust 遵循已知的 C 编程语言的注释风格。单行注释以两个正斜杠(`//`)开始,多行注释以 `/*` 开始,以 `*/` 结束。
|
||||
|
||||
```
|
||||
// this is a multi-line comment
|
||||
// but nothing stops me to doing the same
|
||||
// on the second or third line too!
|
||||
// 这是一个多行注释
|
||||
// 但是没有什么阻止你在
|
||||
// 第二行或第三行也这样写
|
||||
|
||||
/*
|
||||
* this is a "true" mutli-line comment
|
||||
* because it is _fancy_
|
||||
* 这是一个“真•多行注释”
|
||||
* 它看起来比较漂亮
|
||||
*/
|
||||
```
|
||||
|
||||
@ -198,9 +168,11 @@ Rust 遵循已知的 C 编程语言的注释风格。单行注释以两个正斜
|
||||
|
||||
你刚刚通过 Hello World 程序迈出了用 Rust 写代码的第一步。
|
||||
|
||||
作为一种练习,也许你可以编写并执行一个打印出 "Yes! I did Rust" 的 Rust 程序。
|
||||
作为一种练习,也许你可以编写并执行一个打印出 `Yes! I did Rust` 的 Rust 程序。
|
||||
|
||||
在本系列的下一部分中,你将学习在 Rust 程序中使用变量。敬请期待!
|
||||
在本系列的下一部分中,你将学习在 Rust 程序中使用变量。敬请期待!
|
||||
|
||||
*(题图:MJ:computer sci-fi ,code secure ,"rust" ,gold blue slive ,background dark, high resolution super detailed)*
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -209,7 +181,7 @@ via: https://itsfoss.com/rust-introduction/
|
||||
作者:[Pratham Patel][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[mcfd](https://github.com/mcfd)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -230,3 +202,4 @@ via: https://itsfoss.com/rust-introduction/
|
||||
[13]: https://itsfoss.com/make-directories/
|
||||
[14]: https://learnubuntu.com/install-gcc/?ref=itsfoss.com
|
||||
[15]: https://itsfoss.com/run-c-program-linux/
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/10/164143yksc0b56bbs0itiu.jpg
|
@ -3,52 +3,56 @@
|
||||
[#]: author: "Jessica Cherry https://opensource.com/users/cherrybomb"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15699-1.html"
|
||||
|
||||
用 Emojicode 写一个可爱的程序
|
||||
======
|
||||
|
||||
在这篇文章中,我将介绍一个最好的编码语言,学习如何制作任何东西!它叫做 Emojicode。Emojicode 由 Theo Belaire 在 2014 年创建,是一种开源的编程语言,使用 emoji 字符来表示其语法。在 Emojicode 中工作时,emoji 被用来创建变量、函数和控制结构。因为它是一种静态类型的语言,变量类型必须在使用前声明,但它也支持类和继承等面向对象的概念。这种语言可以在每个操作系统上运行,它是一种超级有趣的编码方式,特别是当你是一个非英语母语的人时。这很有帮助,因为象形图表示法可以把我们大家聚集在一起,让我们以类似数学的方式说同样的语言。
|
||||
![][0]
|
||||
|
||||
> 这种有趣的开源语言是学习编码真正的完美选择。
|
||||
|
||||
在这篇文章中,我将介绍一个最好的编码语言,学习如何制作任何东西!它叫做 Emojicode,是由 Theo Belaire 在 2014 年创建的,它是一种开源的编程语言,使用 emoji 字符来表示其语法。当用 Emojicode 开发时,表情符被用来创建变量、函数和控制结构。因为它是一种静态类型的语言,变量类型必须在使用前声明,但它也支持类和继承等面向对象的概念。这种语言可以在每个操作系统上运行,它是一种超级有趣的编码方式,特别是当你是一个非英语母语的人时。这很有帮助,因为象形表示可以把我们大家聚集在一起,让我们以类似数学的方式说同样的语言。
|
||||
|
||||
### 先决条件
|
||||
|
||||
在本教程中,我使用的是基于 Debian 的操作系统。我的工具可能与你的操作系统的要求不同。以下是我所使用的工具:
|
||||
|
||||
- [Geany][1],一个 Linux 下的开源 IDE。
|
||||
- IBus,它允许你挑选 emoji 并把它们放在你的编辑器中。我使用的界面被称为 **emoji picker**。
|
||||
- IBus,它允许你挑选表情符并把它们放在你的编辑器中。我使用的界面被称为 **emoji picker**。
|
||||
- 基于 Debian 的 Linux。
|
||||
- 一个 C++ 编译器。我使用的是 `g++` 编译器。
|
||||
- [Emojicode][2]
|
||||
|
||||
我使用的是 Linux 操作系统,但你可以[阅读文档][3]了解在其他操作系统上使用它时可能需要采取的任何特殊步骤。
|
||||
我使用的是 Linux 操作系统,但你可以 [阅读文档][3] 了解在其他操作系统上使用它时可能需要采取的任何特殊步骤。
|
||||
|
||||
### 在 Linux 上安装 Emojicode
|
||||
|
||||
有几种方法可以在你的电脑上安装 Emojicode,但他们有一个很酷的[神奇的安装页面][4],可以告诉你具体该怎么做。下面是我的做法:
|
||||
有几种方法可以在你的电脑上安装 Emojicode,但它们有一个很酷的 [神奇的安装页面][4],可以告诉你具体该怎么做。下面是我的做法:
|
||||
|
||||
```
|
||||
$ wget https://github.com/emojicode/emojicode/releases/download/v1.0-beta.2/Emojicode-1.0-beta.2-Linux-x86_64.tar.gz -O emojicode.tar.gz \
|
||||
&& tar -xzf emojicode.tar.gz && rm emojicode.tar.gz \
|
||||
&& cd Emojicode-1.0-beta.2-Linux-x86_64 && ./install.sh \
|
||||
&& cd .. && rm -r Emojicode-1.0-beta.2-Linux-x86_64
|
||||
&& tar -xzf emojicode.tar.gz && rm emojicode.tar.gz \
|
||||
&& cd Emojicode-1.0-beta.2-Linux-x86_64 && ./install.sh \
|
||||
&& cd .. && rm -r Emojicode-1.0-beta.2-Linux-x86_64
|
||||
```
|
||||
|
||||
emojicode的安装过程提供了有用的反馈。
|
||||
Emojicode 的安装过程提供了有用的反馈。
|
||||
|
||||
![The emojicode installation procedure provides useful feedback along the way.][5]
|
||||
|
||||
现在,你已经安装好了,是时候开始编写代码了!
|
||||
|
||||
### 整体是如何进行的?
|
||||
### 它是怎么运作的?
|
||||
|
||||
首先,所有 Emojicode 文件的扩展名都以文件名.🍇结尾,但因为你不能在一般的文件名中这样做,所以它被翻译成 `filename.emojic`。这里是最重要的语法元素:
|
||||
首先,所有 Emojicode 文件的扩展名都以文件名 `.🍇` 结尾,但因为你不能在一般的文件名中这样做,所以它被翻译成 `filename.emojic`。这里是最重要的语法元素:
|
||||
|
||||
- 把 🏁 放在一行的开头,表示要执行哪些代码块
|
||||
- 用 🍇 开始一个代码块
|
||||
- 用 🍉 来结束一个代码块
|
||||
- 想打印什么吗?就用 😀 🔤 `<string>` 🔤 ❗
|
||||
- 把 `🏁` 放在一行的开头,表示要执行哪些代码块
|
||||
- 用 `🍇` 开始一个代码块
|
||||
- 用 `🍉` 来结束一个代码块
|
||||
- 想打印什么吗?就用 `😀 🔤 <string> 🔤 ❗`
|
||||
|
||||
还有很多其他的,所以这里有一些实际的例子。
|
||||
|
||||
@ -75,7 +79,6 @@ haiku haiku.emojic haiku.o
|
||||
|
||||
正如你所看到的,代码已经被编译并生成了两个文件,其中一个是可执行的。运行 `haiku` 文件:
|
||||
|
||||
|
||||
```
|
||||
$ ./haiku
|
||||
Emojicode is great,
|
||||
@ -85,27 +88,27 @@ no sadness, just joy.
|
||||
|
||||
### 数学和变量操作
|
||||
|
||||
接下来,你要同时做几件事:一点点数学和变量的改变。首先,将一个变量赋值为0:
|
||||
接下来,你要同时做几件事:一点点数学和变量的改变。首先,将一个变量赋值为 0:
|
||||
|
||||
```
|
||||
0 ➡️ 🖍🆕x
|
||||
```
|
||||
|
||||
你刚刚使用 crayon emoji 和变量名称旁边的新 emoij 创建了一个新变量,同时还将该变量赋值为 0。
|
||||
你刚刚使用蜡笔(`🖍`)表情符、新建(`🆕`)表情符和变量名称创建了一个新变量,同时还将该变量赋值为 0。
|
||||
|
||||
接下来,用磁铁的 emoji 打印一行包括该变量的内容:
|
||||
接下来,用磁铁(`🧲`)表情符打印一行包括该变量的内容:
|
||||
|
||||
```
|
||||
😀 🔤The value is 🧲x🧲 🔤 ❗
|
||||
```
|
||||
|
||||
接下来,使用加号和箭头 emoji 改变变量:
|
||||
接下来,使用加号(`➕`)和箭头(`⬅️`)表情符改变变量:
|
||||
|
||||
```
|
||||
x ⬅️➕ 1
|
||||
```
|
||||
|
||||
然后打印另一行的值。我继续这样做了一会儿,然后打印出最终的数值。下面是我的做法:
|
||||
然后打印另一行的值。如此这般,然后打印出最终的数值。如下:
|
||||
|
||||
```
|
||||
🏁 🍇
|
||||
@ -140,7 +143,7 @@ The value is 7
|
||||
The final value is 3
|
||||
```
|
||||
|
||||
如你所见,作为变量打印出来的所有内容都已使用新数学进行了更新。你可以用许多数学 emoji 来进一步操作。下面是一些更多的运算符:
|
||||
如你所见,作为变量打印出来的所有内容都已使用新数学进行了更新。你可以用许多数学表情符来进一步操作。下面是一些更多的运算符:
|
||||
|
||||
```
|
||||
🚮 is your modulo
|
||||
@ -166,11 +169,11 @@ The final value is 3
|
||||
🆕🔡▶️👂🏼❗️ ➡️ inputText
|
||||
```
|
||||
|
||||
我试图让它工作,但当我发现它时我的编译器出现了一些问题。 你也可能会在这里和那里遇到一些小问题。 如果你遇到了,请创建一个[问题][6],这样它就有可能被修复。
|
||||
我试图让它工作,我的编译器出现了一些问题,我发现了这个问题。你也可能会在这里和那里遇到一些小问题。如果你遇到了,请创建一个 [议题][6],这样它就有可能被修复。
|
||||
|
||||
### 没有技巧,只有很棒的代码
|
||||
|
||||
虽然我可以了解更多,但我可以向你保证,这段令人惊叹的代码背后的文档非常广泛。尽管我写这篇文章只是为了赶上愚人节的乐趣,但我不得不承认这是有史以来最好的语言之一,因为它教会了你很多非常真实的编程概念。我恳切地建议把它作为一种有趣的方式来教你的一些朋友、孩子,或者是对编码感兴趣的同学。 希望你度过了一个充满乐趣的愚人节!
|
||||
虽然我可以介绍更多内容,但我可以向你保证,这段令人惊叹的代码背后的文档非常丰富。尽管我写这篇文章只是为了赶上愚人节的乐趣,但我不得不承认这是有史以来最好的语言之一,因为它教会了你很多非常真实的编程概念。我恳切地建议把它作为一种有趣的方式来教你的一些朋友、孩子,或者是对编码感兴趣的同学。希望你度过了一个充满乐趣的愚人节!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -179,7 +182,7 @@ via: https://opensource.com/article/23/4/emojicode
|
||||
作者:[Jessica Cherry][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
@ -191,3 +194,4 @@ via: https://opensource.com/article/23/4/emojicode
|
||||
[4]: https://www.emojicode.org/docs/guides/
|
||||
[5]: https://opensource.com/sites/default/files/2023-03/emoji.webp
|
||||
[6]: https://github.com/emojicode/emojicode/issues
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/07/141230yv2s53itmiw45ots.jpg
|
151
published/20230407.2 ⭐️⭐️ Xubuntu 23.04 Best New Features.md
Normal file
151
published/20230407.2 ⭐️⭐️ Xubuntu 23.04 Best New Features.md
Normal file
@ -0,0 +1,151 @@
|
||||
[#]: subject: "Xubuntu 23.04: Best New Features"
|
||||
[#]: via: "https://www.debugpoint.com/xubuntu-23-04/"
|
||||
[#]: author: "Arindam https://www.debugpoint.com/author/admin1/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "wxy"
|
||||
[#]: reviewer: "wxy"
|
||||
[#]: publisher: "wxy"
|
||||
[#]: url: "https://linux.cn/article-15706-1.html"
|
||||
|
||||
Xubuntu 23.04 的最佳新功能
|
||||
======
|
||||
|
||||
![][0]
|
||||
|
||||
> 一些很酷的功能将在 Xubuntu 23.04 “Lunar Lobster” 版本中出现。
|
||||
|
||||
Xubuntu 23.04,基于即将发布的 [Ubuntu 23.04 “Lunar Lobster”][1],将于 2023 年 4 月 20 日到达。这个最新版本建立在 Linux 内核 6.2 上,带来了最新的硬件、CPU、GPU 和文件系统支持。
|
||||
|
||||
从改进的小程序到更强大的 Thunar 文件管理器,Xubuntu 23.04 提供了大量的改进和错误修复,通过所有 Linux 桌面的 “OG” —— Xfce 4.18,提供了更精炼的用户体验。
|
||||
|
||||
![Xubuntu 23.04 桌面][2]
|
||||
|
||||
如果你正在使用之前的 Xubuntu 22.10,那么你可能会注意到桌面环境的明显变化。Xubuntu 22.10 以开发版 Xfce 4.17 为特色,并带有来自 Xfce 4.18 少量功能。
|
||||
|
||||
考虑到这一点,让我们来看看 Xubuntu 23.04 “Lunar Lobster” 的最佳新功能。
|
||||
|
||||
### Xubuntu 23.04 的最佳新功能
|
||||
|
||||
#### Xfce 4.18 更新
|
||||
|
||||
这个版本中的一个重要变化是对 Xfce 桌面环境的更新。Xubuntu 23.04 基于 2022 年 12 月发布的 [最新的 Xfce 4.18][3]。Xfce 4.18 是该桌面环境的一个重要里程碑,提供了对 GTK4 的更新、对 Wayland 的初始支持以及对核心原生应用的改造,更新量很大。
|
||||
|
||||
顶部主面板已经更新了新的设置和调整,而整体外观仍与早期版本相同。一些默认的面板小程序在这个版本中也被改变了,而桌面图标、右键上下文菜单和项目保持不变。
|
||||
|
||||
![Xfce 4.18 中的面板偏好][4]
|
||||
|
||||
面板首选项得到了增强,有两个新的选项。首先,面板的长度现在是以像素为单位,而不是百分比。其次,增加了一个新的选项,“保持面板在窗口上方”,允许用户将窗口对话放到面板后面。在早期版本中,应用程序窗口只能达到面板边缘。
|
||||
|
||||
在 Xfce 4.18 中对时钟小程序的设置进行了大修。用户终于可以改变 Xfce 时钟小程序的字体风格,并且有四个时钟布局选项:只显示日期,只显示时间,日期和时间,以及时间和日期。
|
||||
|
||||
#### Thunar 文件管理器的更新
|
||||
|
||||
由于在 [Google Summer of Code 2022][5] 期间所做的工作,用户现在可以在 Thunar 的嵌入式侧边栏中看到图片预览,或者在独立模式下出现在右侧的新面板中,这可以通过偏好设置进行更改。
|
||||
|
||||
Thunar 的设置也得到了加强,增加了一个新的标签用于定制键盘快捷键。用户现在可以直接指定新的组合键,并从这个标签中改变现有的组合键。
|
||||
|
||||
一个新的搜索图标已经取代了工具栏中的重载按钮,当点击它时,它会在地址栏中调出搜索,用用户的搜索关键词进行递归搜索。重载按钮已被移至 “<ruby>查看<rt>View</rt></ruby>” 菜单。另一个新项目,“<ruby>最近<rt>Recent</rt></ruby>”,已被添加到左边的导航栏。同时,元数据被组织得更好了(从逗号分隔换成竖线分隔),一个新的上下文菜单项允许用户选择他们想要的选项。
|
||||
|
||||
Thunar 的主菜单也发生了重大变化。引入了一个新的 “<ruby>书签<rt>Bookmarks</rt></ruby>” 菜单,允许用户将当前文件夹作为快捷方式添加到侧边栏中。“<ruby>编辑<rt>Edit</rt></ruby>”菜单现在包括 “<ruby>撤销<rt>Undo</rt></ruby>” 和 “<ruby>重做<rt>Redo</rt></ruby>” 选项,而 “<ruby>前往<rt>Go</rt></ruby>” 菜单则有 “最近”和 “<ruby>按文件搜索<rt>Search for the file</rt></ruby>”选项。
|
||||
|
||||
![Thunar 带有分割视图和图像预览][6]
|
||||
|
||||
Thunar 还首次通过 “<ruby>视图<rt>View</rt></ruby>” 菜单项增加了分割视图,使用户能够在视图面板中拖放项目。另外,为了组织你的文件夹以加快工作流程,Thunar 还为你的文件夹及其名称引入了背景颜色。
|
||||
|
||||
![带有文件夹高亮选项的 Thunar][7]
|
||||
|
||||
除了 Xfce 4.18 的功能外,Xubuntu 23.04 还为窗口管理器和桌面的提供了更多的错误修复和性能改进。这些改进是在底层进行的;用户可以期待一个更精巧的 Xfce 桌面体验。
|
||||
|
||||
虽然 Xfce 桌面核心和本地应用程序的 Wayland 迁移工作已经开始,但它仍然远远没有准备好。因此,这个 Xubuntu 23.04 可能是未来 Wayland 工作的基础,希望可以出现在下一个 Xubuntu LTS 之前。虽然,考虑到 Xfce 团队的规模和其他方面,这不太有信心。
|
||||
|
||||
#### 最小化 ISO
|
||||
|
||||
正如我之前所报道的,Xubuntu 23.04 也引入了一个最小化的 ISO 镜像,其中只有基本的 Xfce 桌面组件,没有任何额外的预装软件。你可以试试这个最小化的 ISO,为你的工作流程建立你自己的桌面设置。
|
||||
|
||||
最小化的 ISO 大小目前为 1.9GB,团队正在努力在未来的版本中进一步减少它。
|
||||
|
||||
你可以在 [这篇文章中][8] 阅读更多关于 Xubuntu 最小化 ISO 的信息。
|
||||
|
||||
![Xubuntu 最小化和标准安装比较][9]
|
||||
|
||||
#### Flathub 和 Snap
|
||||
|
||||
几周前,Canonical 宣布已决定从所有 Ubuntu 官方风味版中默认删除 Flatpak 支持。因此,在 Xubuntu 23.04 中,你将不会默认安装 Flatpak。
|
||||
|
||||
Ubuntu 自己的 Snap 将默认安装所有相关组件,以运行几个 Snap 应用程序,如 Firefox。
|
||||
|
||||
但是,在 Xubuntu 中设置 Flatpak 和 Flathub 非常容易,[只需要两个命令][10]。
|
||||
|
||||
#### 其他变化和总结
|
||||
|
||||
在核心方面,Xubuntu 23.04 基于 [Linux 内核 6.2][11] 主线版本,它带来了对领先制造商的最新 CPU/GPU 产品的支持。此外,这个内核版本还引入了内存优化、安全修复和许多附件支持。
|
||||
|
||||
应用程序栈和 GNOME 组件的更新如下:
|
||||
|
||||
- Firefox 111.0(Snap)
|
||||
- Thunderbird 102.9
|
||||
- Thunar 4.18.4
|
||||
- Parole media player 4.18
|
||||
- LibreOffice 7.5
|
||||
- GNOME Software 44.0
|
||||
- Catfish file search 4.16.4
|
||||
- Transmission 3.0
|
||||
|
||||
![GNOME 软件应用 44 在 Xubuntu 23.04 中][12]
|
||||
|
||||
在核心部分,Python 3.11 现在可以在 Xubuntu 23.04 中开箱即用。你不需要再单独 [安装 Python 3.11][13] 了。值得一提的是,Python 3.12版本将在今年发布,目前正在进行多个 RC 测试。下面是这个版本中核心模块的总结:
|
||||
|
||||
- Python 3.11
|
||||
- GCC 13
|
||||
- GlibC 2.37
|
||||
- Ruby 3.1
|
||||
- golang 1.2
|
||||
- LLVM 16
|
||||
|
||||
### 下载
|
||||
|
||||
你可以从下面的链接中下载 Xubuntu 23.04(测试版)。请记住,它仍然在进行测试。所以,请谨慎使用它。
|
||||
|
||||
> **[下载 Xubuntu 23.04 - Beta][14]**
|
||||
|
||||
如果你想要 Xubuntu 23.04 的最小化 ISO,你可以从下面的链接获得该文件。[了解更多关于 Xubuntu-mini][8]。
|
||||
|
||||
> **[下载 Xubuntu 23.04 (mini-ISO) - Beta][14]**
|
||||
|
||||
### 总结
|
||||
|
||||
总之,Xubuntu 23.04 是一个重要的版本,具有 Xfce 4.18 桌面环境的若干改进和功能。由于专注于提高用户体验,Xubuntu 用户可以享受到最新的 Linux 内核、改进后的 Thunar 文件管理器以及其他一些调整和变化。
|
||||
|
||||
这将是 Xubuntu 对每个人来说最好的版本之一。
|
||||
|
||||
(题图由 MJ 生成:https://s.mj.run/0robf_nipRw Lunar Lobster hyper detailed, intricate detail, beautiful lighting, Illustration --q 2 --ar 16:9 --v 5)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://www.debugpoint.com/xubuntu-23-04/
|
||||
|
||||
作者:[Arindam][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[wxy](https://github.com/wxy)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.debugpoint.com/author/admin1/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://www.debugpoint.com/ubuntu-23-04-features/
|
||||
[2]: https://www.debugpoint.com/wp-content/uploads/2023/04/Xubuntu-23.04-Desktop.jpg
|
||||
[3]: https://www.debugpoint.com/xfce-4-18-features/
|
||||
[4]: https://www.debugpoint.com/wp-content/uploads/2022/11/Panel-preferences-in-Xfce-4.18.jpg
|
||||
[5]: https://debugpointnews.com/xfce-gsoc-2022/
|
||||
[6]: https://www.debugpoint.com/wp-content/uploads/2023/04/Thunar-with-split-view-and-image-preview.jpg
|
||||
[7]: https://www.debugpoint.com/wp-content/uploads/2023/04/Thunar-with-folder-highlight-option.jpg
|
||||
[8]: https://www.debugpoint.com/xubuntu-minimal/
|
||||
[9]: https://www.debugpoint.com/wp-content/uploads/2023/03/Xubuntu-minimal-and-standard-install-comparison.jpg
|
||||
[10]: https://www.debugpoint.com/how-to-install-flatpak-apps-ubuntu-linux/
|
||||
[11]: https://www.debugpoint.com/linux-kernel-6-2/
|
||||
[12]: https://www.debugpoint.com/wp-content/uploads/2023/04/GNOME-Software-44-in-Xubuntu-23.04.jpg
|
||||
[13]: https://www.debugpoint.com/install-python-3-11-ubuntu/
|
||||
[14]: https://cdimage.ubuntu.com/xubuntu/releases/lunar/beta/
|
||||
[15]: https://www.xfce-look.org/p/1953253
|
||||
[0]: https://img.linux.net.cn/data/attachment/album/202304/09/164211inurec5cc59cqtmc.jpg
|
@ -0,0 +1,52 @@
|
||||
[#]: subject: "Linux Mint Team Announced “Styles” for Cinnamon Desktop"
|
||||
[#]: via: "https://debugpointnews.com/cinnamon-styles-announcement/"
|
||||
[#]: author: "arindam https://debugpointnews.com/author/dpicubegmail-com/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Linux Mint Team Announced “Styles” for Cinnamon Desktop
|
||||
======
|
||||
|
||||
**The Linux Mint team has introduced “styles” in Cinnamon desktop for the upcoming release, Linux Mint 21.2, allowing for easier customization and a visually appealing interface.**
|
||||
|
||||
In their monthly update post, the Linux Mint team gave a sneak peek of what’s in store for the upcoming release, Linux Mint 21.2. One of the exciting new features that caught the eye was the introduction of “styles” in the Cinnamon desktop.
|
||||
|
||||
The next iteration of Cinnamon will present a novel concept known as “styles”. Styles come in three modes: mixed, dark, and light, and each of these modes can have colour “variants”. A variant is a combination of themes that blend together. The goal of styles, modes, and variants is to make it easier to switch to a beautiful-looking interface and quickly browse through available options. You won’t have to find matching elements because styles will do that for you, no matter how many individual themes you have installed.
|
||||
|
||||
In the style combo, you will see popular styles such as Adwaita, Mint-X, Mint-Y, among others. Just select one mode, and the colour variants will be displayed. You can switch between styles, modes, and colour variants with a few clicks of a button. However, if you prefer a specific combination of not proposed themes, you can click on “Advanced settings” and choose individual themes.
|
||||
|
||||
![Adwaita Cinnamon Style][1]
|
||||
|
||||
![Mint-Y Cinnamon Style][2]
|
||||
|
||||
![Mint-L Cinnamon Style][3]
|
||||
|
||||
The best part is that everything will work out of the box for everybody. The Linux Mint team wants Cinnamon styles to work well for everyone, including third-party theme artists and other distributions. Cinnamon styles are defined in JSON files in `/usr/share/cinnamon/styles.d/`. These files are read alphabetically, and styles can override one another if they have the same name. This approach lets distributions or theme artists define their styles while also using Cinnamon’s style definitions.
|
||||
|
||||
This entire feature should arrive as part of [Linux Mint 21.2 “Victoria” release][4], due on June 2023. If you want to contribute or want to develop your own theme for Mint, you can create a post in Mint forums.
|
||||
|
||||
Linux Mint users have long awaited this new feature and are sure to make the desktop environment more visually appealing and customizable. We can’t wait to see what the Linux Mint team has in store for us with the upcoming release!
|
||||
|
||||
Image credits: Linux Mint team, Via [announcement][5]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://debugpointnews.com/cinnamon-styles-announcement/
|
||||
|
||||
作者:[arindam][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://debugpointnews.com/author/dpicubegmail-com/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://debugpointnews.com/wp-content/uploads/2023/04/Adwaita-Cinnamon-Style.jpg
|
||||
[2]: https://debugpointnews.com/wp-content/uploads/2023/04/Mint-Y-Cinnamon-Style.jpg
|
||||
[3]: https://debugpointnews.com/wp-content/uploads/2023/04/Mint-L-Cinnamon-Style.jpg
|
||||
[4]: https://debugpointnews.com/linux-mint-21-2-announcement/
|
||||
[5]: https://blog.linuxmint.com/?p=4486
|
@ -0,0 +1,93 @@
|
||||
[#]: subject: "Color Variants & Styles Are Coming to Linux Mint 21.2"
|
||||
[#]: via: "https://news.itsfoss.com/color-styles-linux-mint/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Color Variants & Styles Are Coming to Linux Mint 21.2
|
||||
======
|
||||
|
||||
New visual elements and options for Linux Mint Cinnamon. What do you think?
|
||||
|
||||
![linux mint style][1]
|
||||
|
||||
![][2]
|
||||
|
||||
Recently, Linux Mint has been focusing on its look and feel more than usual.
|
||||
|
||||
With [Linux Mint 21.1][3], you get a new default theme and several subtle visual refinements.
|
||||
|
||||
And it looks like more such changes are in progress for the upcoming Linux Mint 21.2. As usual, a new monthly blog post highlighted some progress planned for the next release.
|
||||
|
||||
The highlight for me is the new concept, "**Styles,**" coming to the **Cinnamon desktop**.
|
||||
|
||||
### Cinnamon Upgrade With Linux Mint 21.2
|
||||
|
||||
Adding Styles to Cinnamon results in a simplified version of theme tweaks.
|
||||
|
||||
With the theme controls on Cinnamon, you must choose the mouse pointer, icon theme, and desktop theme separately.
|
||||
|
||||
![linux mint theme selection][4]
|
||||
|
||||
There are a lot of themes to select from. So, with the "Styles" approach, the tweaks get simplified to two things:
|
||||
|
||||
![linux mint style selection][5]
|
||||
|
||||
- **Style**
|
||||
- **Appearance**
|
||||
|
||||
The Style preset will feature options like Adwaita, Mint-X, Mint-Y, etc (the same options you find with the current theme selection).
|
||||
|
||||
![styles in linux mint][6]
|
||||
|
||||
For the appearance, you will choose the theme mode as dark/light or mixed as per your preferences.
|
||||
|
||||
The mixed mode will have both dark/light modes of apps for contrast, and the other modes are self-explanatory.
|
||||
|
||||
Once you have set these two options, you can find new color variants, combining themes. You can also play around with it to see what color combination works best for your style.
|
||||
|
||||
![linux mint yaru theme][7]
|
||||
|
||||
You can always find the current way of setting things under "**Advance settings**".
|
||||
|
||||
In addition, as shown in the screenshot above, you will find new color combinations available to add variety, even if the theme sounds similar.
|
||||
|
||||
Other changes expected with Linux Mint 21.2 include:
|
||||
|
||||
![][8]
|
||||
|
||||
- **Dropping the folder stripes**
|
||||
- **Removing monochrome icons and dark theme icons to replace them with symbolic icons to ensure compatibility and uniform contrast with all themes**
|
||||
|
||||
Sure, these simplifications of options for the end-user may not be massive overhauls but meaningful changes to improve the Cinnamon desktop experience overall.
|
||||
|
||||
Of course, it could become one of the [reasons you choose Cinnamon][9].
|
||||
|
||||
Not just limited to Linux Mint, these improvements will also help elevate the experience with any other distributions offering a Cinnamon desktop edition. You can head to Linux Mint's [official blog][10] to explore more about it.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/color-styles-linux-mint/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://news.itsfoss.com/content/images/size/w1304/2023/04/mint-21-2-color-styles.png
|
||||
[2]: https://news.itsfoss.com/content/images/2023/03/linux-mega-packt.webp
|
||||
[3]: https://news.itsfoss.com/linux-mint-21-1-release/
|
||||
[4]: https://news.itsfoss.com/content/images/2023/04/linux-mint-theme-current.jpg
|
||||
[5]: https://news.itsfoss.com/content/images/2023/04/adwaita.png
|
||||
[6]: https://news.itsfoss.com/content/images/2023/04/mint-y-styles.png
|
||||
[7]: https://news.itsfoss.com/content/images/2023/04/yaru.png
|
||||
[8]: https://news.itsfoss.com/content/images/2023/04/nemo.png
|
||||
[9]: https://itsfoss.com/why-cinnamon/?ref=news.itsfoss.com
|
||||
[10]: https://blog.linuxmint.com/?ref=news.itsfoss.com
|
@ -0,0 +1,117 @@
|
||||
[#]: subject: "TUXEDO Stellaris 16 (Gen5) is The Ultimate Linux Laptop You Can Find Now"
|
||||
[#]: via: "https://news.itsfoss.com/tuxedo-stellaris-16-gen-5/"
|
||||
[#]: author: "Sourav Rudra https://news.itsfoss.com/author/sourav/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
TUXEDO Stellaris 16 (Gen5) is The Ultimate Linux Laptop You Can Find Now
|
||||
======
|
||||
|
||||
The laptop packs in a punch with specs
|
||||
like RTX 4090 and i9 processor! Don't you think?
|
||||
|
||||
![tuxedo stellar][1]
|
||||
|
||||
![][2]
|
||||
|
||||
TUXEDO Computers is a well-known brand in the Linux space that provide customizable Linux notebooks and Desktop PCs at various price/performance points.
|
||||
|
||||
Not to forget, it is one of the trusted places to [buy Linux computers][3].
|
||||
|
||||
With a recent announcement, they have launched the **next evolution of their Stellaris 16-inch laptop.**
|
||||
|
||||
I must say that this can be a proper challenger to Framework's recently announced high-performance 16-inch Laptop.
|
||||
|
||||
Let's take a look at it.
|
||||
|
||||
### TUXEDO Stellaris 16 Gen 5: Overview ⭐
|
||||
|
||||
![a photo of the tuxedo stellaris 16 - gen5 laptop][4]
|
||||
|
||||
The major highlight of this laptop is that it features Nvidia's latest and greatest [**RTX40 series**][5] of mobile GPUs that offer some great graphics performance and features.
|
||||
|
||||
Paired with Intel's top-of-the-line processor, the **[i9 13900HX][6]**, with its 24-cores that can turbo up to a **blazing fast 5.40 GHz** at a whopping **157 W TDP** (Turbo), it is a compelling package.
|
||||
|
||||
Though keep in mind; that for running the laptop at its full potential, TUXEDO recommends using **their external water cooling solution**, [TUXEDO Aquaris][7], which can be attached magnetically to the back of the laptop.
|
||||
|
||||
> 📋 You will have to pay extra for this when ordering the laptop.
|
||||
|
||||
The processor can run at a base TDP of **55 W** with a 3.90 GHz clock speed when it is not running at full blast.
|
||||
|
||||
That's still a decent performance figure for such a thin laptop! 😮
|
||||
|
||||
Some other key highlights of the Stellaris 16 – Gen5 laptop are as follows:
|
||||
|
||||
- **The chassis is made up of a combination of Aluminum and Plastics.**
|
||||
- **A 240 Hz 16-inch IPS display with Nvidia G-SYNC support.**
|
||||
- **GPU options up to an Nvidia RTX 4090.**
|
||||
- **Up to 64 GB DDR5, 5600 MHz RAM (2x 32 GB).**
|
||||
- **A 99 Wh Battery that allows for runtimes of up to 10 hours (idle), and around 6–7 hours under typical loads.**
|
||||
|
||||
### ⚡ TUXEDO Stellaris 16: What Makes it a Powerhouse?
|
||||
|
||||
The high-end hardware aboard the Stellaris 16 – Gen5 laptop won't only appeal to gamers but also to a wide variety of other users such as content creators, AI/ML engineers, UI/UX artists, and more.
|
||||
|
||||
**So, what makes it such a complete package?**
|
||||
|
||||
Well, it is the freedom of choosing from various possible setups.
|
||||
|
||||
For starters, you get to pick from a relatively calmer GPU in the form of an **RTX 4060**, all the way to the **insane RTX 4090,** with the **RTX 4070** and **RTX 4080** filling in the gaps.
|
||||
|
||||
![tuxedo stellaris laptop][8]
|
||||
|
||||
Then there are the keyboard options that let you decide between their newly added [Cherry MX Ultra-Low Profile][9] clicky switches for a tactile and audible feel during typing or the usual silent membrane switches.
|
||||
|
||||
You can also pick from an extensive **list of keyboard layouts** that include English, German, Spanish, Hungarian, and more with the backlit TUX super-key.
|
||||
|
||||
The RAM offerings are no less; you can decide between two performance tiers. One is a 'Performance' tier that offers **DDR5 RAM** running at a swift **4800 MHZ** and a 'High Performance' tier that offers DDR5 RAM running at an eye-watering **5600 MHz**.
|
||||
|
||||
These tiers offer a maximum of 64 GB RAM, mixing sticks from **SK Hynix**, **Samsung,** and **Micron**.
|
||||
|
||||
As for storage, two M.2 2280 SSD slots run on PCIe 4.0 x4 with various Samsung SSDs.
|
||||
|
||||
The lineup starts with a **Samsung 970 EVO Plus**, with the **Samsung 980** in the middle and the blazing-fast **Samsung 980 Pro** being the range-topper.
|
||||
|
||||
> 📋 A maximum of 4 TB of storage is possible with both the M.2 slots occupied.
|
||||
|
||||
Besides that, the Stellaris 16 – Gen5 features **Wi-Fi 6E** with **Bluetooth 5.3** and comes with the **[TUXEDO OS][10] pre-installed** unless you choose a different one at checkout.
|
||||
|
||||
The OS offerings include the likes of **Ubuntu 22.04 LTS**, **Kubuntu 22.04 LTS**, **Ubuntu Budgie 22.04 LTS,** and **Windows 11 Home/Pro**.
|
||||
|
||||
### 💸 Availability and Pricing
|
||||
|
||||
The TUXEDO Stellaris 16 – Gen5 is **available for pre-order**, with **deliveries starting at the end of April**.
|
||||
|
||||
Prices start at **1763,87 EUR for the base config** with the i9 processor, an RTX 4060, 16 GB of RAM (2x 8 GB) running at 5600MHZ, a 500 GB Samsung 980 SSD, and TUXEDO OS.
|
||||
|
||||
[Pre-Order][11]
|
||||
|
||||
Head over to the [official store listing][11], and start configuring as per your requirements.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/tuxedo-stellaris-16-gen-5/
|
||||
|
||||
作者:[Sourav Rudra][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/sourav/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://news.itsfoss.com/content/images/size/w1304/2023/04/tuxedo-stellaris-gen-5.png
|
||||
[2]: https://news.itsfoss.com/content/images/2023/03/linux-mega-packt.webp
|
||||
[3]: https://itsfoss.com/get-linux-laptops/?ref=news.itsfoss.com
|
||||
[4]: https://news.itsfoss.com/content/images/2023/04/TUXEDO_Stellaris_16-Gen5.jpg
|
||||
[5]: https://www.nvidia.com/en-us/geforce/laptops/?ref=news.itsfoss.com
|
||||
[6]: https://ark.intel.com/content/www/us/en/ark/products/232171/intel-core-i913900hx-processor-36m-cache-up-to-5-40-ghz.html?ref=news.itsfoss.com
|
||||
[7]: https://www.tuxedocomputers.com/en/Linux-Hardware/Accessories/Further-accessories/TUXEDO-Aquaris--External-Water-Cooling-Device_1.tuxedo?ref=news.itsfoss.com
|
||||
[8]: https://news.itsfoss.com/content/images/2023/04/stellaris16-gen5_back.jpg
|
||||
[9]: https://www.cherrymx.de/en/cherry-mx/mx-ultra-low-profile/mx-ulp-click.html?ref=news.itsfoss.com
|
||||
[10]: https://www.tuxedocomputers.com/os?ref=news.itsfoss.com
|
||||
[11]: https://www.tuxedocomputers.com/en/TUXEDO-Stellaris-16-Gen5.tuxedo?ref=news.itsfoss.com
|
@ -0,0 +1,86 @@
|
||||
[#]: subject: "Open source community analysis with actionable insights"
|
||||
[#]: via: "https://opensource.com/article/23/4/open-source-community-analysis-actionable-insights"
|
||||
[#]: author: "Cali Dolfi https://opensource.com/users/cdolfi"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Open source community analysis with actionable insights
|
||||
======
|
||||
|
||||
Organizations are increasingly adopting open source software development models and open source aspects of organizational culture. As a result, interest in how open source communities succeed is reaching an all-time high.
|
||||
|
||||
Until recent years, measuring the success of open source communities was haphazard and anecdotal. Ask someone what makes one community more successful than another, and you will likely get observations such as, "The software is great, so the community is too," or "The people in this community just mesh well." The problem with these evaluations is not that they are necessarily wrong, but that they don't provide information that others can use to reproduce successful results. What works for one community is not necessarily going to work for another.
|
||||
|
||||
Research universities, businesses, and other organizations interested in determining what makes open source projects successful have begun to collaborate on finding ways to measure aspects of community in a qualitative and data-driven way. One of the more prominent efforts is [CHAOSS][1], a Linux Foundation project focused on creating metrics, metrics models, and software to better understand open source community health on a global scale. Unhealthy projects hurt both their communities and the organizations relying on those projects, so identifying measures of robustness isn't just an interesting project. It's critical to the open source ecosystem.
|
||||
|
||||
CHAOSS is a great tool for looking at a pressing set of questions. First, how should [community health][2] be defined? Second, as metrics begin to take shape, how can we transition from reacting to one-off requests for data-based information about a given community to creating an entire process pipeline, literally and theoretically, for this work? The development of [Project Aspen][3] is the culmination of this pipeline, which will ultimately bring community data analysis to everyone.
|
||||
|
||||
### Collecting community data
|
||||
|
||||
In 2017, Harish Pillay created Prospector with the aim of presenting information from core data sources in a graphical dashboard. This resonated with [CHAOSS][1], which had a goal to better understand the health of open source communities. Prospector was donated to CHAOSS in 2017. Project Aspen builds upon that work.
|
||||
|
||||
Aspen is backed by a database generated from the [Augur Project][4], a CHAOSS-based project that collects, organizes, and validates the completeness of open source software trace data. With this database, we can store all types of data points around the Git-based repositories from which we collect data, such as pull requests, reviews, and contributors. The data is already collected and cleaned, which, from a data science perspective, is where the most significant time drains occur. The continued data collection allows us to act agilely when questions arise. Over time, we will grow our pipeline to collect data from many other avenues in addition to Git-based repositories, such as Stack Overflow and Reddit.
|
||||
|
||||
As Augur regularly collects data on our selected repositories, the data is updated within a week and cleaned. With all the data collection and most preprocessing already completed, we are much better equipped to answer the analysis questions we receive and generate our own questions too. No matter where the questions come from, the same analysis process is necessary.
|
||||
|
||||
For every visualization or analysis, community leaders need to consider these questions:
|
||||
|
||||
- What perspective are you looking to gain or give?
|
||||
- What question can you directly answer from the data available to you?
|
||||
- What assumptions am I making, and what biases may I hold?
|
||||
- Who can I work with to get feedback and a different perspective?
|
||||
|
||||
Everyone's individual experiences and expertise impact the lens through which they look at a problem. Some people have experience in code review, while others' expertise lies in community management. How can we start comparing community aspects like apples to apples instead of oranges? Quantifying what people in different roles in open source are looking at when examining a project community can address this problem.
|
||||
|
||||
Community metrics empower all members to communicate in a common domain and share their unique expertise. Different perspectives lead to further insights, and Project Aspen uses data to make those insights more accessible to the entire community through data visualizations.
|
||||
|
||||
### Assumptions and analysis
|
||||
|
||||
Analysis is a tool for narrative building, not an oracle. Data analysis can help take the ambiguity and bias out of inferences we make, but interpreting data is not simple. A bar chart showing an increase in commits over time is not, by itself, a positive indicator of community health. Nor is a stable or decreasing number always a negative sign. What any chart gives you is more information and areas to explore.
|
||||
|
||||
For instance, you could build from a commits-over-time visualization, creating a graph that plots the "depth" of a commit, perhaps defined as the number of line changes. Or you could dive into the specific work of your community to see what these trends actually represent.
|
||||
|
||||
Comparing an issues-over-time graph (**Figure 1**) to an issues staleness graph (**Figure 2**) is a great illustration of why perspective matters. These visualizations reflect the same data but reveal completely different insights. From the issue staleness graph, we can see not only how many issues are open, but how many have been open for various time intervals.
|
||||
|
||||
This figure shows that over many months, there's relative consistency in how many issues are opened and closed:
|
||||
|
||||
![A graph showing relative consistency in how many issues are opened and closed.][5]
|
||||
|
||||
On the other hand, this figure highlights the growing number of issues that have been open for over 30 days:
|
||||
|
||||
![A graph showing issues over the past 30 days.][6]
|
||||
|
||||
The same data populates each graph, but a fuller picture can only come from seeing both. By adding the perspective of the growth in issue staleness, communities can clearly see that there is a growing backlog of issues and take steps to understand what it means for their community. At that point, they will be well-equipped to devise a strategy and prioritize actions based on both good data and thoughtful analysis.
|
||||
|
||||
### Using data wisely
|
||||
|
||||
Including multiple points of view also provides much-needed insight and helps guard against false positives and gamification. Economists have a saying: "When a measure becomes a target, it ceases to be a good measure." In other words, measures used to reward performance create an incentive to manipulate measurement. As people learn which measures bring attention, money, or power, open source communities run the risk of encouraging actions taken just to play the system. Using multiple perspectives to define success will keep your metrics meaningful, so they have genuine value in maintaining your community.
|
||||
|
||||
To that end, Project Aspen is an exciting tool for building your own knowledge and making better decisions about communities. Whether you want to understand where your community is most vulnerable or the seasonality of activity within the community, having quality data to inform your analysis is essential. To see some of the work being done around community data analysis, please check out our [Git repositories][3] or the demo [8Knot][7] app instance.
|
||||
|
||||
_This article was originally published with [Red Hat Research Quarterly][8] and has been republished with the author's permission._
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/open-source-community-analysis-actionable-insights
|
||||
|
||||
作者:[Cali Dolfi][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/cdolfi
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://chaoss.community/
|
||||
[2]: https://opensource.com/article/22/11/community-metrics
|
||||
[3]: https://github.com/oss-aspen
|
||||
[4]: https://github.com/chaoss/augur
|
||||
[5]: https://opensource.com/sites/default/files/2023-03/100000010000046C00000235638F4D10A6C6F100.webp
|
||||
[6]: https://opensource.com/sites/default/files/2023-03/100000010000046C0000025A21BB9C28E7B4B93C.webp
|
||||
[7]: https://eightknot.osci.io/
|
||||
[8]: https://research.redhat.com/blog/article/measuring-open-source-success-developing-analysis-for-actionable-insights/?intcmp=7013a000002qLH8AAM
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://opensource.com/article/21/12/kdenlive-linux-creative-app"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "yjacks"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
@ -1,110 +0,0 @@
|
||||
[#]: subject: "Open source mind mapping with Draw.io"
|
||||
[#]: via: "https://opensource.com/article/21/12/open-source-mind-mapping-drawio"
|
||||
[#]: author: "Seth Kenlon https://opensource.com/users/seth"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "FYJNEVERFOLLOWS "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Open source mind mapping with Draw.io
|
||||
======
|
||||
Next time you need to brainstorm, organize ideas, or plan a project,
|
||||
start with Draw.io.
|
||||
![Looking at a map for career journey][1]
|
||||
|
||||
There's something special about maps. I remember opening the front book cover of JRR Tolkien's _The Hobbit_ when I was younger, staring at the hand-drawn map of Middle Earth, and feeling the wealth of possibility contained in the simple drawing. Aside from their obvious purpose of actually describing where things are in relation to other things, I think maps do a great job of expressing potential. You could step outside and take the road this way or that way, and if you do, just think of all the new and exciting things you'll be able to see.
|
||||
|
||||
Maps don't have to be literal to be valuable and full of possibility, though. Some maps describe a thought process, plan, algorithm, or even random ideas desperately trying to fit together in a potential work of art. Call them "mind maps" or "flowcharts" or "idea boards." They're easy to make with the open source [Draw.io][2] application.
|
||||
|
||||
### Install Draw.io
|
||||
|
||||
Draw.io is designed as an open source online app, so you can either use it as an online application, download the [desktop version][3], or [clone the Git repository][4] and host it on your own server.
|
||||
|
||||
### Mapping with Draw.io
|
||||
|
||||
When you first start Draw.io, you need to choose where you want to save your data. If you're hosting Draw.io yourself, your choices depend on which API keys you have access to. You can choose from several online storage services for the online public instance, depending on what you've got an account for. If you don't want to store your data on somebody else's server, you can also choose to save your work on a local drive. If you're unsure yet, you can click **Decide later** to continue into the app without choosing anything.
|
||||
|
||||
The Draw.io interface has a big workspace in the center, the main toolbar on the left, a toolbar along the top, and a properties panel on the right.
|
||||
|
||||
![Draw.io interface][5]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][6])
|
||||
|
||||
The workflow is simple:
|
||||
|
||||
1. Select a shape from the left toolbar.
|
||||
2. Edit the shape in the workspace.
|
||||
3. Add another shape, and connect them.
|
||||
|
||||
|
||||
|
||||
Repeat that process, and you've got a map.
|
||||
|
||||
![Draw.io example][7]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][6])
|
||||
|
||||
### Project planning
|
||||
|
||||
When you first take on a big task, you often have a pretty clear idea of your desired outcome. Say you want to start a community project to paint a mural. Your desired outcome is a mural. It's pretty easy to define, and you can more or less picture the results in your mind's eye.
|
||||
|
||||
Once you start moving toward your goal, however, you have to start figuring out the details. Where should the mural be painted? How do you get permission to paint on a public wall, anyway? What about paint? Is there a special kind of paint you ought to use? Will you apply the paint with brushes or airbrushes? What kind of specialized equipment do you need for painting? How many people and hours will it take to paint a mural? What about support services for the painters while they work? And what's the painting going to be about, anyway? A single idea can very quickly become overwhelming the closer you get to making it happen.
|
||||
|
||||
This doesn't just apply to painting murals, producing a play, or making a movie. It applies to nearly any non-trivial endeavor. And it's exactly what an application like Draw.io can help map out.
|
||||
|
||||
Here's how you can use Draw.io to create a project flowchart:
|
||||
|
||||
1. Start with a brainstorming session. No thoughts are too trivial or big. Make a box for every idea, and double-click the box in the Draw.io workspace to enter text.
|
||||
2. Once you have all the ideas you can possibly think of on your workspace, drag and drop them into related groups. The goal is to create little clouds, or clusters, of tasks that more or less go together because they're part of the same process.
|
||||
3. Once you've identified the clusters of related tasks, give those tasks a name. For instance, if you're painting a mural, then the tasks might be _approval_, _design_, _purchase_, _paint_, reflecting that you need to get permission from your local government first, then design the mural, then purchase the supplies, and finally paint the mural. Each task has component parts, but broadly you've now determined the workflow for your project.
|
||||
4. Connect the major tasks with arrows. Not all processes are entirely linear. For instance, after you've obtained permission from your city council, you might have to come back to them for final approval once you've designed what you intend to paint. That's normal. It's a loop, there's some back and forth, but eventually, you break out of the loop to proceed to the next stage.
|
||||
5. Armed with your flowchart, work through each task until you've reached your ultimate goal.
|
||||
|
||||
|
||||
|
||||
### Mind mapping
|
||||
|
||||
Mind maps tend to be less about progress and more about maintaining a certain state or putting many ideas into perspective. For instance, suppose you've decided to reduce the amount of waste in your life. You have some ideas about what you can do, but you want to organize and preserve your ideas, so you don't forget them.
|
||||
|
||||
Here's how you can use Draw.io to create a mind map:
|
||||
|
||||
1. Start with a brainstorming session. No thoughts are too trivial or big. Make a box for every idea, and double-click the box in the Draw.io workspace to enter text. You can also give boxes a background color by selecting the box and clicking a color swatch in the right properties panel.
|
||||
2. Arrange your ideas into groups or categories.
|
||||
3. Optionally, connect ideas with arrows that relate directly to one another.
|
||||
|
||||
|
||||
|
||||
![Draw.io waste reduction example][8]
|
||||
|
||||
(Seth Kenlon, [CC BY-SA 4.0][6])
|
||||
|
||||
### Saving your diagram
|
||||
|
||||
You can save your diagram as a PNG, JPG image, Draw.io XML, or plain XML file. If you save it as XML, you can open it again in Draw.io for further editing. An exported image is great for sharing with others.
|
||||
|
||||
### Use Draw.io
|
||||
|
||||
There are many great diagramming applications, but I don't make diagrams often, so having Draw.io available is convenient at a moment's notice. Its interface is simple and easy to use, and the results are clean and professional. Next time you need to brainstorm, organize ideas, or plan a project, start with Draw.io.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/12/open-source-mind-mapping-drawio
|
||||
|
||||
作者:[Seth Kenlon][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[FYJNEVERFOLLOWS](https://github.com/FYJNEVERFOLLOWS)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/career_journey_road_gps_path_map_520.png?itok=PpL6jJgY (Looking at a map for career journey)
|
||||
[2]: http://draw.io
|
||||
[3]: https://github.com/jgraph/drawio-desktop
|
||||
[4]: https://github.com/jgraph/drawio
|
||||
[5]: https://opensource.com/sites/default/files/uploads/draw-io-ui.png (Draw.io interface)
|
||||
[6]: https://creativecommons.org/licenses/by-sa/4.0/
|
||||
[7]: https://opensource.com/sites/default/files/uploads/draw-io-example.jpg (Draw.io example)
|
||||
[8]: https://opensource.com/sites/default/files/uploads/draw-io-export.jpg (Draw.io waste reduction example)
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://itsfoss.com/speek/"
|
||||
[#]: author: "Pratham Patel https://itsfoss.com/author/pratham/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "XiaotingHuang22"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
@ -87,7 +87,7 @@ via: https://itsfoss.com/speek/
|
||||
|
||||
作者:[Pratham Patel][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
译者:[XiaotingHuang22](https://github.com/XiaotingHuang22)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
@ -1,280 +0,0 @@
|
||||
[#]: subject: "Level up your HTML document with CSS"
|
||||
[#]: via: "https://opensource.com/article/22/8/css-html-project-documentation"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Level up your HTML document with CSS
|
||||
======
|
||||
Use CSS to bring style to your HTML project documentation.
|
||||
|
||||
When you write documentation, whether that's for an open source project or a technical writing project, you should have two goals: The document should be written well, and the document should be easy to read. The first is addressed by clear writing skills and technical editing. The second can be addressed with a few simple changes to an HTML document.
|
||||
|
||||
HyperText Markup Language, or HTML, is the backbone of the internet. Since the dawn of the "World Wide Web" in 1994, every web browser uses HTML to display documents and websites. And for almost as long, HTML has supported the *stylesheet*, a special addition to an HTML document that defines how the text should appear on the screen.
|
||||
|
||||
You can write project documentation in plain HTML, and that gets the job done. However, plain HTML styling may feel a little spartan. Instead, try adding a few simple styles to an HTML document to add a little pizzazz to documentation, and make your documents clearer and easier to read.
|
||||
|
||||
### Defining an HTML document
|
||||
|
||||
Let's start with a plain HTML document and explore how to add styles to it. An empty HTML document contains the <!DOCTYPE html> definition at the top, followed by an <html> block to define the document itself. Within the <html> element, you also need to include a document header that contains metadata about the document, such as its title. The contents of the document body go inside a <body> block within the parent <html> block.
|
||||
|
||||
You can define a blank page with this HTML code:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>This is a new document</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
In another article about [Writing project documentation in HTML][2], I updated a Readme file from an open source board game from plain text to an HTML document, using a few basic HTML tags like <h1> and <h2> for heading and subheadings, <p> for paragraphs, and <b> and <i> for bold and italic text. Let's pick up where we left off with that article:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple Senet</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Simple Senet</h1>
|
||||
<h2>How to Play</h2>
|
||||
|
||||
<p>The game will automatically "throw" the throwing sticks
|
||||
for you, and display the results in the lower-right corner
|
||||
of the screen.</p>
|
||||
|
||||
<p>If the "throw" is zero, then you lose your turn.</p>
|
||||
|
||||
<p>When it's your turn, the game will automatically select
|
||||
your first piece on the board. You may or may not be
|
||||
able to make a move with this piece, so select your piece
|
||||
to move, and hit <i>Space</i> (or <i>Enter</i>) to move
|
||||
it. You can select using several different methods:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>Up</i>/<i>down</i>/<i>left</i>/<i>right</i> to
|
||||
navigate to a specific square.</li>
|
||||
|
||||
<li>Plus (<b>+</b>) or minus (<b>-</b>) to navigate "left"
|
||||
and "right" on the board. Note that this will automatically
|
||||
follow the "backwards S" shape of the board.</li>
|
||||
|
||||
<li><em>Tab</em> to select your next piece on the
|
||||
board.</li>
|
||||
</ul>
|
||||
|
||||
<p>To quit the game at any time, press <b>Q</b> (uppercase
|
||||
Q) or hit <i>Esc</i>, and the game will prompt if you want
|
||||
to forfeit the game.</p>
|
||||
|
||||
<p>You win if you move all of your pieces off the board
|
||||
before your opponent. It takes a combination of luck and
|
||||
strategy!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
This HTML document demonstrates a few common block and inline elements used by technical writers who write with HTML. Block elements define a rectangle around text. Paragraphs and headings are examples of block elements, because they extend from the left to the right edges of the document. For example, <p> encloses an invisible rectangle around a paragraph. In contrast, inline elements follow the text where they are used. If you use <b> on some text within a paragraph, only the text surrounded by <b> and </b> becomes bold.
|
||||
|
||||
You can apply direct styling to this document to change the font, colors, and other text styles, but a more efficient way to modify the document's appearance is to apply a *stylesheet* to the document itself. You can do that in the <head> element, with other metadata. You can reference a file for the style sheet, but for this example, use a <style> block to define a style sheet within the document. Here's the <head> with an empty stylesheet:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple Senet</title>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Defining styles
|
||||
|
||||
Since you're just starting to learn about stylesheets, let's demonstrate a basic style: background color. I like to start with the background color because it helps to demonstrate block and inline elements. Let's apply a somewhat gaudy stylesheet that sets a *light blue* background color for all <p> paragraphs, and a *light green* background for the <ul> unordered list. Use a *yellow* background for any bold text, and a *pink* background for any italics text.
|
||||
|
||||
You define these using styles in the <style> block of our HTML document. The stylesheet uses a different markup than an HTML document. The style syntax looks like `element { style; style; style; ... }` and uses curly braces to group together several text styles into a single definition.
|
||||
|
||||
```
|
||||
<style>
|
||||
p { background-color: lightblue; }
|
||||
ul { background-color: lightgreen; }
|
||||
|
||||
b { background-color: yellow; }
|
||||
i { background-color: pink; }
|
||||
</style>
|
||||
```
|
||||
|
||||
Note that each style ends with a semicolon.
|
||||
|
||||
If you view this HTML document in a web browser, you can see how the <p> and <ul> block elements are filled in as rectangles, and the <b> and <i> inline elements highlight only the bold and italics text. This use of contrasting colors may not be pretty to look at, but I think you can see the block and inline elements:
|
||||
|
||||
![My eyes! But the colors do help us see block and inline elements.][3]
|
||||
|
||||
### Applying styles
|
||||
|
||||
You can use styles to make this Readme document easier to read. You're just starting to learn about styles, you'll stick to a few simple style elements:
|
||||
|
||||
* background-color to set the background color
|
||||
* color to set the text color
|
||||
* font-family to use a different text font
|
||||
* margin-top to add space above an element
|
||||
* margin-bottom to add space below an element
|
||||
* text-align to change how the text is displayed, such as to the left, to the right, or centered
|
||||
|
||||
Let's start over with your stylesheet and apply these new styles to your document. To begin, use a more pleasing font for your document. If your HTML document does not specify a font, the web browser picks one for you. Depending on how the browser is set up, this could be a *serif* font, like the font used in my screenshot, or a *sans-serif* font. Serif fonts have a small stroke added to each letter, which makes these fonts much easier to read in print. Sans-serif fonts lack this extra stroke, which makes text appear sharper on a computer display. Common serif fonts include Garamond or Times New Roman. Popular sans-serif fonts include Roboto and Arial.
|
||||
|
||||
For example, to set the document body font to Roboto, use this style:
|
||||
|
||||
```
|
||||
body { font-family: Roboto; }
|
||||
```
|
||||
|
||||
By setting a font, you assume the person viewing your document also has that font installed. Some fonts have become so common they are considered de facto "Web safe" fonts. These include sans-serif fonts like Arial and serif fonts such as Times New Roman. Roboto is a newer font and may not be available everywhere. So instead of listing just one font, web designers usually put one or more "backup" fonts. You can add these alternative fonts by separating them with a comma. For example, if the user doesn't have the Roboto font on their system, you can instead use Arial for the text body by using this style definition:
|
||||
|
||||
```
|
||||
body { font-family: Roboto, Arial; }
|
||||
```
|
||||
|
||||
All web browsers define a default serif and sans-serif font that you can reference with those names. Users can change which font they prefer to use for serif and sans-serif, so aren't likely to be the same for everyone, but using serif or sans-serif in a font list is usually a good idea. By adding that font, at least the user gets some approximation of how you want the HTML document to appear:
|
||||
|
||||
```
|
||||
body { font-family: Roboto, Arial, sans-serif; }
|
||||
```
|
||||
|
||||
If your font name is more than one word, you have to put quotes around it. HTML allows you to use either single quotes or double quotes here. Define a few serif fonts for the heading and subheading, including Times New Roman:
|
||||
|
||||
```
|
||||
h1 { font-family: "Times New Roman", Garamond, serif; }
|
||||
h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
```
|
||||
|
||||
Note that the h1 heading and h2 subheading use exactly the same font definition. If you want to avoid the extra typing, you can use a stylesheet shortcut to use the same style definition for both h1 and h2:
|
||||
|
||||
```
|
||||
h1, h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
```
|
||||
|
||||
When writing documentation, many technical writers prefer to center the main title on the page. You can use text-align on a block element, such as the h1 heading, to center just the title:
|
||||
|
||||
```
|
||||
h1 { text-align: center; }
|
||||
```
|
||||
|
||||
To help bold and italics text to stand out, put them in a slightly different color. For certain documents, I might use *dark blue* for bold text, and *dark green* for italics text. These are pretty close to black, but with just enough subtle difference that the color grabs the reader's attention.
|
||||
|
||||
```
|
||||
b { color: darkblue; }
|
||||
i { color: darkgreen; }
|
||||
```
|
||||
|
||||
Finally, I prefer to add extra spacing around my list elements, to make these easier to read. If each list item was only a few words, the extra space might not matter. But the middle item in my example text is quite long and wraps to a second line. The extra space helps the reader see each item in this list more clearly. You can use the margin style to add space above and below a block element:
|
||||
|
||||
```
|
||||
li { margin-top: 10px; margin-bottom: 10px; }
|
||||
```
|
||||
|
||||
This style defines a distance, which I've indicated here as 10px (ten *pixels*) above and below each list element. You can use several different measures for distance. Ten pixels is literally the space of ten pixels on your screen, whether that's a desktop monitor, a laptop display, or a phone or tablet screen.
|
||||
|
||||
Assuming you really just want to add an extra blank line between the list elements, you can also use em for my measurement. An *em* is an old typesetting term that is exactly the width of capital **M** if you refer to left and right spacing, or the height of a capital **M** for vertical spacing. So you can instead write the margin style using 1em:
|
||||
|
||||
```
|
||||
li { margin-top: 1em; margin-bottom: 1em; }
|
||||
```
|
||||
|
||||
The complete list of styles in your HTML document looks like this:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple Senet</title>
|
||||
<style>
|
||||
body { font-family: Roboto, Arial, sans-serif; }
|
||||
h1, h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
h1 { text-align: center; }
|
||||
b { color: darkblue; }
|
||||
i { color: darkgreen; }
|
||||
li { margin-top: 1em; margin-bottom: 1em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Simple Senet</h1>
|
||||
<h2>How to Play</h2>
|
||||
|
||||
<p>The game will automatically "throw" the throwing sticks
|
||||
for you, and display the results in the lower-right corner
|
||||
of the screen.</p>
|
||||
|
||||
<p>If the "throw" is zero, then you lose your turn.</p>
|
||||
|
||||
<p>When it's your turn, the game will automatically select
|
||||
your first piece on the board. You may or may not be
|
||||
able to make a move with this piece, so select your piece
|
||||
to move, and hit <i>Space</i> (or <i>Enter</i>) to move
|
||||
it. You can select using several different methods:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>Up</i>/<i>down</i>/<i>left</i>/<i>right</i> to
|
||||
navigate to a specific square.</li>
|
||||
|
||||
<li>Plus (<b>+</b>) or minus (<b>-</b>) to navigate "left"
|
||||
and "right" on the board. Note that this will automatically
|
||||
follow the "backwards S" shape of the board.</li>
|
||||
|
||||
<li><em>Tab</em> to select your next piece on the
|
||||
board.</li>
|
||||
</ul>
|
||||
|
||||
<p>To quit the game at any time, press <b>Q</b> (uppercase
|
||||
Q) or hit <i>Esc</i>, and the game will prompt if you want
|
||||
to forfeit the game.</p>
|
||||
|
||||
<p>You win if you move all of your pieces off the board
|
||||
before your opponent. It takes a combination of luck and
|
||||
strategy!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
When viewed on a web browser, you see your Readme document in a sans-serif font, with serif fonts for the heading and subheading. The page title is centered. The bold and italics text use a slightly different color that calls the reader's attention without being distracting. Finally, your list items have extra space around them, making each item easier to read.
|
||||
|
||||
![By adding a few styles, we've made this Readme much easier to read.][4]
|
||||
|
||||
This is a simple introduction to using styles in technical writing. Having mastered the basics, you might be interested in [Mozilla's HTML Guide][5]. This includes some great beginner's tutorials so you can learn how to create your own web pages.
|
||||
|
||||
For more information on how CSS styling works, I recommend [Mozilla's CSS Guide][6].
|
||||
|
||||
Image by: (Jim Hall, CC BY-SA 4.0)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/22/8/css-html-project-documentation
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://opensource.com/sites/default/files/lead-images/painting_computer_screen_art_design_creative.png
|
||||
[2]: https://opensource.com/article/22/8/writing-project-documentation-html
|
||||
[3]: https://opensource.com/sites/default/files/2022-08/style-html-1.png
|
||||
[4]: https://opensource.com/sites/default/files/2022-08/style-html-2.png
|
||||
[5]: https://developer.mozilla.org/en-US/docs/Web/HTML
|
||||
[6]: https://developer.mozilla.org/en-US/docs/Web/CSS
|
@ -24,16 +24,20 @@ I’ve heard a million times about the dangers of floating point arithmetic, lik
|
||||
But I find all of this a little abstract on its own, and I really wanted some
|
||||
specific examples of floating point bugs in real-world programs.
|
||||
|
||||
So I [asked on Mastodon][1] for
|
||||
examples of how floating point has gone wrong for them in real programs, and as
|
||||
always folks delivered! Here are a bunch of examples. I’ve also written some
|
||||
example programs for some of them to see exactly what happens. Here’s a table of contents:
|
||||
So I [asked on Mastodon][1] for examples of how floating point has gone wrong for them in real programs, and as always folks delivered! Here are a bunch of examples. I’ve also written some example programs for some of them to see exactly what happens. Here’s a table of contents:
|
||||
|
||||
[how does floating point work?][2][floating point isn’t “bad” or random][3][example 1: the odometer that stopped][4][example 2: tweet IDs in Javascript][5][example 3: a variance calculation gone wrong][6][example 4: different languages sometimes do the same floating point calculation differently][7][example 5: the deep space kraken][8][example 6: the inaccurate timestamp][9][example 7: splitting a page into columns][10][example 8: collision checking][11]
|
||||
- [how does floating point work?][2]
|
||||
- [floating point isn’t “bad” or random][3]
|
||||
- [example 1: the odometer that stopped][4]
|
||||
- [example 2: tweet IDs in Javascript][5]
|
||||
- [example 3: a variance calculation gone wrong][6]
|
||||
- [example 4: different languages sometimes do the same floating point calculation differently][7]
|
||||
- [example 5: the deep space kraken][8]
|
||||
- [example 6: the inaccurate timestamp][9]
|
||||
- [example 7: splitting a page into columns][10]
|
||||
- [example 8: collision checking][11]
|
||||
|
||||
None of these 8 examples talk about NaNs or +0/-0 or infinity values or
|
||||
subnormals, but it’s not because those things don’t cause problems – it’s just
|
||||
that I got tired of writing at some point :).
|
||||
None of these 8 examples talk about NaNs or +0/-0 or infinity values or subnormals, but it’s not because those things don’t cause problems – it’s just that I got tired of writing at some point :).
|
||||
|
||||
Also I’ve probably made some mistakes in this post.
|
||||
|
||||
@ -45,35 +49,21 @@ I’m not going to write a long explanation of how floating point works in this
|
||||
|
||||
#### floating point isn’t “bad” or random
|
||||
|
||||
I don’t want you to read this post and conclude that floating point is bad.
|
||||
It’s an amazing tool for doing numerical calculations. So many smart people
|
||||
have done so much work to make numerical calculations on computers efficient and
|
||||
accurate! Two points about how all of this isn’t floating point’s fault:
|
||||
I don’t want you to read this post and conclude that floating point is bad. It’s an amazing tool for doing numerical calculations. So many smart people have done so much work to make numerical calculations on computers efficient and accurate! Two points about how all of this isn’t floating point’s fault:
|
||||
|
||||
- Doing numerical computations on a computer inherently involves
|
||||
some approximation and rounding, especially if you want to do it
|
||||
efficiently. You can’t always store an arbitrary amount of precision for
|
||||
- Doing numerical computations on a computer inherently involves some approximation and rounding, especially if you want to do it efficiently. You can’t always store an arbitrary amount of precision for
|
||||
every single number you’re working with.
|
||||
- Floating point is standardized (IEEE 754), so operations like addition on
|
||||
floating point numbers are deterministic – my understanding is that 0.1 +
|
||||
0.2 will always give you the exact same result (0.30000000000000004), even
|
||||
across different architectures. It might not be the result you _expected_,
|
||||
but it’s actually very predictable.
|
||||
- Floating point is standardized (IEEE 754), so operations like addition on floating point numbers are deterministic – my understanding is that 0.1 + 0.2 will always give you the exact same result (0.30000000000000004), even across different architectures. It might not be the result you _expected_, but it’s actually very predictable.
|
||||
|
||||
My goal for this post is just to explain what kind of problems can come up with
|
||||
floating point numbers and why they happen so that you know when to be
|
||||
careful with them, and when they’re not appropriate.
|
||||
My goal for this post is just to explain what kind of problems can come up with floating point numbers and why they happen so that you know when to be careful with them, and when they’re not appropriate.
|
||||
|
||||
Now let’s get into the examples.
|
||||
|
||||
#### example 1: the odometer that stopped
|
||||
|
||||
One person said that they were working on an odometer that was continuously
|
||||
adding small amounts to a 32-bit float to measure distance travelled, and
|
||||
things went very wrong.
|
||||
One person said that they were working on an odometer that was continuously adding small amounts to a 32-bit float to measure distance travelled, and things went very wrong.
|
||||
|
||||
To make this concrete, let’s say that we’re adding numbers to the odometer 1cm
|
||||
at a time. What does it look like after 10,000 kilometers?
|
||||
To make this concrete, let’s say that we’re adding numbers to the odometer 1cm at a time. What does it look like after 10,000 kilometers?
|
||||
|
||||
Here’s a C program that simulates that:
|
||||
|
||||
@ -101,10 +91,7 @@ This is VERY bad – it’s not a small error, 262km is a LOT less than 10,000km
|
||||
|
||||
#### what went wrong: gaps between floating point numbers get big
|
||||
|
||||
The problem in this case is that, for 32-bit floats, 262144.0 + 0.01 = 262144.0.
|
||||
So it’s not just that the number is inaccurate, it’ll actually never increase
|
||||
at all! If we travelled another 10,000 kilometers, the odometer would still be
|
||||
stuck at 262144 meters (aka 262.144km).
|
||||
The problem in this case is that, for 32-bit floats, 262144.0 + 0.01 = 262144.0. So it’s not just that the number is inaccurate, it’ll actually never increase at all! If we travelled another 10,000 kilometers, the odometer would still be stuck at 262144 meters (aka 262.144km).
|
||||
|
||||
Why is this happening? Well, floating point numbers get farther apart as they get bigger. In this example, for 32-bit floats, here are 3 consecutive floating point numbers:
|
||||
|
||||
@ -116,13 +103,9 @@ I got those numbers by going to [https://float.exposed/0x48800000][13] and incre
|
||||
|
||||
So, there are no 32-bit floating point numbers between 262144.0 and 262144.03125. Why is that a problem?
|
||||
|
||||
The problem is that 262144.03125 is about 262144.0 + 0.03. So when we try to
|
||||
add 0.01 to 262144.0, it doesn’t make sense to round up to the next number. So
|
||||
the sum just stays at 262144.0.
|
||||
The problem is that 262144.03125 is about 262144.0 + 0.03. So when we try to add 0.01 to 262144.0, it doesn’t make sense to round up to the next number. So the sum just stays at 262144.0.
|
||||
|
||||
Also, it’s not a coincidence that 262144 is a power of 2 (it’s 2^18). The gaps
|
||||
been floating point numbers change after every power of 2, and at 2^18 the gap
|
||||
between 32-bit floats is 0.03125, increasing from 0.016ish.
|
||||
Also, it’s not a coincidence that 262144 is a power of 2 (it’s 2^18). The gaps been floating point numbers change after every power of 2, and at 2^18 the gap between 32-bit floats is 0.03125, increasing from 0.016ish.
|
||||
|
||||
#### one way to solve this: use a double
|
||||
|
||||
@ -133,41 +116,26 @@ Expected: 10000.000000 km
|
||||
Got: 9999.999825 km
|
||||
```
|
||||
|
||||
There are still some small inaccuracies here – we’re off about 17 centimeters.
|
||||
Whether this matters or not depends on the context: being slightly off could very
|
||||
well be disastrous if we were doing a precision space maneuver or something, but
|
||||
it’s probably fine for an odometer.
|
||||
There are still some small inaccuracies here – we’re off about 17 centimeters. Whether this matters or not depends on the context: being slightly off could very well be disastrous if we were doing a precision space maneuver or something, but it’s probably fine for an odometer.
|
||||
|
||||
Another way to improve this would be to increment the odometer in bigger chunks
|
||||
– instead of adding 1cm at a time, maybe we could update it less frequently,
|
||||
like every 50cm.
|
||||
Another way to improve this would be to increment the odometer in bigger chunks – instead of adding 1cm at a time, maybe we could update it less frequently, like every 50cm.
|
||||
|
||||
If we use a double **and** increment by 50cm instead of 1cm, we get the exact
|
||||
correct answer:
|
||||
If we use a double **and** increment by 50cm instead of 1cm, we get the exact correct answer:
|
||||
|
||||
```
|
||||
Expected: 10000.000000 km
|
||||
Got: 10000.000000 km
|
||||
```
|
||||
|
||||
A third way to solve this could be to use an **integer**: maybe we decide that
|
||||
the smallest unit we care about is 0.1mm, and then measure everything as
|
||||
integer multiples of 0.1mm. I have never built an odometer so I can’t say what
|
||||
the best approach is.
|
||||
A third way to solve this could be to use an **integer**: maybe we decide that the smallest unit we care about is 0.1mm, and then measure everything as integer multiples of 0.1mm. I have never built an odometer so I can’t say what the best approach is.
|
||||
|
||||
#### example 2: tweet IDs in Javascript
|
||||
|
||||
Javascript only has floating point numbers – it doesn’t have an integer type.
|
||||
The biggest integer you can represent in a 64-bit floating point number is
|
||||
2^53.
|
||||
Javascript only has floating point numbers – it doesn’t have an integer type. The biggest integer you can represent in a 64-bit floating point number is 2^53.
|
||||
|
||||
But tweet IDs are big numbers, bigger than 2^53. The Twitter API now returns
|
||||
them as both integers and strings, so that in Javascript you can just use the
|
||||
string ID (like “1612850010110005250”), but if you tried to use the integer
|
||||
version in JS, things would go very wrong.
|
||||
But tweet IDs are big numbers, bigger than 2^53. The Twitter API now returns them as both integers and strings, so that in Javascript you can just use the string ID (like “1612850010110005250”), but if you tried to use the integer version in JS, things would go very wrong.
|
||||
|
||||
You can check this yourself by taking a tweet ID and putting it in the
|
||||
Javascript console, like this:
|
||||
You can check this yourself by taking a tweet ID and putting it in the Javascript console, like this:
|
||||
|
||||
```
|
||||
>> 1612850010110005250
|
||||
@ -176,8 +144,7 @@ Javascript console, like this:
|
||||
|
||||
Notice that 1612850010110005200 is NOT the same number as 1612850010110005250!! It’s 50 less!
|
||||
|
||||
This particular issue doesn’t happen in Python (or any other language that I
|
||||
know of), because Python has integers. Here’s what happens if we enter the same number in a Python REPL:
|
||||
This particular issue doesn’t happen in Python (or any other language that I know of), because Python has integers. Here’s what happens if we enter the same number in a Python REPL:
|
||||
|
||||
```
|
||||
In [3]: 1612850010110005250
|
||||
@ -188,14 +155,9 @@ Same number, as you’d expect.
|
||||
|
||||
#### example 2.1: the corrupted JSON data
|
||||
|
||||
This is a small variant of the “tweet IDs in Javascript” issue, but even if
|
||||
you’re _not_ actually writing Javascript code, numbers in JSON are still sometimes
|
||||
treated as if they’re floats. This mostly makes sense to me because JSON has
|
||||
“Javascript” in the name, so it seems reasonable to decode the values the way
|
||||
Javascript would.
|
||||
This is a small variant of the “tweet IDs in Javascript” issue, but even if you’re _not_ actually writing Javascript code, numbers in JSON are still sometimes treated as if they’re floats. This mostly makes sense to me because JSON has “Javascript” in the name, so it seems reasonable to decode the values the way Javascript would.
|
||||
|
||||
For example, if we pass some JSON through `jq`, we see the exact same issue:
|
||||
the number 1612850010110005250 gets changed into 1612850010110005200.
|
||||
For example, if we pass some JSON through `jq`, we see the exact same issue: the number 1612850010110005250 gets changed into 1612850010110005200.
|
||||
|
||||
```
|
||||
$ echo '{"id": 1612850010110005250}' | jq '.'
|
||||
@ -206,19 +168,13 @@ $ echo '{"id": 1612850010110005250}' | jq '.'
|
||||
|
||||
But it’s not consistent across all JSON libraries Python’s `json` module will decode `1612850010110005250` as the correct integer.
|
||||
|
||||
Several people mentioned issues with sending floats in JSON, whether either
|
||||
they were trying to send a large integer (like a pointer address) in JSON and
|
||||
it got corrupted, or sending smaller floating point values back and forth
|
||||
repeatedly and the value slowly diverging over time.
|
||||
Several people mentioned issues with sending floats in JSON, whether either they were trying to send a large integer (like a pointer address) in JSON and it got corrupted, or sending smaller floating point values back and forth repeatedly and the value slowly diverging over time.
|
||||
|
||||
#### example 3: a variance calculation gone wrong
|
||||
|
||||
Let’s say you’re doing some statistics, and you want to calculate the variance
|
||||
of many numbers. Maybe more numbers than you can easily fit in memory, so you
|
||||
want to do it in a single pass.
|
||||
Let’s say you’re doing some statistics, and you want to calculate the variance of many numbers. Maybe more numbers than you can easily fit in memory, so you want to do it in a single pass.
|
||||
|
||||
There’s a simple (but bad!!!) algorithm you can use to calculate the variance in a single pass,
|
||||
from [this blog post][14]. Here’s some Python code:
|
||||
There’s a simple (but bad!!!) algorithm you can use to calculate the variance in a single pass, from [this blog post][14]. Here’s some Python code:
|
||||
|
||||
```
|
||||
def calculate_bad_variance(nums):
|
||||
@ -255,50 +211,27 @@ This is extremely bad: not only is the bad variance way off, it’s NEGATIVE! (t
|
||||
|
||||
#### what went wrong: catastrophic cancellation
|
||||
|
||||
What’s going here is similar to our odometer number problem: the
|
||||
`sum_of_squares` number gets extremely big (about 10^21 or 2^69), and at that point, the
|
||||
gap between consecutive floating point numbers is also very big – it’s 2**46.
|
||||
So we just lose all precision in our calculations.
|
||||
What’s going here is similar to our odometer number problem: the `sum_of_squares` number gets extremely big (about 10^21 or 2^69), and at that point, the gap between consecutive floating point numbers is also very big – it’s 2**46. So we just lose all precision in our calculations.
|
||||
|
||||
The term for this problem is “catastrophic cancellation” – we’re subtracting
|
||||
two very large floating point numbers which are both going to be pretty far
|
||||
from the correct value of the calculation, so the result of the subtraction is
|
||||
also going to be wrong.
|
||||
The term for this problem is “catastrophic cancellation” – we’re subtracting two very large floating point numbers which are both going to be pretty far from the correct value of the calculation, so the result of the subtraction is also going to be wrong. [The blog post I mentioned before][14]
|
||||
talks about a better algorithm people use to compute variance called Welford’s algorithm, which doesn’t have the catastrophic cancellation issue.
|
||||
|
||||
[The blog post I mentioned before][14]
|
||||
talks about a better algorithm people use to compute variance called
|
||||
Welford’s algorithm, which doesn’t have the catastrophic cancellation issue.
|
||||
|
||||
And of course, the solution for most people is to just use a scientific
|
||||
computing library like Numpy to calculate variance instead of trying to do it
|
||||
yourself :)
|
||||
And of course, the solution for most people is to just use a scientific computing library like Numpy to calculate variance instead of trying to do it yourself :)
|
||||
|
||||
#### example 4: different languages sometimes do the same floating point calculation differently
|
||||
|
||||
A bunch of people mentioned that different platforms will do the same
|
||||
calculation in different ways. One way this shows up in practice is – maybe
|
||||
you have some frontend code and some backend code that do the exact same
|
||||
floating point calculation. But it’s done slightly differently in Javascript
|
||||
and in PHP, so you users end up seeing discrepancies and getting confused.
|
||||
A bunch of people mentioned that different platforms will do the same calculation in different ways. One way this shows up in practice is – maybe you have some frontend code and some backend code that do the exact same floating point calculation. But it’s done slightly differently in Javascript and in PHP, so you users end up seeing discrepancies and getting confused.
|
||||
|
||||
In principle you might think that different implementations should work the
|
||||
same way because of the IEEE 754 standard for floating point, but here are a
|
||||
couple of caveats that were mentioned:
|
||||
In principle you might think that different implementations should work the same way because of the IEEE 754 standard for floating point, but here are a couple of caveats that were mentioned:
|
||||
|
||||
- math operations in libc (like sin/log) behave differently in different
|
||||
implementations. So code using glibc could give you different results than
|
||||
code using musl
|
||||
- some x86 instructions can use 80 bit precision for some double operations
|
||||
internally instead of 64 bit precision. [Here’s a GitHub issue talking about
|
||||
that][15]
|
||||
- math operations in libc (like sin/log) behave differently in different implementations. So code using glibc could give you different results than code using musl
|
||||
- some x86 instructions can use 80 bit precision for some double operations internally instead of 64 bit precision. [Here’s a GitHub issue talking about that][15]
|
||||
|
||||
I’m not very sure about these points and I don’t have concrete examples I can reproduce.
|
||||
|
||||
#### example 5: the deep space kraken
|
||||
|
||||
Kerbal Space Program is a space simulation game, and it used to have a bug
|
||||
called the [Deep Space Kraken][16] where when
|
||||
you moved very fast, your ship would start getting destroyed due to floating point issues. This is similar to the other problems we’ve talked out involving big floating numbers (like the variance problem), but I wanted to mention it because:
|
||||
Kerbal Space Program is a space simulation game, and it used to have a bug called the [Deep Space Kraken][16] where when you moved very fast, your ship would start getting destroyed due to floating point issues. This is similar to the other problems we’ve talked out involving big floating numbers (like the variance problem), but I wanted to mention it because:
|
||||
|
||||
- it has a funny name
|
||||
- it seems like a very common bug in video games / astrophysics / simulations in general – if you have points that are very far from the origin, your math gets messed up
|
||||
@ -307,32 +240,24 @@ Another example of this is the [Far Lands][17] in Minecraft.
|
||||
|
||||
#### example 6: the inaccurate timestamp
|
||||
|
||||
I promise this is the last example of “very large floating numbers can ruin your day”.
|
||||
But! Just one more! Let’s imagine that we try to represent the current Unix epoch in nanoseconds
|
||||
(about 1673580409000000000) as a 64-bit floating point number.
|
||||
I promise this is the last example of “very large floating numbers can ruin your day”. But! Just one more! Let’s imagine that we try to represent the current Unix epoch in nanoseconds (about 1673580409000000000) as a 64-bit floating point number.
|
||||
|
||||
This is no good! 1673580409000000000 is about 2^60 (crucially, bigger than 2^53), and the next 64-bit float after it is 1673580409000000256.
|
||||
|
||||
So this would be a great way to end up with inaccuracies in your time math. Of
|
||||
course, time libraries actually represent times as integers, so this isn’t
|
||||
usually a problem. (there’s always still the [year 2038 problem][18], but that’s not
|
||||
related to floats)
|
||||
So this would be a great way to end up with inaccuracies in your time math. Of course, time libraries actually represent times as integers, so this isn’t usually a problem. (there’s always still the [year 2038 problem][18], but that’s not related to floats)
|
||||
|
||||
In general, the lesson here is that sometimes it’s better to use integers.
|
||||
|
||||
#### example 7: splitting a page into columns
|
||||
|
||||
Now that we’ve talked about problems with big floating point numbers, let’s do
|
||||
a problem with small floating point numbers.
|
||||
Now that we’ve talked about problems with big floating point numbers, let’s do a problem with small floating point numbers.
|
||||
|
||||
Let’s say you have a page width, and a column width, and you want to figure out:
|
||||
|
||||
- how many columns fit on the page
|
||||
- how much space is left over
|
||||
|
||||
You might reasonably try `floor(page_width / column_width)` for the first
|
||||
question and `page_width % column_width` for the second question. Because
|
||||
that would work just fine with integers!
|
||||
You might reasonably try `floor(page_width / column_width)` for the first question and `page_width % column_width` for the second question. Because that would work just fine with integers!
|
||||
|
||||
```
|
||||
In [5]: math.floor(13.716 / 4.572)
|
||||
@ -344,21 +269,15 @@ Out[6]: 4.571999999999999
|
||||
|
||||
This is wrong! The amount of space left is 0!
|
||||
|
||||
A better way to calculate the amount of space left might have been
|
||||
`13.716 - 3 * 4.572`, which gives us a very small negative number.
|
||||
A better way to calculate the amount of space left might have been `13.716 - 3 * 4.572`, which gives us a very small negative number.
|
||||
|
||||
I think the lesson here is to never calculate the same thing in 2 different ways with floats.
|
||||
|
||||
This is a very basic example but I can kind of see how this would create all
|
||||
kinds of problems if I was doing page layout with floating point numbers, or
|
||||
doing CAD drawings.
|
||||
This is a very basic example but I can kind of see how this would create all kinds of problems if I was doing page layout with floating point numbers, or doing CAD drawings.
|
||||
|
||||
#### example 8: collision checking
|
||||
|
||||
Here’s a very silly Python program, that starts a variable at 1000 and
|
||||
decrements it until it collides with 0. You can imagine that this is part of a
|
||||
pong game or something, and that `a` is a ball that’s supposed to collide with
|
||||
a wall.
|
||||
Here’s a very silly Python program, that starts a variable at 1000 and decrements it until it collides with 0. You can imagine that this is part of a pong game or something, and that `a` is a ball that’s supposed to collide with a wall.
|
||||
|
||||
```
|
||||
a = 1000
|
||||
@ -366,21 +285,15 @@ while a != 0:
|
||||
a -= 0.001
|
||||
```
|
||||
|
||||
You might expect this program to terminate. But it doesn’t! `a` is never 0,
|
||||
instead it goes from 1.673494676862619e-08 to -0.0009999832650532314.
|
||||
You might expect this program to terminate. But it doesn’t! `a` is never 0, instead it goes from 1.673494676862619e-08 to -0.0009999832650532314.
|
||||
|
||||
The lesson here is that instead of checking for float equality, usually you
|
||||
want to check if two numbers are different by some very small amount. Or here
|
||||
we could just write `while a > 0`.
|
||||
The lesson here is that instead of checking for float equality, usually you want to check if two numbers are different by some very small amount. Or here we could just write `while a > 0`.
|
||||
|
||||
#### that’s all for now
|
||||
|
||||
I didn’t even get to NaNs (the are so many of them!) or infinity or +0 / -0 or subnormals, but we’ve
|
||||
already written 2000 words and I’m going to just publish this.
|
||||
I didn’t even get to NaNs (the are so many of them!) or infinity or +0 / -0 or subnormals, but we’ve already written 2000 words and I’m going to just publish this.
|
||||
|
||||
I might write another followup post later – that Mastodon thread has literally
|
||||
15,000 words of floating point problems in it, there’s a lot of material! Or I
|
||||
might not, who knows :)
|
||||
I might write another followup post later – that Mastodon thread has literally 15,000 words of floating point problems in it, there’s a lot of material! Or I might not, who knows :)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -12,18 +12,22 @@ Examples of problems with integers
|
||||
|
||||
Hello! A few days back we talked about [problems with floating point numbers][1].
|
||||
|
||||
This got me thinking – but what about integers? Of course integers have all
|
||||
kinds of problems too – anytime you represent a number in a small fixed amount of
|
||||
space (like 8/16/32/64 bits), you’re going to run into problems.
|
||||
This got me thinking – but what about integers? Of course integers have all kinds of problems too – anytime you represent a number in a small fixed amount of space (like 8/16/32/64 bits), you’re going to run into problems.
|
||||
|
||||
So I [asked on Mastodon again][2] for examples of integer problems and got all kinds of great responses again. Here’s a table of contents.
|
||||
|
||||
[example 1: the small database primary key][3][example 2: integer overflow/underflow][4][aside: how do computers represent negative integers?][5][example 3: decoding a binary format in Java][6][example 4: misinterpreting an IP address or string as an integer][7][example 5: security problems because of integer overflow][8][example 6: the case of the mystery byte order][9][example 7: modulo of negative numbers][10][example 8: compilers removing integer overflow checks][11][example 9: the && typo][12]
|
||||
- [example 1: the small database primary key][3]
|
||||
- [example 2: integer overflow/underflow][4]
|
||||
- [aside: how do computers represent negative integers?][5]
|
||||
- [example 3: decoding a binary format in Java][6]
|
||||
- [example 4: misinterpreting an IP address or string as an integer][7]
|
||||
- [example 5: security problems because of integer overflow][8]
|
||||
- [example 6: the case of the mystery byte order][9]
|
||||
- [example 7: modulo of negative numbers][10]
|
||||
- [example 8: compilers removing integer overflow checks][11]
|
||||
- [example 9: the && typo][12]
|
||||
|
||||
Like last time, I’ve written some example programs to demonstrate these
|
||||
problems. I’ve tried to use a variety of languages in the examples (Go,
|
||||
Javascript, Java, and C) to show that these problems don’t just show up in
|
||||
super low level C programs – integers are everywhere!
|
||||
Like last time, I’ve written some example programs to demonstrate these problems. I’ve tried to use a variety of languages in the examples (Go, Javascript, Java, and C) to show that these problems don’t just show up in super low level C programs – integers are everywhere!
|
||||
|
||||
Also I’ve probably made some mistakes in here, I learned several things while writing this.
|
||||
|
||||
@ -36,9 +40,7 @@ One of the most classic (and most painful!) integer problems is:
|
||||
- oh no!
|
||||
- You need to do a database migration to switch your primary key to be a 64-bit integer instead
|
||||
|
||||
If the primary key actually reaches its maximum value I’m not sure exactly what
|
||||
happens, I’d imagine you wouldn’t be able to create any new database rows and
|
||||
it would be a very bad day for your massively successful service.
|
||||
If the primary key actually reaches its maximum value I’m not sure exactly what happens, I’d imagine you wouldn’t be able to create any new database rows and it would be a very bad day for your massively successful service.
|
||||
|
||||
#### example 2: integer overflow/underflow
|
||||
|
||||
@ -87,20 +89,15 @@ Some brief notes about other languages:
|
||||
- In C, you can compile with `clang -fsanitize=unsigned-integer-overflow`. Then if your code has an overflow/underflow like this, the program will crash.
|
||||
- Similarly in Rust, if you compile your program in debug mode it’ll crash if there’s an integer overflow. But in release mode it won’t crash, it’ll just happily decide that 0 - 1 = 4294967295.
|
||||
|
||||
The reason Rust doesn’t check for overflows if you compile your program in
|
||||
release mode (and the reason C and Go don’t check) is that – these checks are
|
||||
expensive! Integer arithmetic is a very big part of many computations, and
|
||||
making sure that every single addition isn’t overflowing makes it slower.
|
||||
The reason Rust doesn’t check for overflows if you compile your program in release mode (and the reason C and Go don’t check) is that – these checks are expensive! Integer arithmetic is a very big part of many computations, and making sure that every single addition isn’t overflowing makes it slower.
|
||||
|
||||
#### aside: how do computers represent negative integers?
|
||||
|
||||
I mentioned in the last section that `0xFFFFFFFF` can mean either `-1` or
|
||||
`4294967295`. You might be thinking – what??? Why would `0xFFFFFFFF` mean `-1`?
|
||||
I mentioned in the last section that `0xFFFFFFFF` can mean either `-1` or `4294967295`. You might be thinking – what??? Why would `0xFFFFFFFF` mean `-1`?
|
||||
|
||||
So let’s talk about how computers represent negative integers for a second.
|
||||
|
||||
I’m going to simplify and talk about 8-bit integers instead of 32-bit integers,
|
||||
because there are less of them and it works basically the same way.
|
||||
I’m going to simplify and talk about 8-bit integers instead of 32-bit integers, because there are less of them and it works basically the same way.
|
||||
|
||||
You can represent 256 different numbers with an 8-bit integer: 0 to 255
|
||||
|
||||
@ -112,9 +109,7 @@ You can represent 256 different numbers with an 8-bit integer: 0 to 255
|
||||
11111111 -> 255
|
||||
```
|
||||
|
||||
But what if you want to represent _negative_ integers? We still only have 8
|
||||
bits! So we need to reassign some of these and treat them as negative numbers
|
||||
instead.
|
||||
But what if you want to represent _negative_ integers? We still only have 8 bits! So we need to reassign some of these and treat them as negative numbers instead.
|
||||
|
||||
Here’s the way most modern computers do it:
|
||||
|
||||
@ -147,9 +142,7 @@ That’s how we end up with `0xFFFFFFFF` meaning -1.
|
||||
|
||||
#### there are multiple ways to represent negative integers
|
||||
|
||||
The way we just talked about of representing negative integers (“it’s the equivalent positive integer, but you subtract 2^n”) is called
|
||||
**two’s complement**, and it’s the most common on modern computers. There are several other ways
|
||||
though, the [wikipedia article has a list][14].
|
||||
The way we just talked about of representing negative integers (“it’s the equivalent positive integer, but you subtract 2^n”) is called **two’s complement**, and it’s the most common on modern computers. There are several other ways though, the [wikipedia article has a list][14].
|
||||
|
||||
#### weird thing: the absolute value of -128 is negative
|
||||
|
||||
@ -182,16 +175,13 @@ This prints out:
|
||||
-128
|
||||
```
|
||||
|
||||
This is because the signed 8-bit integers go from -128 to 127 – there **is** no +128!
|
||||
Some programs might crash when you try to do this (it’s an overflow), but Go
|
||||
doesn’t.
|
||||
This is because the signed 8-bit integers go from -128 to 127 – there **is** no +128! Some programs might crash when you try to do this (it’s an overflow), but Go doesn’t.
|
||||
|
||||
Now that we’ve talked about signed integers a bunch, let’s dig into another example of how they can cause problems.
|
||||
|
||||
#### example 3: decoding a binary format in Java
|
||||
|
||||
Let’s say you’re parsing a binary format in Java, and you want to get the first
|
||||
4 bits of the byte `0x90`. The correct answer is 9.
|
||||
Let’s say you’re parsing a binary format in Java, and you want to get the first 4 bits of the byte `0x90`. The correct answer is 9.
|
||||
|
||||
```
|
||||
public class Main {
|
||||
@ -222,9 +212,7 @@ Let’s break down what those two facts mean for our little calculation `b >> 4`
|
||||
|
||||
#### what can you do about it?
|
||||
|
||||
I don’t the actual idiomatic way to do this in Java is, but the way I’d naively
|
||||
approach fixing this is to put in a bit mask before doing the right shift. So
|
||||
instead of:
|
||||
I don’t the actual idiomatic way to do this in Java is, but the way I’d naively approach fixing this is to put in a bit mask before doing the right shift. So instead of:
|
||||
|
||||
```
|
||||
b >> 4
|
||||
@ -238,20 +226,15 @@ we’d write
|
||||
|
||||
`b & 0xFF` seems redundant (`b` is already a byte!), but it’s actually not because `b` is being promoted to an integer.
|
||||
|
||||
Now instead of `0x90 -> 0xFFFFFF90 -> 0xFFFFFFF9`, we end up calculating `0x90 -> 0xFFFFFF90 -> 0x00000090 -> 0x00000009`, which is the result we wanted: 9.
|
||||
Now instead of `0x90 -> 0xFFFFFF90 -> 0xFFFFFFF9`, we end up calculating `0x90 -> 0xFFFFFF90 -> 0x00000090 -> x00000009`, which is the result we wanted: 9.
|
||||
|
||||
And when we actually try it, it prints out “9”.
|
||||
|
||||
Also, if we were using a language with unsigned integers, the natural way to
|
||||
deal with this would be to treat the value as an unsigned integer in the first
|
||||
place. But that’s not possible in Java.
|
||||
Also, if we were using a language with unsigned integers, the natural way to deal with this would be to treat the value as an unsigned integer in the first place. But that’s not possible in Java.
|
||||
|
||||
#### example 4: misinterpreting an IP address or string as an integer
|
||||
|
||||
I don’t know if this is technically a “problem with integers” but it’s funny
|
||||
so I’ll mention it: [Rachel by the bay][16] has a bunch of great
|
||||
examples of things that are not integers being interpreted as integers. For
|
||||
example, “HTTP” is `0x48545450` and `2130706433` is `127.0.0.1`.
|
||||
I don’t know if this is technically a “problem with integers” but it’s funny so I’ll mention it: [Rachel by the bay][16] has a bunch of great examples of things that are not integers being interpreted as integers. For example, “HTTP” is `0x48545450` and `2130706433` is `127.0.0.1`.
|
||||
|
||||
She points out that you can actually ping any integer, and it’ll convert that integer into an IP address, for example:
|
||||
|
||||
@ -266,8 +249,7 @@ PING 132848123841239999988888888888234234234234234234 (251.164.101.122): 56 data
|
||||
|
||||
#### example 5: security problems because of integer overflow
|
||||
|
||||
Another integer overflow example: here’s a [search for CVEs involving integer overflows][17].
|
||||
There are a lot! I’m not a security person, but here’s one random example: this [json parsing library bug][18]
|
||||
Another integer overflow example: here’s a [search for CVEs involving integer overflows][17]. There are a lot! I’m not a security person, but here’s one random example: this [json parsing library bug][18]
|
||||
|
||||
My understanding of that json parsing bug is roughly:
|
||||
|
||||
@ -276,40 +258,25 @@ My understanding of that json parsing bug is roughly:
|
||||
- but the JSON file is still 3GB, so it gets copied into the tiny buffer with almost 0 bytes of memory
|
||||
- this overwrites all kinds of other memory that it’s not supposed to
|
||||
|
||||
The CVE says “This vulnerability mostly impacts process availability”, which I
|
||||
think means “the program crashes”, but sometimes this kind of thing is much
|
||||
worse and can result in arbitrary code execution.
|
||||
The CVE says “This vulnerability mostly impacts process availability”, which I think means “the program crashes”, but sometimes this kind of thing is much worse and can result in arbitrary code execution.
|
||||
|
||||
My impression is that there are a large variety of different flavours of
|
||||
security vulnerabilities caused by integer overflows.
|
||||
My impression is that there are a large variety of different flavours of security vulnerabilities caused by integer overflows.
|
||||
|
||||
#### example 6: the case of the mystery byte order
|
||||
|
||||
One person said that they’re do scientific computing and sometimes they need to
|
||||
read files which contain data with an unknown byte order.
|
||||
One person said that they’re do scientific computing and sometimes they need to read files which contain data with an unknown byte order.
|
||||
|
||||
Let’s invent a small example of this: say you’re reading a file which contains 4
|
||||
bytes - `00`, `00`, `12`, and `81` (in that order), that you happen to know
|
||||
represent a 4-byte integer. There are 2 ways to interpret that integer:
|
||||
Let’s invent a small example of this: say you’re reading a file which contains 4 bytes - `00`, `00`, `12`, and `81` (in that order), that you happen to know represent a 4-byte integer. There are 2 ways to interpret that integer:
|
||||
|
||||
- `0x00001281` (which translates to 4737). This order is called “big endian”
|
||||
- `0x81120000` (which translates to 2165440512). This order is called “little endian”.
|
||||
|
||||
Which one is it? Well, maybe the file contains some metadata that specifies the
|
||||
endianness. Or maybe you happen to know what machine it was generated on and
|
||||
what byte order that machine uses. Or maybe you just read a bunch of values,
|
||||
try both orders, and figure out which makes more sense. Maybe 2165440512 is too
|
||||
big to make sense in the context of whatever your data is supposed to mean, or
|
||||
maybe `4737` is too small.
|
||||
Which one is it? Well, maybe the file contains some metadata that specifies the endianness. Or maybe you happen to know what machine it was generated on and what byte order that machine uses. Or maybe you just read a bunch of values, try both orders, and figure out which makes more sense. Maybe 2165440512 is too big to make sense in the context of whatever your data is supposed to mean, or maybe `4737` is too small.
|
||||
|
||||
A couple more notes on this:
|
||||
|
||||
- this isn’t just a problem with integers, floating point numbers have byte
|
||||
order too
|
||||
- this also comes up when reading data from a network, but in that case the
|
||||
byte order isn’t a “mystery”, it’s just going to be big endian. But x86
|
||||
machines (and many others) are little endian, so you have to swap the byte
|
||||
order of all your numbers.
|
||||
- this isn’t just a problem with integers, floating point numbers have byte order too
|
||||
- this also comes up when reading data from a network, but in that case the byte order isn’t a “mystery”, it’s just going to be big endian. But x86 machines (and many others) are little endian, so you have to swap the byte order of all your numbers.
|
||||
|
||||
#### example 7: modulo of negative numbers
|
||||
|
||||
@ -317,17 +284,13 @@ This is more of a design decision about how different programming languages desi
|
||||
|
||||
Let’s say you write `-13 % 3` in your program, or `13 % -3`. What’s the result?
|
||||
|
||||
It turns out that different programming languages do it differently, for
|
||||
example in Python `-13 % 3 = 2` but in Javascript `-13 % 3 = -1`.
|
||||
It turns out that different programming languages do it differently, for example in Python `-13 % 3 = 2` but in Javascript `-13 % 3 = -1`.
|
||||
|
||||
There’s a table in [this blog post][19] that
|
||||
describes a bunch of different programming languages’ choices.
|
||||
There’s a table in [this blog post][19] that describes a bunch of different programming languages’ choices.
|
||||
|
||||
#### example 8: compilers removing integer overflow checks
|
||||
|
||||
We’ve been hearing a lot about integer overflow and why it’s bad. So let’s
|
||||
imagine you try to be safe and include some checks in your programs – after
|
||||
each addition, you make sure that the calculation didn’t overflow. Like this:
|
||||
We’ve been hearing a lot about integer overflow and why it’s bad. So let’s imagine you try to be safe and include some checks in your programs – after each addition, you make sure that the calculation didn’t overflow. Like this:
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
@ -356,39 +319,26 @@ $ gcc -O3 check_overflow.c -o check_overflow && ./check_overflow
|
||||
0
|
||||
```
|
||||
|
||||
That’s weird – when we compile with `gcc`, we get the answer we expected, but
|
||||
with `gcc -O3`, we get a different answer. Why?
|
||||
That’s weird – when we compile with `gcc`, we get the answer we expected, but with `gcc -O3`, we get a different answer. Why?
|
||||
|
||||
#### what’s going on?
|
||||
|
||||
My understanding (which might be wrong) is:
|
||||
|
||||
- Signed integer overflow in C is **undefined behavior**. I think that’s
|
||||
because different C implementations might be using different representations
|
||||
of signed integers (maybe they’re using one’s complement instead of two’s
|
||||
complement or something)
|
||||
- Signed integer overflow in C is **undefined behavior**. I think that’s because different C implementations might be using different representations of signed integers (maybe they’re using one’s complement instead of two’s complement or something)
|
||||
- “undefined behaviour” in C means “the compiler is free to do literally whatever it wants after that point” (see this post [With undefined behaviour, anything is possible][20] by Raph Levine for a lot more)
|
||||
- Some compiler optimizations assume that undefined behaviour will never
|
||||
happen. They’re free to do this, because – if that undefined behaviour
|
||||
_did_ happen, then they’re allowed to do whatever they want, so “run the
|
||||
code that I optimized assuming that this would never happen” is fine.
|
||||
- So this `if (n + 100 < 0)` check is irrelevant – if that did
|
||||
happen, it would be undefined behaviour, so there’s no need to execute the
|
||||
contents of that if statement.
|
||||
- Some compiler optimizations assume that undefined behaviour will never happen. They’re free to do this, because – if that undefined behaviour _did_ happen, then they’re allowed to do whatever they want, so “run the code that I optimized assuming that this would never happen” is fine.
|
||||
- So this `if (n + 100 < 0)` check is irrelevant – if that did happen, it would be undefined behaviour, so there’s no need to execute the contents of that if statement.
|
||||
|
||||
So, that’s weird. I’m not going to write a “what can you do about it?” section here because I’m pretty out of my depth already.
|
||||
|
||||
I certainly would not have expected that though.
|
||||
|
||||
My impression is that “undefined behaviour” is really a C/C++ concept, and
|
||||
doesn’t exist in other languages in the same way except in the case of “your
|
||||
program called some C code in an incorrect way and that C code did something
|
||||
weird because of undefined behaviour”. Which of course happens all the time.
|
||||
My impression is that “undefined behaviour” is really a C/C++ concept, and doesn’t exist in other languages in the same way except in the case of “your program called some C code in an incorrect way and that C code did something weird because of undefined behaviour”. Which of course happens all the time.
|
||||
|
||||
#### example 9: the && typo
|
||||
|
||||
This one was mentioned as a very upsetting bug. Let’s say you have two integers
|
||||
and you want to check that they’re both nonzero.
|
||||
This one was mentioned as a very upsetting bug. Let’s say you have two integers and you want to check that they’re both nonzero.
|
||||
|
||||
In Javascript, you might write:
|
||||
|
||||
@ -406,9 +356,7 @@ if a & b {
|
||||
}
|
||||
```
|
||||
|
||||
This is still perfectly valid code, but it means something completely different
|
||||
– it’s a bitwise and instead of a boolean and. Let’s go into a Javascript
|
||||
console and look at bitwise vs boolean and for `9` and `4`:
|
||||
This is still perfectly valid code, but it means something completely different – it’s a bitwise and instead of a boolean and. Let’s go into a Javascript console and look at bitwise vs boolean and for `9` and `4`:
|
||||
|
||||
```
|
||||
> 9 && 4
|
||||
@ -421,20 +369,15 @@ console and look at bitwise vs boolean and for `9` and `4`:
|
||||
4
|
||||
```
|
||||
|
||||
It’s easy to imagine this turning into a REALLY annoying bug since it would be
|
||||
intermittent – often `x & y` does turn out to be truthy if `x && y` is truthy.
|
||||
It’s easy to imagine this turning into a REALLY annoying bug since it would be intermittent – often `x & y` does turn out to be truthy if `x && y` is truthy.
|
||||
|
||||
#### what to do about it?
|
||||
|
||||
For Javascript, ESLint has a [no-bitwise check][21] check), which
|
||||
requires you manually flag “no, I actually know what I’m doing, I want to do
|
||||
bitwise and” if you use a bitwise and in your code. I’m sure many other linters
|
||||
have a similar check.
|
||||
For Javascript, ESLint has a [no-bitwise check][21] check), which requires you manually flag “no, I actually know what I’m doing, I want to do bitwise and” if you use a bitwise and in your code. I’m sure many other linters have a similar check.
|
||||
|
||||
#### that’s all for now!
|
||||
|
||||
There are definitely more problems with integers than this, but this got pretty
|
||||
long again and I’m tired of writing again so I’m going to stop :)
|
||||
There are definitely more problems with integers than this, but this got pretty long again and I’m tired of writing again so I’m going to stop :)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,26 +10,16 @@
|
||||
Why does 0.1 + 0.2 = 0.30000000000000004?
|
||||
======
|
||||
|
||||
Hello! I was trying to write about floating point yesterday,
|
||||
and I found myself wondering about this calculation, with 64-bit floats:
|
||||
Hello! I was trying to write about floating point yesterday, and I found myself wondering about this calculation, with 64-bit floats:
|
||||
|
||||
```
|
||||
>>> 0.1 + 0.2
|
||||
0.30000000000000004
|
||||
```
|
||||
|
||||
I realized that I didn’t understand exactly how it worked. I mean, I know
|
||||
floating point calculations are inexact, and I know that you can’t exactly
|
||||
represent `0.1` in binary, but: there’s a floating point number that’s closer to
|
||||
0.3 than `0.30000000000000004`! So why do we get the answer
|
||||
`0.30000000000000004`?
|
||||
I realized that I didn’t understand exactly how it worked. I mean, I know floating point calculations are inexact, and I know that you can’t exactly represent `0.1` in binary, but: there’s a floating point number that’s closer to 0.3 than `0.30000000000000004`! So why do we get the answer `0.30000000000000004`?
|
||||
|
||||
If you don’t feel like reading this whole post with a bunch of calculations, the short answer is that
|
||||
`0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125` lies exactly between
|
||||
2 floating point numbers,
|
||||
`0.299999999999999988897769753748434595763683319091796875` (usually printed as `0.3`) and
|
||||
`0.3000000000000000444089209850062616169452667236328125` (usually printed as `0.30000000000000004`). The answer is
|
||||
`0.30000000000000004` (the second one) because its significand is even.
|
||||
If you don’t feel like reading this whole post with a bunch of calculations, the short answer is that `0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125` lies exactly between 2 floating point numbers, `0.299999999999999988897769753748434595763683319091796875` (usually printed as `0.3`) and `0.3000000000000000444089209850062616169452667236328125` (usually printed as `0.30000000000000004`). The answer is `0.30000000000000004` (the second one) because its significand is even.
|
||||
|
||||
#### how floating point addition works
|
||||
|
||||
@ -38,9 +28,7 @@ This is roughly how floating point addition works:
|
||||
- Add together the numbers (with extra precision)
|
||||
- Round the result to the nearest floating point number
|
||||
|
||||
So let’s use these rules to calculate 0.1 + 0.2. I just learned how floating
|
||||
point addition works yesterday so it’s possible I’ve made some mistakes in this
|
||||
post, but I did get the answers I expected at the end.
|
||||
So let’s use these rules to calculate 0.1 + 0.2. I just learned how floating point addition works yesterday so it’s possible I’ve made some mistakes in this post, but I did get the answers I expected at the end.
|
||||
|
||||
#### step 1: find out what 0.1 and 0.2 are
|
||||
|
||||
@ -53,9 +41,7 @@ First, let’s use Python to figure out what the exact values of `0.1` and `0.2`
|
||||
'0.20000000000000001110223024625156540423631668090820312500000000000000000000000000'
|
||||
```
|
||||
|
||||
These really are the exact values: because floating point numbers are in base
|
||||
2, you can represent them all exactly in base 10. You just need a lot of digits
|
||||
sometimes :)
|
||||
These really are the exact values: because floating point numbers are in base 2, you can represent them all exactly in base 10. You just need a lot of digits sometimes :)
|
||||
|
||||
#### step 2: add the numbers together
|
||||
|
||||
@ -79,8 +65,7 @@ Now, let’s look at the floating point numbers around `0.3`. Here’s the close
|
||||
'0.29999999999999998889776975374843459576368331909179687500000000000000000000000000'
|
||||
```
|
||||
|
||||
We can figure out the next floating point number after `0.3` by serializing
|
||||
`0.3` to 8 bytes with `struct.pack`, adding 1, and then using `struct.unpack`:
|
||||
We can figure out the next floating point number after `0.3` by serializing `0.3` to 8 bytes with `struct.pack`, adding 1, and then using `struct.unpack`:
|
||||
|
||||
```
|
||||
>>> struct.pack("!d", 0.3)
|
||||
@ -100,17 +85,13 @@ Apparently you can also do this with `math.nextafter`:
|
||||
0.30000000000000004
|
||||
```
|
||||
|
||||
So the two 64-bit floats around
|
||||
`0.3` are
|
||||
`0.299999999999999988897769753748434595763683319091796875` and
|
||||
So the two 64-bit floats around `0.3` are `0.299999999999999988897769753748434595763683319091796875` and
|
||||
`0.3000000000000000444089209850062616169452667236328125`
|
||||
|
||||
#### step 4: find out which one is closest to our result
|
||||
|
||||
It turns out that `0.3000000000000000166533453693773481063544750213623046875`
|
||||
is exactly in the middle of
|
||||
`0.299999999999999988897769753748434595763683319091796875` and
|
||||
`0.3000000000000000444089209850062616169452667236328125`.
|
||||
It turns out that `0.3000000000000000166533453693773481063544750213623046875` is exactly in the middle of
|
||||
`0.299999999999999988897769753748434595763683319091796875` and `0.3000000000000000444089209850062616169452667236328125`.
|
||||
|
||||
You can see that with this calculation:
|
||||
|
||||
@ -123,10 +104,7 @@ So neither of them is closest.
|
||||
|
||||
#### how does it know which one to round to?
|
||||
|
||||
In the binary representation of a floating point number, there’s a number
|
||||
called the “significand”. In cases like this (where the result is exactly in
|
||||
between 2 successive floating point number, it’ll round to the one with the
|
||||
even significand.
|
||||
In the binary representation of a floating point number, there’s a number called the “significand”. In cases like this (where the result is exactly in between 2 successive floating point number, it’ll round to the one with the even significand.
|
||||
|
||||
In this case that’s `0.300000000000000044408920985006261616945266723632812500`
|
||||
|
||||
@ -135,20 +113,13 @@ We actually saw the significand of this number a bit earlier:
|
||||
- 0.30000000000000004 is `struct.unpack('!d', b'?\xd3333334')`
|
||||
- 0.3 is `struct.unpack('!d', b'?\xd3333333')`
|
||||
|
||||
The last digit of the big endian hex representation of `0.30000000000000004` is
|
||||
`4`, so that’s the one with the even significand (because the significand is at
|
||||
the end).
|
||||
The last digit of the big endian hex representation of `0.30000000000000004` is `4`, so that’s the one with the even significand (because the significand is at the end).
|
||||
|
||||
#### let’s also work out the whole calculation in binary
|
||||
|
||||
Above we did the calculation in decimal, because that’s a little more intuitive
|
||||
to read. But of course computers don’t do these calculations in decimal –
|
||||
they’re done in a base 2 representation. So I wanted to get an idea of how that
|
||||
worked too.
|
||||
Above we did the calculation in decimal, because that’s a little more intuitive to read. But of course computers don’t do these calculations in decimal – they’re done in a base 2 representation. So I wanted to get an idea of how that worked too.
|
||||
|
||||
I don’t think this binary calculation part of the post is particularly clear
|
||||
but it was helpful for me to write out. There are a really a lot of numbers and
|
||||
it might be terrible to read.
|
||||
I don’t think this binary calculation part of the post is particularly clear but it was helpful for me to write out. There are a really a lot of numbers and it might be terrible to read.
|
||||
|
||||
#### how 64-bit floats numbers work: exponent and significand
|
||||
|
||||
@ -181,11 +152,9 @@ def get_significand(f):
|
||||
return x ^ (exponent << 52)
|
||||
```
|
||||
|
||||
I’m ignoring the sign bit (the first bit) because we only need these functions
|
||||
to work on two numbers (0.1 and 0.2) and those two numbers are both positive.
|
||||
I’m ignoring the sign bit (the first bit) because we only need these functions to work on two numbers (0.1 and 0.2) and those two numbers are both positive.
|
||||
|
||||
First, let’s get the exponent and significand of 0.1. We need to subtract 1023
|
||||
to get the actual exponent because that’s how floating point works.
|
||||
First, let’s get the exponent and significand of 0.1. We need to subtract 1023 to get the actual exponent because that’s how floating point works.
|
||||
|
||||
```
|
||||
>>> get_exponent(0.1) - 1023
|
||||
@ -203,9 +172,7 @@ Here’s that calculation in Python:
|
||||
0.1
|
||||
```
|
||||
|
||||
(you might legitimately be worried about floating point accuracy issues with
|
||||
this calculation, but in this case I’m pretty sure it’s fine because these
|
||||
numbers by definition don’t have accuracy issues – the floating point numbers starting at `2**-4` go up in steps of `1/2**(52 + 4)`)
|
||||
(you might legitimately be worried about floating point accuracy issues with this calculation, but in this case I’m pretty sure it’s fine because these numbers by definition don’t have accuracy issues – the floating point numbers starting at `2**-4` go up in steps of `1/2**(52 + 4)`)
|
||||
|
||||
We can do the same thing for `0.2`:
|
||||
|
||||
@ -309,10 +276,7 @@ That’s the answer we expected:
|
||||
|
||||
#### this probably isn’t exactly how it works in hardware
|
||||
|
||||
The way I’ve described the operations here isn’t literally exactly
|
||||
what happens when you do floating point addition (it’s not “solving for X” for
|
||||
example), I’m sure there are a lot of efficient tricks. But I think it’s about
|
||||
the same idea.
|
||||
The way I’ve described the operations here isn’t literally exactly what happens when you do floating point addition (it’s not “solving for X” for example), I’m sure there are a lot of efficient tricks. But I think it’s about the same idea.
|
||||
|
||||
#### printing out floating point numbers is pretty weird
|
||||
|
||||
@ -325,48 +289,31 @@ We said earlier that the floating point number 0.3 isn’t equal to 0.3. It’s
|
||||
|
||||
So when you print out that number, why does it display `0.3`?
|
||||
|
||||
The computer isn’t actually printing out the exact value of the number, instead
|
||||
it’s printing out the _shortest_ decimal number `d` which has the property that
|
||||
our floating point number `f` is the closest floating point number to `d`.
|
||||
The computer isn’t actually printing out the exact value of the number, instead it’s printing out the _shortest_ decimal number `d` which has the property that our floating point number `f` is the closest floating point number to `d`.
|
||||
|
||||
It turns out that doing this efficiently isn’t trivial at all, and there are a bunch of academic papers about it like [Printing Floating-Point Numbers Quickly and Accurately][1]. or [How to print floating point numbers accurately][2].
|
||||
|
||||
#### would it be more intuitive if computers printed out the exact value of a float?
|
||||
|
||||
Rounding to a nice clean decimal value is nice, but in a way I feel like it
|
||||
might be more intuitive if computers just printed out the exact value of a
|
||||
floating point number – it might make it seem a lot less surprising when you
|
||||
get weird results.
|
||||
Rounding to a nice clean decimal value is nice, but in a way I feel like it might be more intuitive if computers just printed out the exact value of a floating point number – it might make it seem a lot less surprising when you get weird results.
|
||||
|
||||
To me,
|
||||
0.1000000000000000055511151231257827021181583404541015625 +
|
||||
0.200000000000000011102230246251565404236316680908203125
|
||||
= 0.3000000000000000444089209850062616169452667236328125 feels less surprising than 0.1 + 0.2 = 0.30000000000000004.
|
||||
To me, 0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125 feels less surprising than 0.1 + 0.2 = 0.30000000000000004.
|
||||
|
||||
Probably this is a bad idea, it would definitely use a lot of screen space.
|
||||
|
||||
#### a quick note on PHP
|
||||
|
||||
Someone in the comments somewhere pointed out that `<?php echo (0.1 + 0.2 );?>`
|
||||
prints out `0.3`. Does that mean that floating point math is different in PHP?
|
||||
Someone in the comments somewhere pointed out that `<?php echo (0.1 + 0.2 );?>` prints out `0.3`. Does that mean that floating point math is different in PHP?
|
||||
|
||||
I think the answer is no – if I run:
|
||||
|
||||
`<?php echo (0.1 + 0.2 )- 0.3);?>` on [this
|
||||
page][3], I get the exact same answer as in
|
||||
Python 5.5511151231258E-17. So it seems like the underlying floating point
|
||||
math is the same.
|
||||
`<?php echo (0.1 + 0.2 )- 0.3);?>` on [this page][3], I get the exact same answer as in Python 5.5511151231258E-17. So it seems like the underlying floating point math is the same.
|
||||
|
||||
I think the reason that `0.1 + 0.2` prints out `0.3` in PHP is that PHP’s
|
||||
algorithm for displaying floating point numbers is less precise than Python’s
|
||||
– it’ll display `0.3` even if that number isn’t the closest floating point
|
||||
number to 0.3.
|
||||
I think the reason that `0.1 + 0.2` prints out `0.3` in PHP is that PHP’s algorithm for displaying floating point numbers is less precise than Python’s – it’ll display `0.3` even if that number isn’t the closest floating point number to 0.3.
|
||||
|
||||
#### that’s all!
|
||||
|
||||
I kind of doubt that anyone had the patience to follow all of that arithmetic,
|
||||
but it was helpful for me to write down, so I’m publishing this post anyway.
|
||||
Hopefully some of this makes sense.
|
||||
I kind of doubt that anyone had the patience to follow all of that arithmetic, but it was helpful for me to write down, so I’m publishing this post anyway. Hopefully some of this makes sense.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,33 +10,19 @@
|
||||
Some notes on using nix
|
||||
======
|
||||
|
||||
Recently I started using a Mac for the first time. The biggest downside I’ve
|
||||
noticed so far is that the package management is much worse than on Linux.
|
||||
At some point I got frustrated with homebrew because I felt like it was
|
||||
spending too much time upgrading when I installed new packages, and so I
|
||||
thought – maybe I’ll try the [nix][1] package manager!
|
||||
Recently I started using a Mac for the first time. The biggest downside I’ve noticed so far is that the package management is much worse than on Linux. At some point I got frustrated with homebrew because I felt like it was spending too much time upgrading when I installed new packages, and so I thought – maybe I’ll try the [nix][1] package manager!
|
||||
|
||||
nix has a reputation for being confusing (it has its whole
|
||||
own programming language!), so I’ve been trying to figure out how to use nix in
|
||||
a way that’s as simple as possible and does not involve managing any
|
||||
configuration files or learning a new programming language. Here’s what I’ve
|
||||
figured out so far! We’ll talk about how to:
|
||||
nix has a reputation for being confusing (it has its whole own programming language!), so I’ve been trying to figure out how to use nix in a way that’s as simple as possible and does not involve managing any configuration files or learning a new programming language. Here’s what I’ve figured out so far! We’ll talk about how to:
|
||||
|
||||
- install packages with nix
|
||||
- build a custom nix package for a C++ program called [paperjam][2]
|
||||
- install a 5-year-old version of [hugo][3] with nix
|
||||
|
||||
As usual I’ve probably gotten some stuff wrong in this post since I’m still
|
||||
pretty new to nix. I’m also still not sure how much I like nix – it’s very
|
||||
confusing! But it’s helped me compile some software that I was struggling to
|
||||
compile otherwise, and in general it seems to install things faster than
|
||||
homebrew.
|
||||
As usual I’ve probably gotten some stuff wrong in this post since I’m still pretty new to nix. I’m also still not sure how much I like nix – it’s very confusing! But it’s helped me compile some software that I was struggling to compile otherwise, and in general it seems to install things faster than homebrew.
|
||||
|
||||
#### what’s interesting about nix?
|
||||
|
||||
People often describe nix as “declarative package management”. I don’t
|
||||
care that much about declarative package management, so here are two things
|
||||
that I appreciate about nix:
|
||||
People often describe nix as “declarative package management”. I don’t care that much about declarative package management, so here are two things that I appreciate about nix:
|
||||
|
||||
- It provides binary packages (hosted at [https://cache.nixos.org/][4]) that you can quickly download and install
|
||||
- For packages which don’t have binary packages, it makes it easier to compile them
|
||||
@ -44,12 +30,8 @@ that I appreciate about nix:
|
||||
I think that the reason nix is good at compiling software is that:
|
||||
|
||||
- you can have multiple versions of the same library or program installed at a time (you could have 2 different versions of libc for instance). For example I have two versions of node on my computer right now, one at `/nix/store/4ykq0lpvmskdlhrvz1j3kwslgc6c7pnv-nodejs-16.17.1` and one at `/nix/store/5y4bd2r99zhdbir95w5pf51bwfg37bwa-nodejs-18.9.1`.
|
||||
- when nix builds a package, it builds it in isolation, using only the
|
||||
specific versions of its dependencies that you explicitly declared. So
|
||||
there’s no risk that the package secretly depends on another package on your
|
||||
system that you don’t know about. No more fighting with `LD_LIBRARY_PATH`!
|
||||
- a lot of people have put a lot of work into writing down all of the
|
||||
dependencies of packages
|
||||
- when nix builds a package, it builds it in isolation, using only the specific versions of its dependencies that you explicitly declared. So there’s no risk that the package secretly depends on another package on your
|
||||
system that you don’t know about. No more fighting with `LD_LIBRARY_PATH`! - a lot of people have put a lot of work into writing down all of the dependencies of packages
|
||||
|
||||
I’ll give a couple of examples later in this post of two times nix made it easier for me to compile software.
|
||||
|
||||
@ -72,15 +54,11 @@ nix-env -iA nixpkgs.fish
|
||||
|
||||
This seems to just download some binaries from [https://cache.nixos.org][8] – pretty simple.
|
||||
|
||||
Some people use nix to install their Node and Python and Ruby packages, but I haven’t
|
||||
been doing that – I just use `npm install` and `pip install` the same way I
|
||||
always have.
|
||||
Some people use nix to install their Node and Python and Ruby packages, but I haven’t been doing that – I just use `npm install` and `pip install` the same way I always have.
|
||||
|
||||
#### some nix features I’m not using
|
||||
|
||||
There are a bunch of nix features/tools that I’m not using, but that I’ll
|
||||
mention. I originally thought that you _had_ to use these features to use nix,
|
||||
because most of the nix tutorials I’ve read talk about them. But you don’t have to use them.
|
||||
There are a bunch of nix features/tools that I’m not using, but that I’ll mention. I originally thought that you _had_ to use these features to use nix, because most of the nix tutorials I’ve read talk about them. But you don’t have to use them.
|
||||
|
||||
- NixOS (a Linux distribution)
|
||||
- [nix-shell][9]
|
||||
@ -88,8 +66,7 @@ because most of the nix tutorials I’ve read talk about them. But you don’t h
|
||||
- [home-manager][11]
|
||||
- [devenv.sh][12]
|
||||
|
||||
I won’t go into these because I haven’t really used them and there are lots of
|
||||
explanations out there.
|
||||
I won’t go into these because I haven’t really used them and there are lots of explanations out there.
|
||||
|
||||
#### where are nix packages defined?
|
||||
|
||||
@ -107,16 +84,14 @@ I found a way to search nix packages from the command line that I liked better:
|
||||
|
||||
#### everything is installed with symlinks
|
||||
|
||||
One of nix’s major design choices is that there isn’t one single `bin` with all
|
||||
your packages, instead you use symlinks. There are a lot of layers of symlinks. A few examples of symlinks:
|
||||
One of nix’s major design choices is that there isn’t one single `bin` with all your packages, instead you use symlinks. There are a lot of layers of symlinks. A few examples of symlinks:
|
||||
|
||||
- `~/.nix-profile` on my machine is (indirectly) a symlink to `/nix/var/nix/profiles/per-user/bork/profile-111-link/`
|
||||
- `~/.nix-profile/bin/fish` is a symlink to `/nix/store/afkwn6k8p8g97jiqgx9nd26503s35mgi-fish-3.5.1/bin/fish`
|
||||
|
||||
When I install something, it creates a new `profile-112-link` directory with new symlinks and updates my `~/.nix-profile` to point to that directory.
|
||||
|
||||
I think this means that if I install a new version of `fish` and I don’t like it, I can
|
||||
easily go back just by running `nix-env --rollback` – it’ll move me to my previous profile directory.
|
||||
I think this means that if I install a new version of `fish` and I don’t like it, I can easily go back just by running `nix-env --rollback` – it’ll move me to my previous profile directory.
|
||||
|
||||
#### uninstalling packages doesn’t delete them
|
||||
|
||||
@ -161,28 +136,19 @@ I haven’t really upgraded anything yet. I think that if something goes wrong w
|
||||
nix-env --rollback
|
||||
```
|
||||
|
||||
Someone linked me to [this post from Ian Henry][15] that
|
||||
talks about some confusing problems with `nix-env --upgrade` – maybe it
|
||||
doesn’t work the way you’d expect? I guess I’ll be wary around upgrades.
|
||||
Someone linked me to [this post from Ian Henry][15] that talks about some confusing problems with `nix-env --upgrade` – maybe it doesn’t work the way you’d expect? I guess I’ll be wary around upgrades.
|
||||
|
||||
#### next goal: make a custom package of paperjam
|
||||
|
||||
After a few months of installing existing packages, I wanted to make a custom package with nix for a program called [paperjam][2] that wasn’t already packaged.
|
||||
|
||||
I was actually struggling to compile `paperjam` at all even without nix because the version I had
|
||||
of `libiconv` I has on my system was wrong. I thought it might be easier to
|
||||
compile it with nix even though I didn’t know how to make nix packages yet. And
|
||||
it actually was!
|
||||
I was actually struggling to compile `paperjam` at all even without nix because the version I had of `libiconv` I has on my system was wrong. I thought it might be easier to compile it with nix even though I didn’t know how to make nix packages yet. And it actually was!
|
||||
|
||||
But figuring out how to get there was VERY confusing, so here are some notes about how I did it.
|
||||
|
||||
#### how to build an example package
|
||||
|
||||
Before I started working on my `paperjam` package, I wanted to build an example existing package just to
|
||||
make sure I understood the process for building a package. I was really
|
||||
struggling to figure out how to do this, but I asked in Discord and someone
|
||||
explained to me how I could get a working package from [https://github.com/NixOS/nixpkgs/][13] and build it. So here
|
||||
are those instructions:
|
||||
Before I started working on my `paperjam` package, I wanted to build an example existing package just to make sure I understood the process for building a package. I was really struggling to figure out how to do this, but I asked in Discord and someone explained to me how I could get a working package from [https://github.com/NixOS/nixpkgs/][13] and build it. So here are those instructions:
|
||||
|
||||
**step 1:** Download some arbitrary package from [nixpkgs][13] on github, for example the `dash` package:
|
||||
|
||||
@ -190,8 +156,7 @@ are those instructions:
|
||||
wget https://raw.githubusercontent.com/NixOS/nixpkgs/47993510dcb7713a29591517cb6ce682cc40f0ca/pkgs/shells/dash/default.nix -O dash.nix
|
||||
```
|
||||
|
||||
**step 2**: Replace the first statement (`{ lib , stdenv , buildPackages , autoreconfHook , pkg-config , fetchurl , fetchpatch , libedit , runCommand , dash }:` with `with import <nixpkgs> {};` I don’t know why you have to do this,
|
||||
but it works.
|
||||
**step 2**: Replace the first statement (`{ lib , stdenv , buildPackages , autoreconfHook , pkg-config , fetchurl , fetchpatch , libedit , runCommand , dash }:` with `with import <nixpkgs> {};` I don’t know why you have to do this, but it works.
|
||||
|
||||
**step 3**: Run `nix-build dash.nix`
|
||||
|
||||
@ -207,11 +172,7 @@ That’s all! Once I’d done that, I felt like I could modify the `dash` packag
|
||||
|
||||
`paperjam` has one dependency (`libpaper`) that also isn’t packaged yet, so I needed to build `libpaper` first.
|
||||
|
||||
Here’s `libpaper.nix`. I basically just wrote this by copying and pasting from
|
||||
other packages in the [nixpkgs][13] repository.
|
||||
My guess is what’s happening here is that nix has some default rules for
|
||||
compiling C packages (like “run `make install`”), so the `make install` happens
|
||||
default and I don’t need to configure it explicitly.
|
||||
Here’s `libpaper.nix`. I basically just wrote this by copying and pasting from other packages in the [nixpkgs][13] repository. My guess is what’s happening here is that nix has some default rules for compiling C packages (like “run `make install`”), so the `make install` happens default and I don’t need to configure it explicitly.
|
||||
|
||||
```
|
||||
with import <nixpkgs> {};
|
||||
@ -249,10 +210,7 @@ Next, I needed to compile `paperjam`. Here’s a link to the [nix package I wrot
|
||||
|
||||
I set the hashes by first leaving the hash empty, then running `nix-build` to get an error message complaining about a mismatched hash. Then I copied the correct hash out of the error message.
|
||||
|
||||
I figured out how to set `installFlags` just by running `rg PREFIX`
|
||||
in the nixpkgs repository – I figured that needing to set a `PREFIX` was
|
||||
pretty common and someone had probably done it before, and I was right. So I
|
||||
just copied and pasted that line from another package.
|
||||
I figured out how to set `installFlags` just by running `rg PREFIX` in the nixpkgs repository – I figured that needing to set a `PREFIX` was pretty common and someone had probably done it before, and I was right. So I just copied and pasted that line from another package.
|
||||
|
||||
Then I ran:
|
||||
|
||||
@ -265,29 +223,17 @@ and then everything worked and I had `paperjam` installed! Hooray!
|
||||
|
||||
#### next goal: install a 5-year-old version of hugo
|
||||
|
||||
Right now I build this blog using Hugo 0.40, from 2018. I don’t need any new
|
||||
features so I haven’t felt a need to upgrade. On Linux this is easy: Hugo’s
|
||||
releases are a static binary, so I can just download the 5-year-old binary from
|
||||
the [releases page][17] and
|
||||
run it. Easy!
|
||||
Right now I build this blog using Hugo 0.40, from 2018. I don’t need any new features so I haven’t felt a need to upgrade. On Linux this is easy: Hugo’s releases are a static binary, so I can just download the 5-year-old binary from the [releases page][17] and run it. Easy!
|
||||
|
||||
But on this Mac I ran into some complications. Mac hardware has changed in the
|
||||
last 5 years, so the Mac Hugo binary I downloaded crashed. And when I tried to
|
||||
build it from source with `go build`, that didn’t work either because Go build
|
||||
norms have changed in the last 5 years as well.
|
||||
But on this Mac I ran into some complications. Mac hardware has changed in the last 5 years, so the Mac Hugo binary I downloaded crashed. And when I tried to build it from source with `go build`, that didn’t work either because Go build norms have changed in the last 5 years as well.
|
||||
|
||||
I was working around this by running Hugo in a Linux docker container, but I
|
||||
didn’t love that: it was kind of slow and it felt silly. It shouldn’t be that
|
||||
hard to compile one Go program!
|
||||
I was working around this by running Hugo in a Linux docker container, but I didn’t love that: it was kind of slow and it felt silly. It shouldn’t be that hard to compile one Go program!
|
||||
|
||||
Nix to the rescue! Here’s what I did to install the old version of Hugo with
|
||||
nix.
|
||||
Nix to the rescue! Here’s what I did to install the old version of Hugo with nix.
|
||||
|
||||
#### installing Hugo 0.40 with nix
|
||||
|
||||
I wanted to install Hugo 0.40 and put it in my PATH as `hugo-0.40`. Here’s how
|
||||
I did it. I did this in a kind of weird way, but it worked ([Searching and installing old versions of Nix packages][18]
|
||||
describes a probably more normal method).
|
||||
I wanted to install Hugo 0.40 and put it in my PATH as `hugo-0.40`. Here’s how I did it. I did this in a kind of weird way, but it worked ([Searching and installing old versions of Nix packages][18] describes a probably more normal method).
|
||||
|
||||
**step 1**: Search through the nixpkgs repo to find Hugo 0.40
|
||||
|
||||
@ -318,33 +264,19 @@ I figured out how to run this by running `rg 'mv '` in the nixpkgs repository an
|
||||
|
||||
I installed into my `~/.nix-profile/bin` by running `nix-env -i -f hugo.nix`.
|
||||
|
||||
And it all works! I put the final `.nix` file into my own personal [nixpkgs repo][20] so that I can use it again later if I
|
||||
want.
|
||||
And it all works! I put the final `.nix` file into my own personal [nixpkgs repo][20] so that I can use it again later if I want.
|
||||
|
||||
#### reproducible builds aren’t magic, they’re really hard
|
||||
|
||||
I think it’s worth noting here that this `hugo.nix` file isn’t magic – the
|
||||
reason I can easily compile Hugo 0.40 today is that many people worked for a long time to make it possible to
|
||||
package that version of Hugo in a reproducible way.
|
||||
I think it’s worth noting here that this `hugo.nix` file isn’t magic – the reason I can easily compile Hugo 0.40 today is that many people worked for a long time to make it possible to package that version of Hugo in a reproducible way.
|
||||
|
||||
#### that’s all!
|
||||
|
||||
Installing `paperjam` and this 5-year-old version of Hugo were both
|
||||
surprisingly painless and actually much easier than compiling it without nix,
|
||||
because nix made it much easier for me to compile the `paperjam` package with
|
||||
the right version of `libiconv`, and because someone 5 years ago had already
|
||||
gone to the trouble of listing out the exact dependencies for Hugo.
|
||||
Installing `paperjam` and this 5-year-old version of Hugo were both surprisingly painless and actually much easier than compiling it without nix, because nix made it much easier for me to compile the `paperjam` package with the right version of `libiconv`, and because someone 5 years ago had already gone to the trouble of listing out the exact dependencies for Hugo.
|
||||
|
||||
I don’t have any plans to get much more complicated with nix (and it’s still
|
||||
very possible I’ll get frustrated with it and go back to homebrew!), but we’ll
|
||||
see what happens! I’ve found it much easier to start in a simple way and then
|
||||
start using more features if I feel the need instead of adopting a whole bunch
|
||||
of complicated stuff all at once.
|
||||
I don’t have any plans to get much more complicated with nix (and it’s still very possible I’ll get frustrated with it and go back to homebrew!), but we’ll see what happens! I’ve found it much easier to start in a simple way and then start using more features if I feel the need instead of adopting a whole bunch of complicated stuff all at once.
|
||||
|
||||
I probably won’t use nix on Linux – I’ve always been happy enough with `apt`
|
||||
(on Debian-based distros) and `pacman` (on Arch-based distros), and they’re
|
||||
much less confusing. But on a Mac it seems like it might be worth it. We’ll
|
||||
see! It’s very possible in 3 months I’ll get frustrated with nix and just go back to homebrew.
|
||||
I probably won’t use nix on Linux – I’ve always been happy enough with `apt` (on Debian-based distros) and `pacman` (on Arch-based distros), and they’re much less confusing. But on a Mac it seems like it might be worth it. We’ll see! It’s very possible in 3 months I’ll get frustrated with nix and just go back to homebrew.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
How do Nix builds work?
|
||||
======
|
||||
|
||||
Hello! For some reason after the last [nix post][1] I got nerdsniped by trying to understand how Nix builds
|
||||
work under the hood, so here’s a quick exploration I did today. There are probably some mistakes in here.
|
||||
Hello! For some reason after the last [nix post][1] I got nerdsniped by trying to understand how Nix builds work under the hood, so here’s a quick exploration I did today. There are probably some mistakes in here.
|
||||
|
||||
I started by [complaining on Mastodon][2]:
|
||||
|
||||
@ -31,24 +30,18 @@ complicated C program.
|
||||
|
||||
#### the goal: compile a C program, without using Nix’s standard machinery
|
||||
|
||||
Our goal is to compile a C program called `paperjam`. This is a real C program
|
||||
that wasn’t in the Nix repository already. I already figured out how to
|
||||
compile it in [this post][1] by copying and pasting a bunch of stuff I didn’t understand, but this time I wanted to do
|
||||
it in a more principled way where I actually understand more of the steps.
|
||||
Our goal is to compile a C program called `paperjam`. This is a real C program that wasn’t in the Nix repository already. I already figured out how to
|
||||
compile it in [this post][1] by copying and pasting a bunch of stuff I didn’t understand, but this time I wanted to do it in a more principled way where I actually understand more of the steps.
|
||||
|
||||
We’re going to avoid using most of Nix’s helpers for compiling C programs.
|
||||
|
||||
The plan is to start with an almost empty build script, and then resolve errors
|
||||
until we have a working build.
|
||||
The plan is to start with an almost empty build script, and then resolve errors until we have a working build.
|
||||
|
||||
#### first: what’s a derivation?
|
||||
|
||||
I said that we weren’t going to talk about too many Nix abstractions (and we won’t!), but understanding what a derivation is really helped me.
|
||||
|
||||
Everything I read about Nix talks about derivations all the time, but I was
|
||||
really struggling to figure out what a derivation _is_. It turns out that `derivation`
|
||||
is a function in the Nix language. But not just any function! The whole point of the Nix language seems to be to
|
||||
to call this function. The [official documentation for the `derivation` function][5] is actually extremely clear. Here’s what I took away:
|
||||
Everything I read about Nix talks about derivations all the time, but I was really struggling to figure out what a derivation _is_. It turns out that `derivation` is a function in the Nix language. But not just any function! The whole point of the Nix language seems to be to to call this function. The [official documentation for the `derivation` function][5] is actually extremely clear. Here’s what I took away:
|
||||
|
||||
`derivation` takes a bunch of keys and values as input. There are 3 required keys:
|
||||
|
||||
@ -56,8 +49,7 @@ to call this function. The [official documentation for the `derivation` function
|
||||
- `name`: the name of the package you’re building
|
||||
- `builder`: a program (usually a bash script) that runs the build
|
||||
|
||||
Every other key is an arbitrary string that gets passed as an environment
|
||||
variable to the `builder` shell script.
|
||||
Every other key is an arbitrary string that gets passed as an environment variable to the `builder` shell script.
|
||||
|
||||
#### derivations automatically build all their inputs
|
||||
|
||||
@ -69,15 +61,12 @@ Nix will:
|
||||
- put the resulting output directory somewhere like `/nix/store/4garxzr1rpdfahf374i9p9fbxnx56519-qpdf-11.1.0`
|
||||
- expand `pkgs.qpdf` into that output directory (as a string), so that I can reference it in my build script
|
||||
|
||||
The derivation function does some other things (described in the
|
||||
[documentation][5]), but “it builds all of its inputs” is all we really need to know
|
||||
The derivation function does some other things (described in the [documentation][5]), but “it builds all of its inputs” is all we really need to know
|
||||
for now.
|
||||
|
||||
#### step 1: write a derivation file
|
||||
|
||||
Let’s write a very simple build script and call the `derivation` function. These don’t work yet,
|
||||
but I found it pretty fun to go through all the errors, fix them one at a time,
|
||||
and learn a little more about how Nix works by fixing them.
|
||||
Let’s write a very simple build script and call the `derivation` function. These don’t work yet, but I found it pretty fun to go through all the errors, fix them one at a time, and learn a little more about how Nix works by fixing them.
|
||||
|
||||
Here’s the build script (`build_paperjam.sh`). This just unpacks the tarball and runs `make install`.
|
||||
|
||||
@ -115,9 +104,7 @@ The main things here are:
|
||||
|
||||
#### problem 1: tar: command not found
|
||||
|
||||
Nix needs you to declare all the dependencies for your builds. It forces this
|
||||
by removing your `PATH` environment variable so that you have no binaries in
|
||||
your PATH at all.
|
||||
Nix needs you to declare all the dependencies for your builds. It forces this by removing your `PATH` environment variable so that you have no binaries in your PATH at all.
|
||||
|
||||
This is pretty easy to fix: we just need to edit our `PATH`.
|
||||
|
||||
@ -150,11 +137,9 @@ The next error was:
|
||||
> #include <qpdf/QPDF.hh>
|
||||
```
|
||||
|
||||
Makes sense: everything is isolated, so it can’t access my system header files.
|
||||
Figuring out how to handle this was a little more confusing though.
|
||||
Makes sense: everything is isolated, so it can’t access my system header files. Figuring out how to handle this was a little more confusing though.
|
||||
|
||||
It turns out that the way Nix handles header files is that it has a shell
|
||||
script wrapper around `clang`. So when you run `clang++`, you’re actually
|
||||
It turns out that the way Nix handles header files is that it has a shell script wrapper around `clang`. So when you run `clang++`, you’re actually
|
||||
running a shell script.
|
||||
|
||||
On my system, the `clang++` wrapper script was at `/nix/store/d929v59l9a3iakvjccqpfqckqa0vflyc-clang-wrapper-11.1.0/bin/clang++`. I searched that file for `LDFLAGS` and found that it uses 2 environment variables:
|
||||
@ -194,22 +179,15 @@ Here’s the next error:
|
||||
|
||||
I started by adding `-L ${pkgs.libiconv}/lib` to my `NIX_LDFLAGS` environment variable, but that didn’t fix it. Then I spent a while going around in circles and being confused.
|
||||
|
||||
I eventually figured out how to fix this by taking a working version of the `paperjam` build that I’d made before
|
||||
and editing my `clang++` wrapper file to print out all of its environment
|
||||
variables. The `LDFLAGS` environment variable in the working version was different from mine: it had `-liconv` in it.
|
||||
I eventually figured out how to fix this by taking a working version of the `paperjam` build that I’d made before and editing my `clang++` wrapper file to print out all of its environment variables. The `LDFLAGS` environment variable in the working version was different from mine: it had `-liconv` in it.
|
||||
|
||||
So I added `-liconv` to `NIX_LDFLAGS` as well and that fixed it.
|
||||
|
||||
#### why doesn’t the original Makefile have -liconv?
|
||||
|
||||
I was a bit puzzled by this `-liconv` thing though: the original Makefile links
|
||||
in `libqpdf` and `libpaper` by passing `-lqpdf -lpaper`. So why doesn’t it link in iconv, if it requires the
|
||||
iconv library?
|
||||
I was a bit puzzled by this `-liconv` thing though: the original Makefile links in `libqpdf` and `libpaper` by passing `-lqpdf -lpaper`. So why doesn’t it link in iconv, if it requires the iconv library?
|
||||
|
||||
I think the reason for this is that the original Makefile assumed that you were
|
||||
running on Linux and using glibc, and glibc includes these iconv functions by
|
||||
default. But I guess Mac OS libc doesn’t include iconv, so we need to
|
||||
explicitly set the linker flag `-liconv` to add the iconv library.
|
||||
I think the reason for this is that the original Makefile assumed that you were running on Linux and using glibc, and glibc includes these iconv functions by default. But I guess Mac OS libc doesn’t include iconv, so we need to explicitly set the linker flag `-liconv` to add the iconv library.
|
||||
|
||||
#### problem 6: missing codesign_allocate
|
||||
|
||||
@ -219,8 +197,7 @@ Time for the next error:
|
||||
libc++abi: terminating with uncaught exception of type std::runtime_error: Failed to spawn codesign_allocate: No such file or directory
|
||||
```
|
||||
|
||||
I guess this is some kind of Mac code signing thing. I used `find /nix/store -name codesign_allocate` to find `codesign_allocate` on my system. It’s at
|
||||
`/nix/store/a17dwfwqj5ry734zfv3k1f5n37s4wxns-cctools-binutils-darwin-973.0.1/bin/codesign_allocate`.
|
||||
I guess this is some kind of Mac code signing thing. I used `find /nix/store -name codesign_allocate` to find `codesign_allocate` on my system. It’s at `/nix/store/a17dwfwqj5ry734zfv3k1f5n37s4wxns-cctools-binutils-darwin-973.0.1/bin/codesign_allocate`.
|
||||
|
||||
But this doesn’t tell us what the package is called – we need to be able to refer to it as `${pkgs.XXXXXXX}` and `${pkgs.cctools-binutils-darwin}` doesn’t work.
|
||||
|
||||
@ -289,8 +266,7 @@ make install PREFIX="$out"
|
||||
|
||||
#### let’s look at our compiled derivation!
|
||||
|
||||
Now that we understand this configuration a little better, let’s talk about
|
||||
what `nix-build` is doing a little more.
|
||||
Now that we understand this configuration a little better, let’s talk about what `nix-build` is doing a little more.
|
||||
|
||||
Behind the scenes, `nix-build paperjam.nix` actually runs `nix-instantiate` and `nix-store --realize`:
|
||||
|
||||
@ -300,11 +276,7 @@ $ nix-instantiate paperjam.nix
|
||||
$ nix-store --realize /nix/store/xp8kibpll55s0bm40wlpip51y7wnpfs0-paperjam-fake.drv
|
||||
```
|
||||
|
||||
I think what this means is that `paperjam.nix` get compiled to some
|
||||
intermediate representation (also called a derivation?), and then the Nix
|
||||
runtime takes over and is in charge of actually running the build scripts.
|
||||
|
||||
We can look at this `.drv` intermediate representation with `nix show-derivation`
|
||||
I think what this means is that `paperjam.nix` get compiled to some intermediate representation (also called a derivation?), and then the Nix runtime takes over and is in charge of actually running the build scripts. We can look at this `.drv` intermediate representation with `nix show-derivation`
|
||||
|
||||
```
|
||||
{
|
||||
@ -345,13 +317,11 @@ We can look at this `.drv` intermediate representation with `nix show-derivation
|
||||
}
|
||||
```
|
||||
|
||||
This feels surprisingly easy to understand – you can see that there are a
|
||||
bunch of environment variables, our bash script, and the paths to our inputs.
|
||||
This feels surprisingly easy to understand – you can see that there are a bunch of environment variables, our bash script, and the paths to our inputs.
|
||||
|
||||
#### the compilation helpers we’re not using: stdenv
|
||||
|
||||
Normally when you build a package with Nix, you don’t do all of this stuff
|
||||
yourself. Instead, you use a helper called `stdenv`, which seems to have two parts:
|
||||
Normally when you build a package with Nix, you don’t do all of this stuff yourself. Instead, you use a helper called `stdenv`, which seems to have two parts:
|
||||
|
||||
- a function called `stdenv.mkDerivation` which takes some arguments and generates a bunch of environment variables (it seems to be [documented here][6])
|
||||
- a 1600-line bash build script ([setup.sh][7]) that consumes those environment variables. This is like our `build-paperjam.sh`, but much more generalized.
|
||||
@ -370,8 +340,7 @@ and probably lots more useful things I don’t know about yet
|
||||
|
||||
#### let’s look at the derivation for jq
|
||||
|
||||
Let’s look at one more compiled derivation, for `jq`. This is quite long but there
|
||||
are some interesting things in here. I wanted to look at this because I wanted to see what a more typical derivation generated by `stdenv.mkDerivation` looked like.
|
||||
Let’s look at one more compiled derivation, for `jq`. This is quite long but there are some interesting things in here. I wanted to look at this because I wanted to see what a more typical derivation generated by `stdenv.mkDerivation` looked like.
|
||||
|
||||
```
|
||||
$ nix show-derivation /nix/store/q9cw5rp0ibpl6h4i2qaq0vdjn4pyms3p-jq-1.6.drv
|
||||
@ -451,8 +420,7 @@ $ nix show-derivation /nix/store/q9cw5rp0ibpl6h4i2qaq0vdjn4pyms3p-jq-1.6.drv
|
||||
}
|
||||
```
|
||||
|
||||
I thought it was interesting that some of the environment variables in here are actually bash scripts themselves – for example the `postInstallCheck` environment variable is a bash script.
|
||||
Those bash script environment variables are `eval`ed in the main bash script (you can [see that happening in setup.sh here][8])
|
||||
I thought it was interesting that some of the environment variables in here are actually bash scripts themselves – for example the `postInstallCheck` environment variable is a bash script. Those bash script environment variables are `eval`ed in the main bash script (you can [see that happening in setup.sh here][8])
|
||||
|
||||
The `postInstallCheck` environment variable in this particular derivation starts like this:
|
||||
|
||||
@ -469,11 +437,7 @@ All of my compiler experiments used about 3GB of disk space, but `nix-collect-ga
|
||||
|
||||
#### let’s recap the process!
|
||||
|
||||
I feel like I understand Nix a bit better after going through this. I still
|
||||
don’t feel very motivated to learn the Nix language, but now I have some
|
||||
idea of what Nix programs are actually doing under the hood!
|
||||
|
||||
My understanding is:
|
||||
I feel like I understand Nix a bit better after going through this. I still don’t feel very motivated to learn the Nix language, but now I have some idea of what Nix programs are actually doing under the hood! My understanding is:
|
||||
|
||||
- First, `.nix` files get compiled into a `.drv` file, which is mostly a bunch of inputs and outputs and environment variables. This is where the Nix language stops being relevant.
|
||||
- Then all the environment variables get passed to a build script, which is in charge of doing the actual build
|
||||
|
@ -10,9 +10,7 @@
|
||||
Some possible reasons for 8-bit bytes
|
||||
======
|
||||
|
||||
I’ve been working on a zine about how computers represent thing in binary, and
|
||||
one question I’ve gotten a few times is – why does the x86 architecture use 8-bit bytes? Why not
|
||||
some other size?
|
||||
I’ve been working on a zine about how computers represent thing in binary, and one question I’ve gotten a few times is – why does the x86 architecture use 8-bit bytes? Why not some other size?
|
||||
|
||||
With any question like this, I think there are two options:
|
||||
|
||||
@ -20,34 +18,18 @@ With any question like this, I think there are two options:
|
||||
- 8 bits is objectively the Best Option for some reason, even if history had played out differently we would still use 8-bit bytes
|
||||
- some mix of 1 & 2
|
||||
|
||||
I’m not super into computer history (I like to use computers a lot more than I
|
||||
like reading about them), but I am always curious if there’s an essential
|
||||
reason for why a computer thing is the way it is today, or whether it’s mostly
|
||||
a historical accident. So we’re going to talk about some computer history.
|
||||
I’m not super into computer history (I like to use computers a lot more than I like reading about them), but I am always curious if there’s an essential reason for why a computer thing is the way it is today, or whether it’s mostly a historical accident. So we’re going to talk about some computer history.
|
||||
|
||||
As an example of a historical accident: DNS has a `class` field which has 5
|
||||
possible values (“internet”, “chaos”, “hesiod”, “none”, and “any”). To me that’s
|
||||
a clear example of a historical accident – I can’t imagine that we’d define
|
||||
the class field the same way if we could redesign DNS today without worrying about backwards compatibility. I’m
|
||||
not sure if we’d use a class field at all!
|
||||
As an example of a historical accident: DNS has a `class` field which has 5 possible values (“internet”, “chaos”, “hesiod”, “none”, and “any”). To me that’s a clear example of a historical accident – I can’t imagine that we’d define the class field the same way if we could redesign DNS today without worrying about backwards compatibility. I’m not sure if we’d use a class field at all!
|
||||
|
||||
There aren’t any definitive answers in this post, but I asked [on Mastodon][1] and
|
||||
here are some potential reasons I found for the 8-bit byte. I think the answer
|
||||
is some combination of these reasons.
|
||||
There aren’t any definitive answers in this post, but I asked [on Mastodon][1] and here are some potential reasons I found for the 8-bit byte. I think the answer is some combination of these reasons.
|
||||
|
||||
#### what’s the difference between a byte and a word?
|
||||
|
||||
First, this post talks about “bytes” and “words” a lot. What’s the difference between a byte and a word? My understanding is:
|
||||
|
||||
- the **byte size** is the smallest unit you can address. For example in a program on my machine `0x20aa87c68` might be the address of one byte, then `0x20aa87c69` is the address of the next byte.
|
||||
- The **word size** is some multiple of the byte size. I’ve been confused about
|
||||
this for years, and the Wikipedia definition is incredibly vague (“a word is
|
||||
the natural unit of data used by a particular processor design”). I
|
||||
originally thought that the word size was the same as your register size (64
|
||||
bits on x86-64). But according to section 4.1 (“Fundamental Data Types”) of the [Intel architecture manual][2],
|
||||
on x86 a word is 16 bits even though the registers are 64 bits. So I’m
|
||||
confused – is a word on x86 16 bits or 64 bits? Can it mean both, depending
|
||||
on the context? What’s the deal?
|
||||
- The **word size** is some multiple of the byte size. I’ve been confused about this for years, and the Wikipedia definition is incredibly vague (“a word is the natural unit of data used by a particular processor design”). I originally thought that the word size was the same as your register size (64 bits on x86-64). But according to section 4.1 (“Fundamental Data Types”) of the [Intel architecture manual][2], on x86 a word is 16 bits even though the registers are 64 bits. So I’m confused – is a word on x86 16 bits or 64 bits? Can it mean both, depending on the context? What’s the deal?
|
||||
|
||||
Now let’s talk about some possible reasons that we use 8-bit bytes!
|
||||
|
||||
@ -65,18 +47,11 @@ Here’s a [video interview with Fred Brooks (who managed the project)][4] talki
|
||||
> My most important technical decision in my IBM career was to go with the 8-bit byte for the 360.
|
||||
> And on the basis of I believe character processing was going to become important as opposed to decimal digits.
|
||||
|
||||
It makes sense that an 8-bit byte would be better for text processing: 2^6 is
|
||||
64, so 6 bits wouldn’t be enough for lowercase letters, uppercase letters, and symbols.
|
||||
It makes sense that an 8-bit byte would be better for text processing: 2^6 is 64, so 6 bits wouldn’t be enough for lowercase letters, uppercase letters, and symbols.
|
||||
|
||||
To go with the 8-bit byte, System/360 also introduced the [EBCDIC][5] encoding, which is an 8-bit character encoding.
|
||||
|
||||
It looks like the next important machine in 8-bit-byte history was the
|
||||
[Intel 8008][6], which was built to be
|
||||
used in a computer terminal (the Datapoint 2200). Terminals need to be able to
|
||||
represent letters as well as terminal control codes, so it makes sense for them
|
||||
to use an 8-bit byte.
|
||||
[This Datapoint 2200 manual from the Computer History Museum][7]
|
||||
says on page 7 that the Datapoint 2200 supported ASCII (7 bit) and EBCDIC (8 bit).
|
||||
It looks like the next important machine in 8-bit-byte history was the [Intel 8008][6], which was built to be used in a computer terminal (the Datapoint 2200). Terminals need to be able to represent letters as well as terminal control codes, so it makes sense for them to use an 8-bit byte. [This Datapoint 2200 manual from the Computer History Museum][7] says on page 7 that the Datapoint 2200 supported ASCII (7 bit) and EBCDIC (8 bit).
|
||||
|
||||
#### why was the 6-bit byte better for scientific computing?
|
||||
|
||||
@ -90,14 +65,11 @@ I was curious about this comment that the 6-bit byte would be better for scienti
|
||||
> you to lose some of the information more rapidly than you would with binary
|
||||
> shifting
|
||||
|
||||
I don’t understand this comment at all – why does the exponent have to be 8 bits
|
||||
if you use a 32-bit word size? Why couldn’t you use 9 bits or 10 bits if you
|
||||
wanted? But it’s all I could find in a quick search.
|
||||
I don’t understand this comment at all – why does the exponent have to be 8 bits if you use a 32-bit word size? Why couldn’t you use 9 bits or 10 bits if you wanted? But it’s all I could find in a quick search.
|
||||
|
||||
#### why did mainframes use 36 bits?
|
||||
|
||||
Also related to the 6-bit byte: a lot of mainframes used a 36-bit word size. Why? Someone pointed out
|
||||
that there’s a great explanation in the Wikipedia article on [36-bit computing][9]:
|
||||
Also related to the 6-bit byte: a lot of mainframes used a 36-bit word size. Why? Someone pointed out that there’s a great explanation in the Wikipedia article on [36-bit computing][9]:
|
||||
|
||||
> Prior to the introduction of computers, the state of the art in precision
|
||||
> scientific and engineering calculation was the ten-digit, electrically powered,
|
||||
@ -111,23 +83,16 @@ that there’s a great explanation in the Wikipedia article on [36-bit computing
|
||||
|
||||
So this 36 bit thing seems to based on the fact that log_2(20000000000) is 34.2. Huh.
|
||||
|
||||
My guess is that the reason for this is in the 50s, computers were
|
||||
extremely expensive. So if you wanted your computer to support ten decimal
|
||||
digits, you’d design so that it had exactly enough bits to do that, and no
|
||||
more.
|
||||
My guess is that the reason for this is in the 50s, computers were extremely expensive. So if you wanted your computer to support ten decimal
|
||||
digits, you’d design so that it had exactly enough bits to do that, and no more.
|
||||
|
||||
Today computers are way faster and cheaper, so if you want to represent ten
|
||||
decimal digits for some reason you can just use 64 bits – wasting a little bit
|
||||
of space is usually no big deal.
|
||||
Today computers are way faster and cheaper, so if you want to represent ten decimal digits for some reason you can just use 64 bits – wasting a little bit of space is usually no big deal.
|
||||
|
||||
Someone else mentioned that some of these machines with 36-bit word sizes let
|
||||
you choose a byte size – you could use 5 or 6 or 7 or 8-bit bytes, depending
|
||||
on the context.
|
||||
Someone else mentioned that some of these machines with 36-bit word sizes let you choose a byte size – you could use 5 or 6 or 7 or 8-bit bytes, depending on the context.
|
||||
|
||||
#### reason 2: to work well with binary-coded decimal
|
||||
|
||||
In the 60s, there was a popular integer encoding called binary-coded decimal (or [BCD][10] for short) that
|
||||
encoded every decimal digit in 4 bits.
|
||||
In the 60s, there was a popular integer encoding called binary-coded decimal (or [BCD][10] for short) that encoded every decimal digit in 4 bits.
|
||||
|
||||
For example, if you wanted to encode the number 1234, in BCD that would be something like:
|
||||
|
||||
@ -135,49 +100,32 @@ For example, if you wanted to encode the number 1234, in BCD that would be somet
|
||||
0001 0010 0011 0100
|
||||
```
|
||||
|
||||
So if you want to be able to easily work with binary-coded decimal, your byte
|
||||
size should be a multiple of 4 bits, like 8 bits!
|
||||
So if you want to be able to easily work with binary-coded decimal, your byte size should be a multiple of 4 bits, like 8 bits!
|
||||
|
||||
#### why was BCD popular?
|
||||
|
||||
This integer representation seemed really weird to me – why not just use
|
||||
binary, which is a much more efficient way to store integers? Efficiency was really important in early computers!
|
||||
This integer representation seemed really weird to me – why not just use binary, which is a much more efficient way to store integers? Efficiency was really important in early computers!
|
||||
|
||||
My best guess about why is that early computers didn’t have displays the same way we do
|
||||
now, so the contents of a byte were mapped directly to on/off lights.
|
||||
My best guess about why is that early computers didn’t have displays the same way we do now, so the contents of a byte were mapped directly to on/off lights.
|
||||
|
||||
Here’s a [picture from Wikipedia of an IBM 650 with some lights on its display][11] ([CC BY-SA 3.0][12]):
|
||||
|
||||
![][13]
|
||||
|
||||
So if you want people to be relatively able to easily read off a decimal number
|
||||
from its binary representation, this makes a lot more sense. I think today BCD
|
||||
is obsolete because we have displays and our computers can convert numbers
|
||||
represented in binary to decimal for us and display them.
|
||||
So if you want people to be relatively able to easily read off a decimal number from its binary representation, this makes a lot more sense. I think today BCD is obsolete because we have displays and our computers can convert numbers represented in binary to decimal for us and display them.
|
||||
|
||||
Also, I wonder if BCD is where the term “nibble” for 4 bits comes from – in
|
||||
the context of BCD, you end up referring to half bytes a lot (because every
|
||||
digits is 4 bits). So it makes sense to have a word for “4 bits”, and people
|
||||
called 4 bits a nibble. Today “nibble” feels to me like an archaic term though –
|
||||
I’ve definitely never used it except as a fun fact (it’s such a fun word!). The Wikipedia article on [nibbles][14] supports this theory:
|
||||
Also, I wonder if BCD is where the term “nibble” for 4 bits comes from – in the context of BCD, you end up referring to half bytes a lot (because every digits is 4 bits). So it makes sense to have a word for “4 bits”, and people called 4 bits a nibble. Today “nibble” feels to me like an archaic term though – I’ve definitely never used it except as a fun fact (it’s such a fun word!). The Wikipedia article on [nibbles][14] supports this theory:
|
||||
|
||||
> The nibble is used to describe the amount of memory used to store a digit of
|
||||
> a number stored in packed decimal format (BCD) within an IBM mainframe.
|
||||
|
||||
Another reason someone mentioned for BCD was **financial calculations**. Today
|
||||
if you want to store a dollar amount, you’ll typically just use an integer
|
||||
amount of cents, and then divide by 100 if you want the dollar part. This is no
|
||||
big deal, division is fast. But apparently in the 70s dividing an integer
|
||||
represented in binary by 100 was very slow, so it was worth it to redesign how
|
||||
you represent your integers to avoid having to divide by 100.
|
||||
Another reason someone mentioned for BCD was **financial calculations**. Today if you want to store a dollar amount, you’ll typically just use an integer amount of cents, and then divide by 100 if you want the dollar part. This is no big deal, division is fast. But apparently in the 70s dividing an integer represented in binary by 100 was very slow, so it was worth it to redesign how you represent your integers to avoid having to divide by 100.
|
||||
|
||||
Okay, enough about BCD.
|
||||
|
||||
#### reason 3: 8 is a power of 2?
|
||||
|
||||
A bunch of people said it’s important for a CPU’s byte size to be a power of 2.
|
||||
I can’t figure out whether this is true or not though, and I wasn’t satisfied with the explanation that “computers use binary so powers of 2 are good”. That seems very plausible but I wanted to dig deeper.
|
||||
And historically there have definitely been lots of machines that used byte sizes that weren’t powers of 2, for example (from [this retro computing stack exchange thread][15]):
|
||||
A bunch of people said it’s important for a CPU’s byte size to be a power of 2. I can’t figure out whether this is true or not though, and I wasn’t satisfied with the explanation that “computers use binary so powers of 2 are good”. That seems very plausible but I wanted to dig deeper. And historically there have definitely been lots of machines that used byte sizes that weren’t powers of 2, for example (from [this retro computing stack exchange thread][15]):
|
||||
|
||||
- Cyber 180 mainframes used 6-bit bytes
|
||||
- the Univac 1100 / 2200 series used a 36-bit word size
|
||||
@ -190,57 +138,31 @@ Some reasons I heard for why powers of 2 are good that I haven’t understood ye
|
||||
|
||||
Reasons that made more sense to me:
|
||||
|
||||
- it makes it easier to design **clock dividers** that can measure “8 bits were
|
||||
sent on this wire” that work based on halving – you can put 3 halving clock
|
||||
dividers in series. [Graham Sutherland][16] told me about this and made this really cool
|
||||
[simulator of clock dividers][17] showing what these clock dividers look like. That site (Falstad) also has a bunch of other example circuits and it seems like a really cool way to make circuit simulators.
|
||||
- if you have an instruction that zeroes out a specific bit in a byte, then if
|
||||
your byte size is 8 (2^3), you can use just 3 bits of your instruction to
|
||||
indicate which bit. x86 doesn’t seem to do this, but the [Z80’s bit testing instructions][18] do.
|
||||
- someone mentioned that some processors use [Carry-lookahead adders][19], and they work
|
||||
in groups of 4 bits. From some quick Googling it seems like there are a wide
|
||||
variety of adder circuits out there though.
|
||||
- **bitmaps**: Your computer’s memory is organized into pages (usually of size 2^n). It
|
||||
needs to keep track of whether every page is free or not. Operating systems
|
||||
use a bitmap to do this, where each bit corresponds to a page and is 0 or 1
|
||||
depending on whether the page is free. If you had a 9-bit byte, you would
|
||||
need to divide by 9 to find the page you’re looking for in the bitmap.
|
||||
Dividing by 9 is slower than dividing by 8, because dividing by powers of 2
|
||||
is always the fastest thing.
|
||||
- it makes it easier to design **clock dividers** that can measure “8 bits were sent on this wire” that work based on halving – you can put 3 halving clock dividers in series. [Graham Sutherland][16] told me about this and made this really cool [simulator of clock dividers][17] showing what these clock dividers look like. That site (Falstad) also has a bunch of other example circuits and it seems like a really cool way to make circuit simulators.
|
||||
- if you have an instruction that zeroes out a specific bit in a byte, then if your byte size is 8 (2^3), you can use just 3 bits of your instruction to indicate which bit. x86 doesn’t seem to do this, but the [Z80’s bit testing instructions][18] do.
|
||||
- someone mentioned that some processors use [Carry-lookahead adders][19], and they work in groups of 4 bits. From some quick Googling it seems like there are a wide variety of adder circuits out there though.
|
||||
- **bitmaps**: Your computer’s memory is organized into pages (usually of size 2^n). It needs to keep track of whether every page is free or not. Operating systems use a bitmap to do this, where each bit corresponds to a page and is 0 or 1 depending on whether the page is free. If you had a 9-bit byte, you would need to divide by 9 to find the page you’re looking for in the bitmap. Dividing by 9 is slower than dividing by 8, because dividing by powers of 2 is always the fastest thing.
|
||||
|
||||
I probably mangled some of those explanations pretty badly: I’m pretty far out
|
||||
of my comfort zone here. Let’s move on.
|
||||
I probably mangled some of those explanations pretty badly: I’m pretty far out of my comfort zone here. Let’s move on.
|
||||
|
||||
#### reason 4: small byte sizes are good
|
||||
|
||||
You might be wondering – well, if 8-bit bytes were better than 4-bit bytes,
|
||||
why not keep increasing the byte size? We could have 16-bit bytes!
|
||||
You might be wondering – well, if 8-bit bytes were better than 4-bit bytes, why not keep increasing the byte size? We could have 16-bit bytes!
|
||||
|
||||
A couple of reasons to keep byte sizes small:
|
||||
|
||||
- It’s a waste of space – a byte is the minimum unit you can address, and if
|
||||
your computer is storing a lot of ASCII text (which only needs 7 bits), it
|
||||
would be a pretty big waste to dedicate 12 or 16 bits to each character when
|
||||
you could use 8 bits instead.
|
||||
- It’s a waste of space – a byte is the minimum unit you can address, and if your computer is storing a lot of ASCII text (which only needs 7 bits), it would be a pretty big waste to dedicate 12 or 16 bits to each character when you could use 8 bits instead.
|
||||
- As bytes get bigger, your CPU needs to get more complex. For example you need one bus line per bit. So I guess simpler is better.
|
||||
|
||||
My understanding of CPU architecture is extremely shaky so I’ll leave it at
|
||||
that. The “it’s a waste of space” reason feels pretty compelling to me though.
|
||||
My understanding of CPU architecture is extremely shaky so I’ll leave it at that. The “it’s a waste of space” reason feels pretty compelling to me though.
|
||||
|
||||
#### reason 5: compatibility
|
||||
|
||||
The Intel 8008 (from 1972) was the precursor to the 8080 (from 1974), which was the precursor to the
|
||||
8086 (from 1976) – the first x86 processor. It seems like the 8080 and the
|
||||
8086 were really popular and that’s where we get our modern x86 computers.
|
||||
The Intel 8008 (from 1972) was the precursor to the 8080 (from 1974), which was the precursor to the 8086 (from 1976) – the first x86 processor. It seems like the 8080 and the 8086 were really popular and that’s where we get our modern x86 computers.
|
||||
|
||||
I think there’s an “if it ain’t broke don’t fix it” thing going on here – I
|
||||
assume that 8-bit bytes were working well, so Intel saw no need to change the
|
||||
design. If you keep the same 8-bit byte, then you can reuse more of your
|
||||
instruction set.
|
||||
I think there’s an “if it ain’t broke don’t fix it” thing going on here – I assume that 8-bit bytes were working well, so Intel saw no need to change the design. If you keep the same 8-bit byte, then you can reuse more of your instruction set.
|
||||
|
||||
Also around the 80s we start getting network protocols like TCP
|
||||
which use 8-bit bytes (usually called “octets”), and if you’re going to be
|
||||
implementing network protocols, you probably want to be using an 8-bit byte.
|
||||
Also around the 80s we start getting network protocols like TCP which use 8-bit bytes (usually called “octets”), and if you’re going to be implementing network protocols, you probably want to be using an 8-bit byte.
|
||||
|
||||
#### that’s all!
|
||||
|
||||
@ -253,29 +175,15 @@ It seems to me like the main reasons for the 8-bit byte are:
|
||||
- 8 is a better number than 7 (because it’s a power of 2)
|
||||
- once you have popular 8-bit computers that are working well, you want to keep the same design for compatibility
|
||||
|
||||
Someone pointed out that [page 65 of this book from 1962][20]
|
||||
talking about IBM’s reasons to choose an 8-bit byte basically says the same thing:
|
||||
Someone pointed out that [page 65 of this book from 1962][20] talking about IBM’s reasons to choose an 8-bit byte basically says the same thing:
|
||||
|
||||
- Its full capacity of 256 characters was considered to be sufficient for the great majority of applications.
|
||||
- Within the limits of this capacity, a single character is represented by a
|
||||
single byte, so that the length of any particular record is not dependent on
|
||||
the coincidence of characters in that record.
|
||||
- 8-bit bytes are reasonably economical of storage space
|
||||
- For purely numerical work, a decimal digit can be represented by only 4
|
||||
bits, and two such 4-bit bytes can be packed in an 8-bit byte. Although such
|
||||
packing of numerical data is not essential, it is a common practice in
|
||||
order to increase speed and storage efficiency. Strictly speaking, 4-bit
|
||||
bytes belong to a different code, but the simplicity of the 4-and-8-bit
|
||||
scheme, as compared with a combination 4-and-6-bit scheme, for example,
|
||||
leads to simpler machine design and cleaner addressing logic.
|
||||
- Byte sizes of 4 and 8 bits, being powers of 2, permit the computer designer
|
||||
to take advantage of powerful features of binary addressing and indexing to
|
||||
the bit level (see Chaps. 4 and 5 ) .
|
||||
> 1. Its full capacity of 256 characters was considered to be sufficient for the great majority of applications.
|
||||
> 2. Within the limits of this capacity, a single character is represented by a single byte, so that the length of any particular record is not dependent on the coincidence of characters in that record.
|
||||
> 3. 8-bit bytes are reasonably economical of storage space
|
||||
> 4. For purely numerical work, a decimal digit can be represented by only 4 bits, and two such 4-bit bytes can be packed in an 8-bit byte. Although such packing of numerical data is not essential, it is a common practice in order to increase speed and storage efficiency. Strictly speaking, 4-bit bytes belong to a different code, but the simplicity of the 4-and-8-bit scheme, as compared with a combination 4-and-6-bit scheme, for example, leads to simpler machine design and cleaner addressing logic.
|
||||
> 5. Byte sizes of 4 and 8 bits, being powers of 2, permit the computer designer to take advantage of powerful features of binary addressing and indexing to the bit level (see Chaps. 4 and 5 ) .
|
||||
|
||||
>
|
||||
|
||||
Overall this makes me feel like an 8-bit byte is a pretty natural choice if
|
||||
you’re designing a binary computer in an English-speaking country.
|
||||
Overall this makes me feel like an 8-bit byte is a pretty natural choice if you’re designing a binary computer in an English-speaking country.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -1,61 +0,0 @@
|
||||
[#]: subject: "Open source tools for mind mapping"
|
||||
[#]: via: "https://opensource.com/article/23/3/open-source-mind-mapping"
|
||||
[#]: author: "Amrita https://opensource.com/users/amrita42"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Open source tools for mind mapping
|
||||
======
|
||||
|
||||
In today's world and social media, many people don't have the patience to read lengthy textual content. Visuals are a great way to capture your audience's attention span.
|
||||
|
||||
Did you know that research at 3M Corporation concluded that visuals are processed 60,000 times faster than text? Visuals are more impactful than words and enhance creative thinking and memory.
|
||||
|
||||
### A picture is worth a thousand words
|
||||
|
||||
I looked at some of the common [Git commands][1]. I used Git commands as the main topic; each sub-topic is a Git command syntax with a definition. For this, I used Wisemapping.
|
||||
|
||||
![A git command mind map][2]
|
||||
|
||||
Whether you knew what a [mind map][3] was before or not, now that you've seen a mind map, you can now understand the concept.. That's the power of visuals.
|
||||
|
||||
### How do you create a mind map?
|
||||
|
||||
- Start with the main topic and place it in the middle of your drawing board.
|
||||
- Create sub-topics and link them to the main topic.
|
||||
- You can add details to each sub-topic, such as definitions, examples, etc.
|
||||
|
||||
### 3 open source tools you can use to create a mind map
|
||||
|
||||
Take a look at these three open source tools to create a visual of your idea:
|
||||
|
||||
- [Wisemapping][4]
|
||||
- [Freeplane][5]
|
||||
- [Semantik][6]
|
||||
|
||||
Wikipedia defines a mind map as a diagram to visually organize information into a hierarchy, showing relationships among pieces of the whole. Mind mapping starts with a central theme and then builds relations. It is a visual way to structure thoughts and create impactful presentations.
|
||||
|
||||
You can use mind maps in your work. For example, I used a mind map to show a high-level overview of features planned for a project. With these excellent open source mind mapping applications, it's easy to get started visualizing your next project. Try mapping your mind with open source.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/3/open-source-mind-mapping
|
||||
|
||||
作者:[Amrita][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/amrita42
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://opensource.com/downloads/cheat-sheet-git
|
||||
[2]: https://opensource.com/sites/default/files/2023-03/mindmap.jpg
|
||||
[3]: https://opensource.com/article/21/12/open-source-mind-mapping-drawio
|
||||
[4]: https://www.wisemapping.com/
|
||||
[5]: https://opensource.com/article/19/1/productivity-tool-freeplane
|
||||
[6]: https://waf.io/semantik.html
|
@ -1,72 +0,0 @@
|
||||
[#]: subject: "Measure pi with a Raspberry Pi"
|
||||
[#]: via: "https://opensource.com/article/23/3/measure-pi-raspberry-pi"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Measure pi with a Raspberry Pi
|
||||
======
|
||||
|
||||
March 14th is celebrated around the world as Pi Day. Many people celebrate Pi Day by measuring pi with objects found around the house. I wanted to do something similar for this year's Pi Day using my Raspberry Pi 3B. Read on to learn how I measured pi using my Raspberry Pi.
|
||||
|
||||
What you'll need:
|
||||
|
||||
- Raspberry Pi single-board computer
|
||||
- Graph paper
|
||||
- Ruler with mm and cm measurements
|
||||
- Pen
|
||||
|
||||
### 1. Draw a circle
|
||||
|
||||
Pi is the ratio of the circumference of a circle to its diameter. To calculate pi, we need to measure both the circumference and diameter of a perfectly drawn circle. Fortunately, the Raspberry Pi motherboard has mounting holes that are big enough to fit a pencil or pen. I stuck a pin through one Pi board mounting hole, careful to land the pin on the intersection of two lines on a piece of graph paper.
|
||||
|
||||
Holding the pin still, I inserted a pen in the opposite mounting hole and drew a circle by moving the pen around the pin. The solder points on the underside of the Raspberry Pi motherboard can catch on the paper, but you can draw a good circle if you are careful.
|
||||
|
||||
![Use the Raspberry Pi as a compass to draw a circle.][1]
|
||||
|
||||
### 2. Divide the circle into segments
|
||||
|
||||
Divide the circle in half by drawing a vertical line through the center of the circle and again into quarters by drawing a horizontal line through the circle. When I drew my circle, I placed the pin exactly on the intersection of two lines on the graph paper, which makes finding the vertical and horizontal center lines easy to find. You can create an "eighth" slice by drawing a line across the diagonal.
|
||||
|
||||
![Each small wedge is 1/8 of a circle.][2]
|
||||
|
||||
Further divisions are an exercise with the ruler. I used the ruler to find the midpoint of any two intersections of the "quarter-wedge" and the "one-eighth wedge" to make a 1/16 wedge. You can use the same method to make smaller and smaller slices that are 1/32 and 1/64 of a circle. By being very careful, I was also able to measure a very narrow wedge at 1/128 of a circle:
|
||||
|
||||
![If you are careful, you can keep dividing to find 1/128 of a circle.][3]
|
||||
|
||||
### 3. Estimate the circumference
|
||||
|
||||
My smallest wedge is 1/128 of a circle. With such a small slice, the outer arc of the wedge is so small that we can approximate it with a straight line. This will not actually be 1/128 of the circle's circumference, but it will be close enough that we can use it as a good estimate.
|
||||
|
||||
![Use the mm measurement on your ruler to measure the outer arc of the 1/128 segment.][4]
|
||||
|
||||
Using the mm measurement on my ruler, I measured the outer arc of my 1/128 wedge at 3.8mm. With that, I can estimate the circumference of my circle as 3.8mm times 128, or 486.4mm. To convert to centimeters, divide by ten: **48.64cm**.
|
||||
|
||||
### 4. Calculate pi
|
||||
|
||||
The value of pi is the ratio of the circumference of a circle to its diameter. We estimated the circumference in step 3. Measuring the diameter is a simple exercise of using the ruler to measure across the circle. My circle is **15.4cm**.
|
||||
|
||||
Now that we know the circumference and diameter, we can calculate pi as 48.64 divided by 15.4, which is **3.158**. That's not too far off from the actual value of pi, at 3.141.
|
||||
|
||||
Measuring pi is a fun math exercise! Math fans of all ages can use simple tools such as graph paper, pen, and ruler to measure pi on their own. Use your Raspberry Pi in a fun, new way to draw a circle and measure pi independently. This is an estimate since we are approximating a 1/128 arc on a circle as a straight line, but this gets us close enough without too much effort.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/3/measure-pi-raspberry-pi
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://opensource.com/sites/default/files/2023-03/10000000000003E8000003E8BE7DE71919BB0C82.jpg
|
||||
[2]: https://opensource.com/sites/default/files/2023-03/100000010000028A0000028A0625B218857F031C.webp
|
||||
[3]: https://opensource.com/sites/default/files/2023-03/100000000000079E00000514506C8EE5131D886A.webp
|
||||
[4]: https://opensource.com/sites/default/files/2023-03/10000000000003E8000003E881402FB71F1945FF.jpg
|
@ -2,7 +2,7 @@
|
||||
[#]: via: "https://opensource.com/article/23/4/open-source-collabora-online-interoperability"
|
||||
[#]: author: "Heike Jurzik https://opensource.com/users/hej"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
@ -0,0 +1,284 @@
|
||||
[#]: subject: "Linux Terminal Basics #8: Move Files and Directories (Cut-Paste Operation)"
|
||||
[#]: via: "https://itsfoss.com/move-files-linux/"
|
||||
[#]: author: "Abhishek Prakash https://itsfoss.com/author/abhishek/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Linux Terminal Basics #8: Move Files and Directories (Cut-Paste Operation)
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
Cut, copy and paste are part of everyday computing life.
|
||||
|
||||
In the previous chapter, you learned about [copying files and folders][2] (directories) in the terminal.
|
||||
|
||||
In this part of the Terminal Basics series, you'll learn about the cut-paste operation (moving) in the Linux terminal.
|
||||
|
||||
### Moving or cut-paste?
|
||||
|
||||
Alright! Cut-paste is not the correct technical term here. It is called moving files (and folders).
|
||||
|
||||
Since you are new to the command line, you may find the term 'moving' confusing.
|
||||
|
||||
When you copy a file to another location using the **cp** command, the source file remains in the same location.
|
||||
|
||||
When you move a file to another location **using the mv command**, the source file no longer remains in the origin location.
|
||||
|
||||
This is the same cut-paste operation (Ctrl+X and Ctrl+V) you do in a graphical file explorer.
|
||||
|
||||
> 📋 Basically, moving files in the command line can be thought same as cut-paste in a graphical environment.
|
||||
|
||||
### Moving files
|
||||
|
||||
Linux has a dedicated mv command (short for move) for moving files and directories to other locations.
|
||||
|
||||
And [using the mv command][3] is quite simple:
|
||||
|
||||
```
|
||||
mv source_file destination_directory
|
||||
```
|
||||
|
||||
The role of path comes to play here as well. You can use either the [absolute or relative path][4]. Whichever suits your need.
|
||||
|
||||
Let's see this with an example. **You should practice along with it by replicating the example scenarios on your system**.
|
||||
|
||||
This is the directory structure in the example:
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ tree
|
||||
.
|
||||
├── dir1
|
||||
│ ├── file_2
|
||||
│ └── file_3
|
||||
├── dir2
|
||||
│ └── passwd
|
||||
├── dir3
|
||||
├── file_1
|
||||
├── file_2
|
||||
├── file_3
|
||||
├── file_4
|
||||
├── passwd
|
||||
└── services
|
||||
|
||||
3 directories, 9 files
|
||||
```
|
||||
|
||||
Now, let's say I want to move the `file_1` to `dir3`.
|
||||
|
||||
```
|
||||
mv file_1 dir3
|
||||
```
|
||||
|
||||
![Example of moving files in Linux using the mv command][5]
|
||||
|
||||
#### Moving multiple files
|
||||
|
||||
You can move multiple files to another location in the same mv command:
|
||||
|
||||
```
|
||||
mv file1 file2 fileN destination_directory
|
||||
```
|
||||
|
||||
Let's continue our example scenario to move multiple files.
|
||||
|
||||
```
|
||||
mv file_2 file_3 file_4 dir3
|
||||
```
|
||||
|
||||
![Example of moving multiple files in Linux][6]
|
||||
|
||||
> 🖥️ Move the files back to the current directory from
|
||||
|
||||
```
|
||||
dir3
|
||||
```
|
||||
|
||||
. We need them in the next examples.
|
||||
|
||||
#### Moving files with caution
|
||||
|
||||
If the destination already has files with the same name, the destination files will be replaced immediately. At times, you won't want that.
|
||||
|
||||
Like the cp command, the mv command also has an interactive mode with option `-i`.
|
||||
|
||||
And the purpose is the same. Ask for confirmation before replacing the files at the destination.
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ mv -i file_3 dir1
|
||||
mv: overwrite 'dir1/file_3'?
|
||||
```
|
||||
|
||||
You can press N to deny replacement and Y or Enter to replace the destination file.
|
||||
|
||||
![Example of moving interactively in Linux][7]
|
||||
|
||||
#### Move but only update
|
||||
|
||||
The mv command comes with some special options. One of them is the update option `-u`.
|
||||
|
||||
With this, the destination file will only be replaced if the file being moved is newer than it.
|
||||
|
||||
```
|
||||
mv -u file_name destination_directory
|
||||
```
|
||||
|
||||
Here's an example. file_2 was modified at 10:39 and file_3 was modified at 10:06.
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ ls -l file_2 file_3
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:39 file_2
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:06 file_3
|
||||
```
|
||||
|
||||
In the destination directory dir1, file_2 was last modified at 10:37 and file_3 was modified at 10:39.
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ ls -l dir1
|
||||
total 0
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:37 file_2
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:39 file_3
|
||||
```
|
||||
|
||||
In other words, in the destination directory, the file_2 is older and file_3 is newer than the ones being moved.
|
||||
|
||||
It also means that file_3 won't me moved while as file_2 will be updated. You can verify it with the timestamps of the files in the destination directory after running the mv command.
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ mv -u file_2 file_3 dir1
|
||||
[email protected]:~/moving_files$ ls -l dir1
|
||||
total 0
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:39 file_2
|
||||
-rw-rw-r-- 1 abhishek abhishek 0 Apr 4 10:39 file_3
|
||||
[email protected]:~/moving_files$ date
|
||||
Tue Apr 4 10:41:16 AM IST 2023
|
||||
[email protected]:~/moving_files$
|
||||
```
|
||||
|
||||
As you can see, the move command was executed at 10:41 and only the timestamp of file_2 has been changed.
|
||||
|
||||
![Using move command with update option][8]
|
||||
|
||||
> 💡 You can also use the backup option
|
||||
|
||||
```
|
||||
-b
|
||||
```
|
||||
|
||||
. If the destination file is being replaced, it will automatically create a backup with the
|
||||
|
||||
```
|
||||
filename~
|
||||
```
|
||||
|
||||
pattern.
|
||||
|
||||
#### Troubleshoot: Target is not a directory
|
||||
|
||||
If you are moving multiple files, the last argument must be a directory. Otherwise, you'll encounter this error:
|
||||
|
||||
```
|
||||
target is not a directory
|
||||
```
|
||||
|
||||
Here, I create a file which is named `dir`. The name sounds like a directory, but it is a file. And when I try to move multiple files to it, the obvious error is there:
|
||||
|
||||
![Handling target is not a directory error in Linux][9]
|
||||
|
||||
But what if you move a single file to another file? In that case, the target file is replaced by the source file's content while the source file is renamed as the target file. More on this in later sections.
|
||||
|
||||
### Moving directories
|
||||
|
||||
So far, you have seen everything about moving files. How about moving directories?
|
||||
|
||||
The cp and rm commands used recusrive option -r to copy and delete folders respectively.
|
||||
|
||||
However, there is no such requirement for the mv command. You can use the mv command as it is for moving directories.
|
||||
|
||||
```
|
||||
mv dir target_directory
|
||||
```
|
||||
|
||||
Here's an example where I move the `dir2` directory to `dir3`. And as you can see, `dir2` along with its content is moved to `dir3`.
|
||||
|
||||
![Moving folders in Linux command line][10]
|
||||
|
||||
You can move multiple directories the same way.
|
||||
|
||||
### Rename files and directories
|
||||
|
||||
If you want to rename a file or directory, you can use the same mv command.
|
||||
|
||||
```
|
||||
mv filename new_name_in_same_or_new_location
|
||||
```
|
||||
|
||||
Let's say you want to rename a file in the same location. Here's an example where I rename `file_1` to `file_one` in the same directory.
|
||||
|
||||
![Rename files with mv command][11]
|
||||
|
||||
You can also move and rename the files. You just have to provide the directory path and the file name of the destination. Here, I rename `services` file to `my_services` while moving it to `dir3`.
|
||||
|
||||
```
|
||||
[email protected]:~/moving_files$ ls
|
||||
dir dir1 dir3 file_2 file_3 file_one passwd services
|
||||
[email protected]:~/moving_files$ mv services dir3/my_services
|
||||
[email protected]:~/moving_files$ ls dir3
|
||||
dir2 my_services
|
||||
```
|
||||
|
||||
> 📋 You cannot rename multiple files directly with mv command. You have to combine it with other commands like find etc.
|
||||
|
||||
### Test your knowledge
|
||||
|
||||
Time to practice what you just learned.
|
||||
|
||||
Create a new folder to practice the exercise. In here, create a directory structure like this:
|
||||
|
||||
```
|
||||
.
|
||||
├── dir1
|
||||
├── dir2
|
||||
│ ├── dir21
|
||||
│ ├── dir22
|
||||
│ └── dir23
|
||||
└── dir3
|
||||
```
|
||||
|
||||
Copy the file /etc/passwd to the current directory. Now rename it `secrets`.
|
||||
|
||||
Make three new files named `file_1`, `file_2` and `file_3`. Move all the files to `dir22`.
|
||||
|
||||
Now move the `dir22` directory to `dir3`.
|
||||
|
||||
Delete all contents of `dir2` now.
|
||||
|
||||
In the penultimate chapter of the Terminal Basics series, you'll learn about editing files in the terminal. Stay tuned.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/move-files-linux/
|
||||
|
||||
作者:[Abhishek Prakash][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/abhishek/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://itsfoss.com/content/images/2023/03/linux-mega-packt.webp
|
||||
[2]: https://itsfoss.com/copy-files-directory-linux/
|
||||
[3]: https://linuxhandbook.com/mv-command/?ref=itsfoss.com
|
||||
[4]: https://linuxhandbook.com/absolute-vs-relative-path/?ref=itsfoss.com
|
||||
[5]: https://itsfoss.com/content/images/2023/04/moving-files-linux.png
|
||||
[6]: https://itsfoss.com/content/images/2023/04/moving_multiple_files_linux.png
|
||||
[7]: https://itsfoss.com/content/images/2023/04/move-interactively-linux.png
|
||||
[8]: https://itsfoss.com/content/images/2023/04/move-command-update-option.png
|
||||
[9]: https://itsfoss.com/content/images/2023/04/target-is-not-a-directory-error-linux.png
|
||||
[10]: https://itsfoss.com/content/images/2023/04/moving-directories.png
|
||||
[11]: https://itsfoss.com/content/images/2023/04/rename-file-with-mv-command.png
|
@ -0,0 +1,52 @@
|
||||
[#]: subject: "How to resolve Git merge conflicts"
|
||||
[#]: via: "https://opensource.com/article/23/4/resolve-git-merge-conflicts"
|
||||
[#]: author: "Agil Antony https://opensource.com/users/agantony"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
How to resolve Git merge conflicts
|
||||
======
|
||||
|
||||
Suppose you and I are working on the same file called **index.html**. I make some changes to the file, commit them, and push the changes to the remote Git repository. You also make some changes to the same file, commit them, and start pushing the changes to the same Git repository. However, Git detects a conflict because the changes you made conflict with the changes I made.
|
||||
|
||||
Here's how you can resolve the conflict:
|
||||
|
||||
- Fetch and merge the latest changes from the remote repository:`$ git pull`
|
||||
- Identify the one or more conflicting files:`$ git status`
|
||||
- Open the conflicting file using a text editor:`$ vim index.html`
|
||||
- Resolve the conflict. The conflicting changes are marked by `<<<<<<< HEAD` and `>>>>>>>`. You need to choose which changes to keep and which to discard. Manually edit the file to combine the conflicting changes. Here's an example:`<<<<<<< HEAD
|
||||
<div class="header">
|
||||
<h1>Sample text 1</h1>
|
||||
</div>
|
||||
=======
|
||||
<div class="header">
|
||||
<h1>Sample text 2</h1>
|
||||
</div>
|
||||
>>>>>>> feature-branch`In this example, I changed the website heading to `Sample text 1`, while you have changed the heading to `Sample text 2`. Both changes have been added to the file. You can now decide which heading to keep or edit the file to combine the changes. In either case, remove the markers that indicate the beginning and end of the changes, leaving only the code you want:`<div class="header">
|
||||
<h1>Sample text 2</h1>
|
||||
</div>`
|
||||
- Save all of your changes, and close your editor.
|
||||
- Add the file to the staging area:`$ git add index.html`
|
||||
- Commit the changes:`$ git commit -m "Updated h1 in index.html"`This command commits the changes with the message `Resolved merge conflict`.
|
||||
- Push the changes to the remote repository:`$ git push`
|
||||
|
||||
### Resolution
|
||||
|
||||
Merge conflicts are a good reason to focus your changes on code. The more you change in a file, the greater the potential for conflict. You should make more commits with fewer changes each. You should avoid making a monolithic change that combines multiple feature enhancements or bug fixes into one. Your project manager will thank you, too, because commits with clear intent are easier to track. A Git merge conflict may seem intimidating at first, but now that you know how to do it, you'll see that it's easily resolved.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/resolve-git-merge-conflicts
|
||||
|
||||
作者:[Agil Antony][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/agantony
|
||||
[b]: https://github.com/lkxed/
|
@ -0,0 +1,182 @@
|
||||
[#]: subject: "BASIC vs. FORTRAN 77: Comparing programming blasts from the past"
|
||||
[#]: via: "https://opensource.com/article/23/4/basic-vs-fortran-77"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
BASIC vs. FORTRAN 77: Comparing programming blasts from the past
|
||||
======
|
||||
|
||||
If you grew up with computers in the 1970s and 1980s, as I did, you probably learned a common programming language for personal computers called BASIC, or the Beginner's All-purpose Symbolic Instruction Code. You could find BASIC implementations on every personal computer of the era, including the TRS-80, Apple II, and the IBM PC. Back then, I was a self-taught BASIC programmer, experimenting with AppleSoft BASIC on the Apple II before moving to GW-BASIC on the IBM PC and, later, to QuickBASIC on DOS.
|
||||
|
||||
But once upon a time, a popular language for scientific programming was FORTRAN, short for FORmula TRANslation. Although since the 1990 specification of the language, the name is more commonly stylized as "Fortran."
|
||||
|
||||
When I studied physics as a university undergraduate student in the early 1990s, I leveraged my experience in BASIC to learn FORTRAN 77. That was when I realized that BASIC derived many of its concepts from FORTRAN. To be clear, FORTRAN and BASIC differ in lots of other ways, but I found that knowing a little BASIC helped me to learn FORTRAN programming quickly.
|
||||
|
||||
I want to show some similarities between the two languages by writing the same program in both. I'll explore the `FOR` loop in BASIC and FORTRAN 77 by writing a sample program to add a list of numbers from 1 to 10.
|
||||
|
||||
### Bywater BASIC
|
||||
|
||||
BASIC came in many flavors, depending on your computer, but the overall language remained the same. One version of BASIC that I like is [Bywater BASIC][1], an open source implementation of BASIC available for different platforms, including Linux and DOS.
|
||||
|
||||
To use Bywater BASIC on FreeDOS, you must first [install the package][2] from the FreeDOS 1.3 Bonus CD. To run it, go into the C: directory and type `bwbasic`. This command starts the BASIC interpreter. You can enter your program from this prompt:
|
||||
|
||||
```
|
||||
bwBASIC:
|
||||
```
|
||||
|
||||
Bywater BASIC uses an older BASIC programming standard that requires you to write every program instruction with a line number. Think of a line number like an index. You can easily refer to any instruction in the program with line numbers. As you type the program into the Bywater BASIC interpreter, add the line number before each instruction:
|
||||
|
||||
```
|
||||
bwBASIC: 10 print "Add the numbers from 1 to 10 ..."
|
||||
bwBASIC: 20 sum = 0
|
||||
bwBASIC: 30 for i = 1 to 10
|
||||
bwBASIC: 40 sum = sum + i
|
||||
bwBASIC: 50 next i
|
||||
bwBASIC: 60 print sum
|
||||
bwBASIC: 70 end
|
||||
```
|
||||
|
||||
Use the `list` command to view the program you have entered into the interpreter:
|
||||
|
||||
```
|
||||
bwBASIC: list
|
||||
10 print "Add the numbers from 1 to 10 ..."
|
||||
20 sum = 0
|
||||
30 for i = 1 to 10
|
||||
40 sum = sum + i
|
||||
50 next i
|
||||
60 print sum
|
||||
70 end
|
||||
```
|
||||
|
||||
This short program demonstrates the `FOR` loop in BASIC. `FOR` is the most fundamental loop construct in any programming language, allowing you to iterate over a set of values. The general syntax of the `FOR` loop in Bywater BASIC looks like this:
|
||||
|
||||
```
|
||||
FOR var = start TO end
|
||||
```
|
||||
|
||||
In this example program, the instruction `for i = 1 to 10` starts a loop that iterates through the values 1 to 10. At each pass through the loop, the variable `i` is set to the new value.
|
||||
|
||||
In BASIC, all instructions up to the next instruction are executed as part of the `FOR` loop. Because you can put one `FOR` loop inside another, Bywater BASIC uses the syntax `NEXT variable` to specify which loop variable to iterate.
|
||||
|
||||
Type `run` at the prompt to execute the program:
|
||||
|
||||
```
|
||||
bwBASIC: run
|
||||
Add the numbers from 1 to 10 ...
|
||||
55
|
||||
```
|
||||
|
||||
Bywater BASIC is called a BASIC interpreter because you can only run the program from inside the Bywater BASIC environment. This means the interpreter does all the hard work of interacting with the operating system, so your program doesn't need to do that on its own, with the trade-off that the program runs a little slower in the interpreted environment than it might if it were a compiled program.
|
||||
|
||||
### FreeBASIC
|
||||
|
||||
Another popular implementation of BASIC is [FreeBASIC][3], an open source BASIC compiler for several platforms, including Linux and DOS. To use FreeBASIC, you'll need to install the FreeBASIC package from the FreeDOS 1.3 Bonus CD, then change into the C: directory where you'll find the FreeBASIC programs.
|
||||
|
||||
FreeBASIC is a compiler, so you first create a source file with your program instructions, then run the compiler with the source code to create a program you can run. I wrote a similar version of the "add the numbers from 1 to 10" program as this BASIC file, which I saved as `sum.bas`:
|
||||
|
||||
```
|
||||
dim sum as integer
|
||||
dim i as integer
|
||||
print "Add the numbers from 1 to 10 ..."
|
||||
sum = 0
|
||||
for i = 1 to 10
|
||||
sum = sum + i
|
||||
next
|
||||
print sum
|
||||
end
|
||||
```
|
||||
|
||||
If you compare this code to the Bywater BASIC version of the program, you may notice that FreeBASIC doesn't require line numbers. FreeBASIC implements a more modern version of BASIC that makes it easier to write programs without keeping track of line numbers.
|
||||
|
||||
Another key difference is that you must define or declare your variables in your source code. Use the `DIM` instruction to declare a variable in FreeBASIC, such as `dim sum as integer`, to define an integer variable called `sum`.
|
||||
|
||||
Now you can compile the BASIC program using `fbc` on the command line:
|
||||
|
||||
```
|
||||
C:\DEVEL\FBC> fbc sum.bas
|
||||
```
|
||||
|
||||
If your code doesn't have any errors in it, the compiler generates a program that you can run. For example, my program is now called `sum`. Running my program adds up the numbers from 1 to 10:
|
||||
|
||||
```
|
||||
C:\DEVEL\FBC> sum
|
||||
Add the numbers from 1 to 10 ...
|
||||
55
|
||||
```
|
||||
|
||||
### FORTRAN 77
|
||||
|
||||
The FORTRAN programming language is like a hybrid between old-style and modern BASIC. FORTRAN came before BASIC, and BASIC clearly took inspiration from FORTRAN, just as later versions of FORTRAN took cues from BASIC. You write FORTRAN programs as source code in a file but you don't use line numbers everywhere. However, FORTRAN 77 does use line numbers (called labels) for certain instructions, including the `FOR` loop. Although in FORTRAN 77, the `FOR` is actually called a `DO` loop, it does the same thing and has almost the same usage.
|
||||
|
||||
In FORTRAN 77, the `DO` loop syntax looks like this:
|
||||
|
||||
```
|
||||
DO label var = start, end
|
||||
```
|
||||
|
||||
This situation is one of the instances where you need a line number to indicate where the `DO` loop ends. You used a `NEXT` instruction in BASIC, but FORTRAN requires a line label instead. Typically, that line is a `CONTINUE` instruction.
|
||||
|
||||
Look at this sample FORTRAN program to see how to use `DO` to loop over a set of numbers. I saved this source file as `sum.f`:
|
||||
|
||||
```
|
||||
PROGRAM MAIN
|
||||
INTEGER SUM,I
|
||||
PRINT *, 'ADD THE NUMBERS FROM 1 TO 10 ...'
|
||||
SUM = 0
|
||||
DO 10 I = 1, 10
|
||||
SUM = SUM + I
|
||||
10 CONTINUE
|
||||
PRINT *, SUM
|
||||
END
|
||||
```
|
||||
|
||||
In FORTRAN, every program needs to start with the PROGRAM instruction, with a name for the program. You might name this program `SUM`, but then you cannot use the variable `SUM` later in the program. When I learned FORTRAN, I borrowed from C programming and started all of my FORTRAN programs with `PROGRAM MAIN`, like the `main()` function in C programs, because I was unlikely to use a variable called `MAIN`.
|
||||
|
||||
The `DO` loop in FORTRAN is similar to the `FOR` loop in BASIC. It iterates over values from 1 to 10. The variable `I` gets the new value at each pass over the loop. This allows you to add each number from 1 to 10 and print the sum when you're done.
|
||||
|
||||
You can find FORTRAN compilers for every platform, including Linux and DOS. FreeDOS 1.3 includes the OpenWatcom FORTRAN compiler on the Bonus CD. On Linux, you may need to install a package to install GNU Fortran support in the GNU Compiler Collection (GCC). On Fedora Linux, you use the following command to add GNU Fortran support:
|
||||
|
||||
```
|
||||
$ sudo dnf install gcc-gfortran
|
||||
```
|
||||
|
||||
Then you can compile `sum.f` and run the program with these commands:
|
||||
|
||||
```
|
||||
$ gfortran -o sum sum.f
|
||||
$ ./sum
|
||||
ADD THE NUMBERS FROM 1 TO 10 ...
|
||||
55
|
||||
```
|
||||
|
||||
### A few differences
|
||||
|
||||
I find that FORTRAN and BASIC are very similar, but with some differences. The core languages are different, but if you know a little of BASIC, you can learn FORTRAN. And if you know some FORTRAN, you can learn BASIC.
|
||||
|
||||
If you want to explore both of these languages, here are a few things to keep in mind:
|
||||
|
||||
- **FORTRAN 77 uses all uppercase,** but later versions of FORTRAN allow mixed cases as long as you use the same capitalization for variables, functions, and subroutines. Most implementations of BASIC are case-insensitive, meaning you can freely mix uppercase and lowercase letters.
|
||||
- **There are many different versions of BASIC,** but they usually do the same thing. If you learn one BASIC implementation, you can easily learn how to use a different one. Watch for warnings or error messages from the BASIC interpreter or compiler, and explore the manual to find the differences.
|
||||
- **Some BASIC implementations require line numbers**, such as Bywater BASIC and GW-BASIC. More modern BASIC versions allow you to write programs without line numbers. FreeBASIC requires the `-lang` deprecated option to compile programs with line numbers.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/basic-vs-fortran-77
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://sourceforge.net/projects/bwbasic/
|
||||
[2]: https://opensource.com/article/21/6/freedos-package-manager
|
||||
[3]: https://www.freebasic.net/
|
@ -0,0 +1,149 @@
|
||||
[#]: subject: "Our favorite fonts for the Linux terminal"
|
||||
[#]: via: "https://opensource.com/article/23/4/linux-terminal-fonts"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Our favorite fonts for the Linux terminal
|
||||
======
|
||||
|
||||
Terminal emulators came up as a topic for me recently, and it got me thinking: What's everyone's favorite terminal font?
|
||||
|
||||
So I asked Opensource.com contributors to share what font they like to use. Here are their answers.
|
||||
|
||||
### VT323
|
||||
|
||||
I like to use a different font ([VT323][1]) in my GNOME Terminal than the font I use (Source Code Pro) in my programming editors or other apps that use a monospace font. I just like the look of the classic VT-style font.
|
||||
|
||||
Sometimes, I switch to the original IBM EGA font, because to my eye it looks really nice. But I associate EGA with DOS, and I associate VT323 with classic Unix terminals, so I use VT323 most of the time. Here's my screenshot of GNOME Terminal using VT323 as the monospace font:
|
||||
|
||||
![gnome-terminal1108×926 output][2]
|
||||
|
||||
I set up the terminal using VT323 at 24 pt, which gives a nice big window. If I'm going to bring up a terminal window, I want to really use it to do real work, not just do one thing and exit. I'm probably going to stay in that terminal window for a while, so it should be big and easy to see. I also prefer 80x25, because I'm an old DOS command line guy and 25 lines looks "right" to my eyes:
|
||||
|
||||
![preference profile screen - text appearance][3]
|
||||
|
||||
**—[Jim Hall][4]**
|
||||
|
||||
### Monospaced fonts
|
||||
|
||||
I don't know that I have a specific font that I use. I usually use either [DejaVu][5] or [Liberation][6] Mono. I like monospaced fonts because they're easier to read. Even then, I don't want the letters to be too close together. The main thing is being able to tell a small "L" from the number 1, Q from O, and so on. It's also nice to have all special characters stand out clearly.
|
||||
|
||||
I also like a good contrast between the font and background, so I set the background to black and characters to white.
|
||||
|
||||
**—[Greg Pittman][7]**
|
||||
|
||||
### Hack
|
||||
|
||||
I like to use monospaced fonts, particularly for the terminal and coding because they're easier to read. I've been using the [Hack][8] font family for years. It provides a nice monospace font combined with additional glyphs and Powerline characters that I can use to display status on the command line.
|
||||
|
||||
![Command line][9]
|
||||
|
||||
Here's the font preview generated with [Fontpreview tool][10].
|
||||
|
||||
![Display of font A-Z and the numbers][11]
|
||||
|
||||
**—[Ricardo Gerardi][12]**
|
||||
|
||||
### Victor Mono
|
||||
|
||||
I've been using [Victor Mono][13] for both my terminal and IDE for a few years. It's perhaps a bit of an acquired taste, because the italic characters are in a monospace cursive script. I like this because code comments have a distinct look that's noticeably different from the rest of the code. Here's what it looks like in a terminal:
|
||||
|
||||
![terminal font is italic characters in a monospace cursive script][14]
|
||||
|
||||
I also use the Solarized Dark color scheme for both my IDE and the terminal. If I could, anything work or code related would all use the same color scheme, and the same fonts, so it all looks uniform. I've gone through various fonts over the years, but I always try to use the same thing in my terminal as in my IDE.
|
||||
|
||||
**—[Chris Reynolds][15]**
|
||||
|
||||
### Monaco
|
||||
|
||||
At the moment, Monaco regular at 16 pt (so much better than 12 or 14 pt fonts).
|
||||
|
||||
**—[Jenny Panighetti][16]**
|
||||
|
||||
### Keeping it pretty in pink
|
||||
|
||||
This reminds me of the time I pranked the other devs on my team by making all of their terminals pink (I was the only woman). It was like a baby pink background with hot pink text.
|
||||
|
||||
I like to make my personal terminals pretty, but for work I leave it white on black and just make the font around 16 pt because I appreciate the larger font size.
|
||||
|
||||
I just leave my terminal set to SF Mono font, but I make it bolder and bump it up a few points so I can see it better. My favorite colors to use are pink or a nice aqua blue color. I also like the default style the terminal has, called "Novel".
|
||||
|
||||
![Two open terminals, one pink and one aqua blue][17]
|
||||
|
||||
**—[RachieVee][18]**
|
||||
|
||||
### Let's ask ChatGPT
|
||||
|
||||
For the heck of it, I decided to ask [ChatGPT][19]. Here was its response:
|
||||
|
||||
> As a language model, I do not have personal preferences or the ability to have a favorite font. However, some popular terminal fonts include Monospace, Consolas, and Inconsolata. These fonts are popular because they are easy to read, have clear distinctions between different characters, and are highly legible even at small font sizes. Additionally, they are designed to work well with a variety of different operating systems and terminals, making them versatile choices for developers and users alike.
|
||||
|
||||
I generated this text in part with GPT-3, OpenAI's large-scale language-generation model. Upon generating draft language, the author reviewed, edited, and revised the language to my own liking and takes ultimate responsibility for the content of this publication.
|
||||
|
||||
**—[Stephanie Brinley][20]**
|
||||
|
||||
### Fantasque Sans Mono
|
||||
|
||||
```
|
||||
$ grep font ~/.Xdefaults
|
||||
URxvt*font: xft:FantasqueSansMono-Regular:pixelsize=12:antialias=true
|
||||
```
|
||||
|
||||
I don't remember when I settled on [Fantasque Sans Mono][21], but I guess it's been my default for the past 8 years now, both in [Rxvt][22] and Konsole. I don't know what font I'm using in my GNOME terminal. Probably whatever the default is on GNOME.
|
||||
|
||||
**—[Seth Kenlon][23]**
|
||||
|
||||
### Jetbrains Mono
|
||||
|
||||
Lately, I have Tilix set as my default terminal. My Tilix config has similar settings to what Jim Hall uses. The few differences are:
|
||||
|
||||
- Cursor shape is underline instead of a block
|
||||
- Font is [Jetbrains Mono][24] Nerd Font Mono Medium 14
|
||||
|
||||
![Black terminal with blue text][25]
|
||||
|
||||
**—[Alan Formy-Duval][26]**
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/linux-terminal-fonts
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://fontsource.org/fonts/vt323
|
||||
[2]: https://opensource.com/sites/default/files/2023-01/gnome-terminal1108%C3%97926.png
|
||||
[3]: https://opensource.com/sites/default/files/2023-01/gnome-terminal-vt323848%C3%97661.png
|
||||
[4]: https://opensource.com/users/jim-hall
|
||||
[5]: https://fontsource.org/fonts/dejavu-mono
|
||||
[6]: https://github.com/liberationfonts
|
||||
[7]: https://opensource.com/users/greg-p
|
||||
[8]: https://sourcefoundry.org/hack/
|
||||
[9]: https://opensource.com/sites/default/files/2023-01/Geradi%201.png
|
||||
[10]: https://github.com/sdushantha/fontpreview
|
||||
[11]: https://opensource.com/sites/default/files/2023-01/fontpreview_default.png
|
||||
[12]: https://opensource.com/users/rgerardi
|
||||
[13]: https://rubjo.github.io/victor-mono/
|
||||
[14]: https://opensource.com/sites/default/files/2023-01/reynolds1.png
|
||||
[15]: https://opensource.com/users/jazzsequence
|
||||
[16]: https://twitter.com/elvenjen
|
||||
[17]: https://opensource.com/sites/default/files/2023-01/pink-blue.webp
|
||||
[18]: https://opensource.com/users/rachievee
|
||||
[19]: https://opensource.com/article/23/2/chatgpt-vs-community
|
||||
[20]: https://opensource.com/users/sbrinley
|
||||
[21]: https://github.com/belluzj/fantasque-sans
|
||||
[22]: https://opensource.com/article/19/10/why-use-rxvt-terminal
|
||||
[23]: https://opensource.com/users/seth
|
||||
[24]: https://www.jetbrains.com/lp/mono/
|
||||
[25]: https://opensource.com/sites/default/files/2023-01/alan.png
|
||||
[26]: https://opensource.com/users/alanfdoss
|
@ -0,0 +1,216 @@
|
||||
[#]: subject: "Make a web-safe color guide with Bash"
|
||||
[#]: via: "https://opensource.com/article/23/4/web-safe-color-guide-bash"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
Make a web-safe color guide with Bash
|
||||
======
|
||||
|
||||
When computer displays had a limited color palette, web designers often used a set of [web-safe colors][1] to create websites. While modern websites displaying on newer devices can display many more colors than the original web-safe color palette, I sometimes like to refer to the web-safe colors when I create web pages. This way I know my pages look good anywhere.
|
||||
|
||||
You can find web-safe color palettes on the web, but I wanted to have my own copy for easy reference. And you can make one too, using the `for` loop in Bash.
|
||||
|
||||
### Bash for loop
|
||||
|
||||
The syntax of a [for loop in Bash][2] looks like this:
|
||||
|
||||
> for _variable_ in _set_ ; do _statements_ ; done
|
||||
|
||||
As an example, say you want to print all numbers from 1 to 3. You can write a quick `for` loop on the Bash command line to do that for you:
|
||||
|
||||
```
|
||||
$ for n in 1 2 3 ; do echo $n ; done
|
||||
1
|
||||
2
|
||||
3
|
||||
```
|
||||
|
||||
The semicolons are a standard Bash statement separator. They let you write multiple commands on a single line. If you were to include this `for` loop in a Bash script file, you might instead replace the semicolons with line breaks and write out the `for` loop like this:
|
||||
|
||||
```
|
||||
for n in 1 2 3
|
||||
do
|
||||
echo $n
|
||||
done
|
||||
```
|
||||
|
||||
I like to include the `do` on the same line as the `for` so it's easier for me to read:
|
||||
|
||||
```
|
||||
for n in 1 2 3 ; do
|
||||
echo $n
|
||||
done
|
||||
```
|
||||
|
||||
### More than one for loop at a time
|
||||
|
||||
You can put one loop inside another. That can help you to iterate over several variables, to do more than one thing at a time. Let's say you wanted to print out all combinations of the letters A, B, and C with the numbers 1, 2, and 3. You can do that with two `for` loops in Bash, like this:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for number in 1 2 3 ; do
|
||||
for letter in A B C ; do
|
||||
echo $letter$number
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
If you put these lines in a Bash script file called `for.bash` and run it, you see nine lines showing the combinations of all the letters paired with each of the numbers:
|
||||
|
||||
```
|
||||
$ bash for.bash
|
||||
A1
|
||||
B1
|
||||
C1
|
||||
A2
|
||||
B2
|
||||
C2
|
||||
A3
|
||||
B3
|
||||
C3
|
||||
```
|
||||
|
||||
### Looping through the web-safe colors
|
||||
|
||||
The web-safe colors are all colors from hexadecimal color `#000` (black, where the red, green, and blue values are all zero) to `#fff` (white, where the red, green, and blue colors are all at their full intensities), stepping through each hexadecimal value as 0, 3, 6, 9, c, and f.
|
||||
|
||||
You can generate a list of all combinations of the web-safe colors using three `for` loops in Bash, where the loops iterate over the red, green, and blue values.
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for r in 0 3 6 9 c f ; do
|
||||
for g in 0 3 6 9 c f ; do
|
||||
for b in 0 3 6 9 c f ; do
|
||||
echo "#$r$g$b"
|
||||
done
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
If you save this in a new Bash script called `websafe.bash` and run it, you see an iteration of all the web safe colors as hexadecimal values:
|
||||
|
||||
```
|
||||
$ bash websafe.bash | head
|
||||
#000
|
||||
#003
|
||||
#006
|
||||
#009
|
||||
#00c
|
||||
#00f
|
||||
#030
|
||||
#033
|
||||
#036
|
||||
#039
|
||||
```
|
||||
|
||||
To make an HTML page that you can use as a reference for web-safe colors, you need to make each entry a separate HTML element. Put each color in a `<div>` element, and set the background to the web-safe color. To make the hexadecimal value easier to read, put it inside a separate `<code>` element. Update the Bash script to look like this:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
for r in 0 3 6 9 c f ; do
|
||||
for g in 0 3 6 9 c f ; do
|
||||
for b in 0 3 6 9 c f ; do
|
||||
echo "<div style='background-color:#$r$g$b'><code>#$r$g$b</code></div>"
|
||||
done
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
When you run the new Bash script and save the results to an HTML file, you can view the output in a web browser to all the web-safe colors:
|
||||
|
||||
```
|
||||
$ bash websafe.bash > websafe.html
|
||||
```
|
||||
|
||||
![Colour gradient.][3]
|
||||
|
||||
The web page isn't very nice to look at. The black text on a dark background is impossible to read. I like to apply some HTML styling to ensure the hexadecimal values are displayed with white text on a black background inside the color rectangle. To make the page look really nice, I also use HTML grid styles to arrange the boxes with six per row and some space between each box.
|
||||
|
||||
To add this extra styling, you need to include the other HTML elements before and after the for loops. The HTML code at the top defines the styles and the HTML code at the bottom closes all the open HTML tags:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
cat<<EOF
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Web-safe colors</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<style>
|
||||
div {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media only screen and (min-width:600px) {
|
||||
|
||||
body {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6,1fr);
|
||||
column-gap: 1em;
|
||||
row-gap: 1em;
|
||||
}
|
||||
|
||||
div {
|
||||
padding-bottom: 3em;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
</body>
|
||||
EOF
|
||||
|
||||
for r in 0 3 6 9 c f ; do
|
||||
for g in 0 3 6 9 c f ; do
|
||||
for b in 0 3 6 9 c f ; do
|
||||
|
||||
echo "<div
|
||||
style='background-color:#$r$g$b'><code>#$r$g$b</code></div>"
|
||||
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
cat<<EOF
|
||||
|
||||
</body>
|
||||
</html>
|
||||
EOF
|
||||
```
|
||||
|
||||
This finished Bash script generates a web-safe color guide in HTML. Whenever you need to refer to the web-safe colors, run the script and save the results to an HTML page. Now you can see a representation of the web-safe colors in your browser as an easy-reference guide for your next web project:
|
||||
|
||||
```
|
||||
$ bash websafe.bash > websafe.html
|
||||
```
|
||||
|
||||
![Web colors.][4]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/web-safe-color-guide-bash
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors
|
||||
[2]: https://opensource.com/article/19/6/how-write-loop-bash
|
||||
[3]: https://opensource.com/sites/default/files/2023-03/10000001000002620000013685924861376B1AB6.webp
|
||||
[4]: https://opensource.com/sites/default/files/2023-03/10000001000002620000013633233DC8DC56C891.webp
|
@ -0,0 +1,213 @@
|
||||
[#]: subject: "A Quick Guide to Install and Play GOG Games on Linux"
|
||||
[#]: via: "https://itsfoss.com/play-gog-games-linux/"
|
||||
[#]: author: "Ankush Das https://itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
A Quick Guide to Install and Play GOG Games on Linux
|
||||
======
|
||||
|
||||
![][1]
|
||||
|
||||
[Gaming on Linux][2] is no longer a problem. You can play plenty of AAA titles, indie games, and Windows-exclusive games on Linux. Several games from GOG, Steam, Epic Games, Origin, and Ubisoft Connect should work flawlessly.
|
||||
|
||||
Unfortunately, GOG does not offer a client for Linux that you can use.
|
||||
|
||||
So, in this guide, I will be focusing on **installing and playing GOG games on Linux**.
|
||||
|
||||
If you have been following us, you may have come across on our ultimate guide to the [Epic Games Store on Linux][3]. It is more or less the same thing, but for a different store.
|
||||
|
||||
> 💡 GOG.com is popular for offering DRM-free games. Furthermore, if you make a purchase on GOG, usually, the developer gets a good cut of it compared to other stores.
|
||||
|
||||
### 3 Ways to Install GOG Games on Linux
|
||||
|
||||
You have a couple of options when it comes to installing and running a game from the GOG store.
|
||||
|
||||
You can use any of the following game clients on Linux:
|
||||
|
||||
- **Lutris**
|
||||
- **Heroic Games Launcher**
|
||||
- **Bottles**
|
||||
|
||||
I found Lutris to be the easiest, and quickest to be able to run a Windows-exclusive GOG game on Linux. So, let me start with it.
|
||||
|
||||
#### Method 1. Install and Play GOG Games Using Lutris
|
||||
|
||||
1. To get started, you need to **install Lutris on Linux**.
|
||||
|
||||
You can install it using [Flathub][4], PPA for Ubuntu-based distros, DEB package or from the software center of distros like Pop!_OS, Solus.
|
||||
|
||||
Head to its [official download page][5] and install Lutris.
|
||||
|
||||
[Install Lutris][5]
|
||||
|
||||
2. Once you are done installing Lutris, launch it and click on “**GOG**” among the sources listed on its left sidebar, as shown in the image:
|
||||
|
||||
![lutris game client gog source][6]
|
||||
|
||||
Do you see a **user avatar icon**, right next to it? Click on it to log in to your GOG account.
|
||||
|
||||
![gog sign in through lutris][7]
|
||||
|
||||
You can access the library of games associated with your account after signing in through Lutris' native user interface.
|
||||
|
||||
![][8]
|
||||
|
||||
3. Pick any game you want, and click on it to find "**Install**" button.
|
||||
|
||||
As you proceed, Lutris will prompt you to **install Wine**, which would enable you to run the Windows game on Linux.
|
||||
|
||||
![][9]
|
||||
|
||||
**(Optional)** You can separately install Wine under the "**Runners**" menu, and have multiple versions of it ready before installing the game if you prefer.
|
||||
|
||||
![lutris wine manager][10]
|
||||
|
||||
4. But, if you do not want any hassle, just go with the installation process, and it will automatically install Wine and then prompt you to download the game
|
||||
|
||||
![][11]
|
||||
|
||||
![][12]
|
||||
|
||||
5. Continue with the process, and it will set up the installer for you and launch it.
|
||||
|
||||
![][13]
|
||||
|
||||
![][14]
|
||||
|
||||
Now, you have to follow the on-screen instructions for any game you want to install and then complete it.
|
||||
|
||||
> 📋 Not every game will work seamlessly. For some, you may have to install it using a specific Wine version and some may not work at all. So, you should do some research on the particular game running on Linux before trying to install it via GOG.
|
||||
|
||||
It is done! The game should launch right after successful setup.
|
||||
|
||||
![Playing a GOG Windows game on Linux][15]
|
||||
|
||||
#### Method 2. Install and Play GOG Games on Linux Using Heroic Games Launcher
|
||||
|
||||
Heroic Games Launcher is a nice option with several features to run GOG games on Linux.
|
||||
|
||||
You can use an **AppImage** file available, or install its Flatpak via **Flathub** or get RPM/DEB packages from its GitHub.
|
||||
|
||||
[Install Heroic Games Launcher][16]
|
||||
|
||||
> 🚧 You get similar functionalities but unlike Lutris, but you need to first install Wine manually using its
|
||||
|
||||
**Wine Manager**
|
||||
|
||||
. Heroic Games Launcher does not automatically install Wine for you. It will download the game for you, even if you do not have Wine installed.
|
||||
|
||||
It can be confusing for new users. But, if you have a bit of experience and want to choose the Wine/Proton version, you can head to its **Wine Manager** and preferably download the latest available version to get started.
|
||||
|
||||
![wine manager listing several versions of wine/proton on heroic games launcher][17]
|
||||
|
||||
No additional fiddling, **just click on the download icon** as shown in the screenshot above, and it will automatically install it.
|
||||
|
||||
Once done with it, here are the steps to install a GOG game using Heroic:
|
||||
|
||||
1. Log in to your GOG account. You can find the GOG menu right after you launch it and head to the **Login section**.
|
||||
|
||||
![][18]
|
||||
|
||||
![][19]
|
||||
|
||||
2. After logging in, head to the **Library** to find the games you have.
|
||||
|
||||
![gog game library on heroic games launcher][20]
|
||||
|
||||
3. Click on the download icon to proceed. Now, you should get a prompt to decide the **installation path, Wine version**, and a couple of other options.
|
||||
|
||||
![gog game installation screen on heroic games launcher selecting the install path, wine, and more][21]
|
||||
|
||||
You can select "**Use Default Wine Settings**" if you want to automatically select the Wine version you have installed.
|
||||
|
||||
Or, you can use the **drop-down arrow** to pick among the Wine/Proton version available on your system.
|
||||
|
||||
For the ease of use, you can go with the default settings. And, if the game fails to work, you can go to its settings later and try other Wine versions.
|
||||
|
||||
4. Wait for the download to complete and then launch/run the game.
|
||||
|
||||
![][22]
|
||||
|
||||
![][23]
|
||||
|
||||
#### Method 3: Install and Play GOG Games on Linux Using Bottles
|
||||
|
||||
Bottles is an impressive platform. However, it does not let you install games through it.
|
||||
|
||||
> 🚧 This is not a recommended method. But, if you want to try the GOG Galaxy game client on Linux, Bottles is the way to go.
|
||||
|
||||
Instead, it will help you install the GOG client (which you find for Windows) and make it work on Linux. Bottles is one of the best [ways to install a Windows program on Linux][24].
|
||||
|
||||
It is recommended to install Bottles as Flatpak, at the time of writing this. So, to get started, you need to get it installed from [Flathub][25]. Additionally, you can explore other download options, if available.
|
||||
|
||||
[Download Bottles][26]
|
||||
|
||||
Once you get it installed, you have to create a new Bottle for Gaming. And, inside it, you will have to search for GOG Galaxy v1 or legacy and install the program to use GOG on Linux.
|
||||
|
||||
![][27]
|
||||
|
||||
![][28]
|
||||
|
||||
In my tests, GOG Galaxy client did not launch. And, when it did, it was too slow/unresponsive. But, at least, it is something you can explore when nothing else works for you. It may or may not work, of course.
|
||||
|
||||
If this is something that interests you, feel free to give it a try.
|
||||
|
||||
### Wrapping Up
|
||||
|
||||
The installers or gaming clients on Linux are making things convenient every day.
|
||||
|
||||
For some games, it can end up as a one-click installation experience, while for others, it might need a little tweaking.
|
||||
|
||||
If you struggle with it, feel free to join our **[It's FOSS forums][29]** for help. And, if you are new to the gaming scene on Linux, I suggest you read our guide on it:
|
||||
|
||||
There is also a handy utility called GameHub that can be utilized for keeping games from different platforms in one UI.
|
||||
|
||||
And of course, GOG is not the only place for [getting Linux games][30].
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://itsfoss.com/play-gog-games-linux/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://itsfoss.com/content/images/2023/03/linux-mega-packt.webp
|
||||
[2]: https://itsfoss.com/linux-gaming-guide/
|
||||
[3]: https://itsfoss.com/epic-games-linux/#3-use-bottles-to-access-epic-games-store
|
||||
[4]: https://flathub.org/apps/details/net.lutris.Lutris?ref=itsfoss.com
|
||||
[5]: https://lutris.net/downloads?ref=itsfoss.com
|
||||
[6]: https://itsfoss.com/content/images/2023/04/lutris-gog.png
|
||||
[7]: https://itsfoss.com/content/images/2023/04/lutris-gog-login.png
|
||||
[8]: https://itsfoss.com/content/images/2023/04/lutris-game-install.png
|
||||
[9]: https://itsfoss.com/content/images/2023/04/install-wine-lutris.png
|
||||
[10]: https://itsfoss.com/content/images/2023/04/lutris-wine-manager.png
|
||||
[11]: https://itsfoss.com/content/images/2023/04/lutris-wine-download.png
|
||||
[12]: https://itsfoss.com/content/images/2023/04/lutris-download-game.png
|
||||
[13]: https://itsfoss.com/content/images/2023/04/lutris-game-installer.png
|
||||
[14]: https://itsfoss.com/content/images/2023/04/lutris-game-installation-1.png
|
||||
[15]: https://itsfoss.com/content/images/2023/04/lutris-game-working.jpg
|
||||
[16]: https://heroicgameslauncher.com/downloads?ref=itsfoss.com
|
||||
[17]: https://itsfoss.com/content/images/2023/04/heroic-games-launcher-wine.png
|
||||
[18]: https://itsfoss.com/content/images/2023/04/heroic-games-gog-login.png
|
||||
[19]: https://itsfoss.com/content/images/2023/04/heroic-gog-login-page.png
|
||||
[20]: https://itsfoss.com/content/images/2023/04/heroic-gog-games-library.png
|
||||
[21]: https://itsfoss.com/content/images/2023/04/gog-wine-path-install.png
|
||||
[22]: https://itsfoss.com/content/images/2023/04/gog-game-download-heroic.png
|
||||
[23]: https://itsfoss.com/content/images/2023/04/gog-game-heroic-game-play.png
|
||||
[24]: https://itsfoss.com/use-windows-applications-linux/
|
||||
[25]: https://flathub.org/apps/details/com.usebottles.bottles?ref=itsfoss.com
|
||||
[26]: https://usebottles.com/download/?ref=itsfoss.com
|
||||
[27]: https://itsfoss.com/content/images/2023/04/gog-installer-1.png
|
||||
[28]: https://itsfoss.com/content/images/2023/04/install-gog-client-1.png
|
||||
[29]: https://itsfoss.community/?ref=itsfoss.com
|
||||
[30]: https://itsfoss.com/download-linux-games/
|
@ -0,0 +1,60 @@
|
||||
[#]: subject: "5 best practices for PatternFly, an open source design system"
|
||||
[#]: via: "https://opensource.com/article/23/4/open-source-design-system-patternfly"
|
||||
[#]: author: "Abigael Donahue https://opensource.com/users/abigaeljamie"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
5 best practices for PatternFly, an open source design system
|
||||
======
|
||||
|
||||
Have you ever admired the facets of a gemstone? The angles and slants are a thing of beauty. You can see that a multi-faceted gemstone shines brighter than a flat one. You may also see this kind of beauty when analyzing a multi-faceted design system. A design system is a collection of guidelines, standards, and resources for creating consistent and unified user interfaces (UI). Like the facets of a diamond, an open source design system rich with diverse contributions and community engagement ultimately leads to better product experiences.
|
||||
|
||||
The [PatternFly][1] project is an open source design system for Red Hat products. But open source doesn't end with PatternFly's code. Behind PatternFly is a team of people who create designs completely in the open. From designers and developers to researchers and writers, we work together to operate as an open source community.
|
||||
|
||||
Our secret? We don't have one — we work in the open, remember? However, we use these five best practices. I'll share them here so that you too can power your own design system with open source.
|
||||
|
||||
### 1. Contribute collectively
|
||||
|
||||
We have a core PatternFly design team to design, maintain, and evolve the design system. But we encourage and welcome contributions from everyone. If you have a passion for collaboration and a knack for user experience (UX), [PatternFly wants to hear from you][2].
|
||||
|
||||
### 2. Build community
|
||||
|
||||
Nothing created in a silo makes its way to PatternFly. We believe design is better in the open. This is why we include the community in all updates, changes, and additions. We collect feedback on contributions from people across design and development so that everyone has a say in what gets implemented. We also seek input and collaboration from people across multiple [design disciplines][3]. This is done to break free from any bias or assumption. This kind of open design makes our design system stronger. It also strengthens our blossoming community of people who engage with or contribute to PatternFly (we lovingly refer to them as Flyers).
|
||||
|
||||
### 3. Loop in everyone
|
||||
|
||||
If you find that brainstorming ideas with others results in solutions better than any one person would have dreamed of, then you already think like a Flyer. We have regular design meetings where contributors present their ideas and discuss design approaches in a group setting. This enables us to keep our ideas collaborative and consider designs from all angles. Additionally, we host monthly community meetings so that we can connect with Flyers from across the globe and share the latest updates. You can catch all of our past meeting recordings on our [PatternFly YouTube channel][4].
|
||||
|
||||
### 4. Listen to users
|
||||
|
||||
As a community, we aim to have all PatternFly contributions lead to functional and beautiful product experiences across different contexts. To make that a reality, we hold ourselves accountable to break out of our own bubbles and engage with users. We work with UX researchers to test updates, changes, and additions with users — such as visual themes and interactions — to ensure that we're creating designs, resources, and experiences that solve for everyone, not just people like us.
|
||||
|
||||
### 5. Create connections
|
||||
|
||||
PatternFly is the thread of consistency through products across Red Hat's portfolio. Everyone has the creative freedom to build what best serves their users. But we work as a team to connect product groups through the design system for a more unified user experience. PatternFly resources are easy to access and open to all. This helps us create connections and squash silos.
|
||||
|
||||
### Come design in the open with us
|
||||
|
||||
Whether you're a team of 1 or 100, or whether your design system is open source or not — there's always room for a little collaboration and community in everything we do. Tell us how things turn out for you by connecting with the [PatternFly community][5]. We can't wait to hear from you.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/4/open-source-design-system-patternfly
|
||||
|
||||
作者:[Abigael Donahue][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/abigaeljamie
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://www.patternfly.org/v4/
|
||||
[2]: https://www.patternfly.org/v4/contribute/about
|
||||
[3]: https://design.redhat.com/?intcmp=7013a000002qLH8AAM
|
||||
[4]: https://www.youtube.com/channel/UCqLT0IEvYmb8z__9IFLSVyQ
|
||||
[5]: https://www.patternfly.org/v4/community
|
@ -0,0 +1,118 @@
|
||||
[#]: subject: "CachyOS: Arch-based Distro for Speed and Ease of Use"
|
||||
[#]: via: "https://news.itsfoss.com/cachyos/"
|
||||
[#]: author: "Ankush Das https://news.itsfoss.com/author/ankush/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: " "
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
CachyOS: Arch-based Distro for Speed and Ease of Use
|
||||
======
|
||||
|
||||
A performance-focused Arch-based distro for newbies and experts.
|
||||
|
||||
![cachyOS][1]
|
||||
|
||||
![][2]
|
||||
|
||||
Arch Linux is suitable for advanced users looking for a challenge to use Linux on their system.
|
||||
|
||||
However, many [Arch-based distributions][3] have made it possible for new users to get into the distribution family by making things easier. Options like Garuda Linux, Manjaro Linux, and others make it convenient for new users.
|
||||
|
||||
And one of the exciting options among them is **CachyOS**.
|
||||
|
||||
Well, you might already know about [blendOS][4] (which is also an Arch-based distro, still in the works). It is not remotely similar, but if you are exploring Arch-based distros, you can check it out.
|
||||
|
||||
### CachyOS: Overview
|
||||
|
||||
![cachyos home with cachyos theme][5]
|
||||
|
||||
CachyOS is tailored for all users, whether you are an expert or just starting out. It is available as a stable release even though it is fairly new.
|
||||
|
||||
It aims to provide a blazing-fast experience and offer customizability and stability simultaneously.
|
||||
|
||||
All of this keeping security in mind.
|
||||
|
||||
Some of the critical highlights of CachyOS include the following:
|
||||
|
||||
- **Desktop****packages compiled with****LTO and x86-64-v3 optimization**.
|
||||
- **Choice of desktop environments** with online installation process (including i3, bspwm, and Openbox window managers)
|
||||
- **Offline and Online installation** options
|
||||
- **GUI and CLI-based installation** options
|
||||
- **Optimized Linux Kernel** with advanced BORE Scheduler for enhanced performance and reliability
|
||||
|
||||
### Initial Impression
|
||||
|
||||
CachyOS looks like a well-polished distribution. When I used the ISO to spin up a virtual machine, I noticed that it does support NVIDIA cards, which is a nice touch.
|
||||
|
||||
![][6]
|
||||
|
||||
And then, the option to use an offline or online installation process was helpful. With the online installation process, you can install desktop environments or window managers as per your preference.
|
||||
|
||||
Once done, the welcome screen provided all the essential abilities from the get-go. So, good points for that as well.
|
||||
|
||||
![cachyos welcome screen][7]
|
||||
|
||||
You can install packages, enable system-specific settings, and tweak application/kernel stuff from the welcome screen. Of course, a newbie should not do anything they do not know, but it is good to have everything accessible.
|
||||
|
||||
![cachyos hello welcome screen tweak options][8]
|
||||
|
||||
I tried the KDE edition of CachyOS, which looks pretty good.
|
||||
|
||||
For some reason, the theme was KDE's default Breeze Dark. I expected it to have CachyOS's customized theme out of the box.
|
||||
|
||||
![cachyos homescreen with file manager using kde breeze dark theme][9]
|
||||
|
||||
So, I had to head to the theme manager settings and apply the CachyOS theme for it to look unique.
|
||||
|
||||
![][10]
|
||||
|
||||
It utilizes the fish shell, making the terminal look and feel excellent out of the box.
|
||||
|
||||
![cachyos fish shell][11]
|
||||
|
||||
Performance and security enhancements are at their core. So, if you are unsure about the claims, you will have to compare things closely with another distro. However, per a couple of Reddit threads, some users mention a 10-20% performance uplift.
|
||||
|
||||
You can read [Phoronix's performance analysis][12] of CachyOS for additional insights.
|
||||
|
||||
Unlike other distributions, it features its own web browser, a fork of Firefox, with modifications/enhancements for privacy and security. However, it missed out on a default video player, which should be given to cater to new users.
|
||||
|
||||
**Overall**: It feels like a well-thought-out distribution out of the box. To add a cherry on top, its [documentation][13] is on point and incredibly useful for beginners.
|
||||
|
||||
### Download CachyOS
|
||||
|
||||
You can find KDE and GNOME editions of CachyOS on its [official website][14]. An XFCE edition is in the works. Of course, you can install anything else using its online installation process.
|
||||
|
||||
[CachyOS][14]
|
||||
|
||||
Additionally, you can explore its [GitHub page][15] if you are curious about the customizations they make under the hood.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://news.itsfoss.com/cachyos/
|
||||
|
||||
作者:[Ankush Das][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://news.itsfoss.com/author/ankush/
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://news.itsfoss.com/content/images/size/w1304/2023/04/CachyOS.jpg
|
||||
[2]: https://news.itsfoss.com/content/images/2023/03/linux-mega-packt.webp
|
||||
[3]: https://itsfoss.com/arch-based-linux-distros/?ref=news.itsfoss.com
|
||||
[4]: https://news.itsfoss.com/blendos/
|
||||
[5]: https://news.itsfoss.com/content/images/2023/04/cachy-os-home.jpg
|
||||
[6]: https://news.itsfoss.com/content/images/2023/04/cachy-os-installer.jpg
|
||||
[7]: https://news.itsfoss.com/content/images/2023/04/cachy-os-hello.jpg
|
||||
[8]: https://news.itsfoss.com/content/images/2023/04/cachyos-app-tweaks.jpg
|
||||
[9]: https://news.itsfoss.com/content/images/2023/04/cachyos-home.jpg
|
||||
[10]: https://news.itsfoss.com/content/images/2023/04/cachyos-nord-theme.jpg
|
||||
[11]: https://news.itsfoss.com/content/images/2023/04/cachy-os-fish-shell.jpg
|
||||
[12]: https://www.phoronix.com/review/cachyos-linux-perf?ref=news.itsfoss.com
|
||||
[13]: https://wiki.cachyos.org/?ref=news.itsfoss.com
|
||||
[14]: https://cachyos.org/?ref=news.itsfoss.com
|
||||
[15]: https://github.com/cachyos?ref=news.itsfoss.com
|
@ -1,93 +0,0 @@
|
||||
[#]: subject: "Open Source Software: Is There an Easy Path to Success?"
|
||||
[#]: via: "https://www.opensourceforu.com/2022/07/open-source-software-is-there-an-easy-path-to-success/"
|
||||
[#]: author: "Jules Graybill https://www.opensourceforu.com/author/jules-graybill/"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "CanYellow"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
开源软件:存在成功的捷径吗?
|
||||
======
|
||||
|
||||
开发开源软件背后的工作是相当庞大的。那么我们如何保证开源项目的成功呢?存在捷径吗?本文认为是没有的。
|
||||
|
||||
![团队合作][1]
|
||||
|
||||
今天,开源已经风靡世界。很多大型企业在快速成功的诱惑下被推向开源。但真实情况是世界上并不存在成功的捷径。你无法做到通过一次努力就能让所有的开源项目正常运行。
|
||||
|
||||
事实上,上述公司早期遇到的许多挑战都不是技术上的,而是人员与文化上的。
|
||||
|
||||
开发一个能够在市场上获得成功的开源项目需要同不同层级(的开源社区人员)一同工作。维护这样的项目也是一个持续的过程。所有这一切的关键在于找到以下这个非常基础的问题的正确答案:开源究竟是什么。
|
||||
|
||||
### 开源是代码
|
||||
|
||||
对于很多没有深刻认识到构成开源的不同层级(的开源社区人员)用户而言,答案相当简单:开源就是软件!这当然没有错,毕竟这就是我们多数人如何使用它的。不过,相比仅仅被视作软件而言,开源远不止这些。
|
||||
|
||||
任何开源项目的实质仍然是代码本身。代码是使一个开源项目有别于其他项目并使其对用户有益的根本。当你在开源中工作的时候,代码和软件一样都是产品自身的一部分。
|
||||
|
||||
从零开始开发一个(开源)项目或者复刻(fork)一个现有项目的分支,即便是在处理如此庞大而复杂的代码库时,也需要编写成千上万行代码。尤其是在创新一个现有项目的分支的情况下,在移除任何在先的许可证、宣传材料或者其他任何可能已经失去作用的文件时必须小心翼翼。终究是一个项目的功能吸引了它的用户群并维持项目的持续发展。当终端用户在考虑是否使用开源软件的时候,他们会阅读项目的源代码,而他们在其中所看到的应当是那些能够建立他们的信心的内容。
|
||||
|
||||
### 开源是社区
|
||||
|
||||
如何参与到社区中也是产品构建项目的一部分。创建一个社区并维护一个健康的社区关系是开源的核心之一,但对于大部分的领导者而言也往往是最坚难的任务,很少有人能很好地维护它。你可以尝试建立基金会或者提供赞助,但是最终还是人们自行决定是否想要加入社区。
|
||||
|
||||
维护一定程度的社区透明度并不断保持也是重要的。社区可以随心所欲地参与项目。除了需要秘密进行的工作之外,诸如安全设置、签发证书、注册商标等,尽可能多的将你所做的工作展示给社区是相当重要的,这有助于取得社区信任。你终究需要对社区负责,你的项目成也社区,败也社区。这可能会导致你的项目开发更谨慎、更缓慢并且向社区公开,不过项目最终会进展顺利。
|
||||
|
||||
如此地公开你正在进行的工作似乎有些令人生怯,尤其是当你担心更新推迟或者是出现漏洞的影响的时候。不过,让社区成员知悉你的进展不仅有助帮助你建立与社区之间的信任关系,而且能够让社区成员感到被认可。
|
||||
|
||||
另一方面,公开你的工作流也可以获得来自社区成员的监督,他们经常有自己的见解并向你反馈。记录这些反馈是很重要的,这使得你的开源项目如实地反映社区需求。他们是项目的末端用户,而他们的反馈则反映了他们如何看待你的项目的长期发展以及你的项目最终将有多么成功或者主流。
|
||||
|
||||
举例而言,当我们在考虑一个新功能的时候,我们在征求意见文档(RFC, Request for Comments)中发布一个征集意见的请求,我们会收到大量的反馈,我们必须认真思考应当如何吸收这些反馈。
|
||||
|
||||
因为开源是一个大型的合作项目,社区在支持开源项目成为可能的万里挑一的项目上享有主动权。并非所有的问题都要解决,但只要你有在倾听社区的呼声,社区就会有参与感。
|
||||
|
||||
参与到社区中也存在一些隐患。社区内部、项目维护与社区之间均可能存在不同意见,尤其是在涉及管理问题上。管理问题对于一个开源项目来说是相当重要的。这也就是为什么拥有一份清晰的文档化的管理条例对于项目以及社区均是如此重要。
|
||||
|
||||
社区管理是一个关键的而又难啃的骨头。社区授权本身需要相当大的信任。对于一个拥有成千上万行代码的项目,在社区中寻找能够有效领导社区的人物是不容易的。不过开源项目经常是由更小的子项目组成的,这些子项目最好由社区中的某个人进行管理。这有助于社区更紧密地参与到项目中。
|
||||
|
||||
| - |
|
||||
| :- |
|
||||
| 建立社区的过程不是一帆风顺的。让我列举一一些有助于维持社区与我的团队之间平衡的技巧。
|
||||
|
||||
**声明你的原则:**尤其是在开源项目的早期,在项目代码仍在完善,很多事情还不完美的时候,项目之外的人员很难真正理解你所做的决定。向他们说明你做出决定所依据的原则有助于你在思考过程上保持坦率,从而让社区不会错误地干扰你的事务。
|
||||
|
||||
这一经验非常有效,在你做出决定时坚持遵循其中一项原则并展示出来是非常重要的。
|
||||
|
||||
*确定如何进行协作:*你可以通过Discord、Slack或者邮件等途径完成这一工作。但是如果你试图同时使用他们,你将毫不意外的分散项目社区。社区人员将在所有这些途径上互相交流。选择一到两种沟通工具,投身于他们来保证社区的信息同步。
|
||||
|
||||
*珍惜反馈意见:*倾听来自社区的反馈并付诸行动。即使需要你作出艰难的决定,你也应当向社区展示你是重视社区话语的。
|
||||
|
||||
**维护一套行为准则:**如果你与社区打交道,你需要定义什么行为是可以接受的。一套落地的行为准则有助于在人们越过红线时警示他们。如果你可以提前制定这些你可以避免很多麻烦。
|
||||
|
||||
*考虑如何分发你的项目:*存在这样的情况,因为你还没有准备好某一个组件,或者是因为存在一些项目功能你不希望所有人都能够访问,所以你可能并不希望将你的项目完全向公众公开。关键是制定符合你的要求而不是向用户妥协的分发条款,如此,需要某种功能的用户可以获取所需项目的同时不需要该功能的用户也不需要做出妥协而开始使用该项目。
|
||||
|
||||
*尽可能地避免投票:*这是因为部分成员经常会赞成与大部分成员的意见相左的选项,这会使这些人产生一定程度的失望,并让他们觉得被项目所孤立。反之,尽量尝试询问他们想要解决什么问题,并尝试创造一个不需要付出代价的解决方案。
|
||||
|
||||
### 开源是许可
|
||||
|
||||
开源是给予你的用户如何使用你的软件的自由,而许可能够做到这一点。一个开源项目许可是极好的,它保证了不论你作为维护者做了什么,你的所有终端用户以及利益相关方总是可以维护一系列的项目复刻版本,这些都是重要的项目复刻版。
|
||||
|
||||
许可提供了人们可选择性,如果他们认为有必要,他们可以将项目复制到不同的路径中。他们拥有创建副本的权利,这使得许多优秀的软件能够被开发出来。维护者有责任倾听他们的社区成员的声音并以一个对项目的社区成员有利的方式运营项目。
|
||||
|
||||
我们推荐使用现有的许多可用的许可证而不是独立制作你自己的许可条款,仅仅只是因为用户以及利益相关方通常都很熟悉公共许可证,因此你不需要再花费时间在解释许可条款上。这将帮助你将你的精力集中在项目的其他部分上。
|
||||
|
||||
### 最后,开源是一项运动
|
||||
|
||||
开源包括了很多维度,也包含了很多人员。最重要的是,它是有关理解人们想要什么的,也是有关创建一个鼓励协作与透明的环境的。开源也是有关创建有利于开源项目走自己想走的道路的社区的。维护者创造越多的机会让社区自由发挥,开源产品就越好,也越发成功。
|
||||
|
||||
开源是以上这些方面,而你的视野越宽阔,你就能越好的利用它。请考虑你如何能够在开源的每一个维度上出类拔萃,因为时至今日,开源的成功之路并无捷径。
|
||||
|
||||
|
||||
via: https://www.opensourceforu.com/2022/07/open-source-software-is-there-an-easy-path-to-success/
|
||||
|
||||
作者:[Jules Graybill][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[CanYellow](https://github.com/CanYellow)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://www.opensourceforu.com/author/jules-graybill/
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://www.opensourceforu.com/wp-content/uploads/2022/07/team-work-working-together-1.jpg
|
@ -1,99 +0,0 @@
|
||||
[#]: subject: "5 open source alternatives to Microsoft Exchange"
|
||||
[#]: via: "https://opensource.com/article/21/11/open-source-alternatives-microsoft-exchange"
|
||||
[#]: author: "Heike Jurzik https://opensource.com/users/hej"
|
||||
[#]: collector: "lujun9972"
|
||||
[#]: translator: "XiaotingHuang22"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
可以替代 Microsoft Exchange 的5个开源软件
|
||||
======
|
||||
不再将就于 Microsoft Exchange 这一专有软件,试一试这些基于 Linux 系统的电子邮件和群件服务吧。
|
||||
![在团队中工作,忙碌的工作生活][1]
|
||||
|
||||
几十年来,Microsoft Exchange 一直统治着电子邮件和群件服务市场。 作为领头羊,它主宰着企业界,无处不在的 Outlook 邮件客户端已成为群件同行里的事实标准。 由于 Exchange 与 Microsoft 的 Office 产品紧密联系,无论是桌面客户端还是移动客户端,微软用户都可以轻松使用各种生产力软件和功能。
|
||||
|
||||
然而,许多公司对于将数据存储在 Microsoft 云中也心存疑虑。 在本文中,我将介绍一些开源替代产品及其优势。 这不仅有关如何不再受供应商控制和降低成本,更关乎使用具有开放标准和不同安全级别的软件——用于组件服务器本身及其背后的操作系统。
|
||||
|
||||
本文中介绍的这五个替代产品都是基于 Linux 的。 虽然 grommunio、Kopano、Nextcloud、ownCloud 和 OX App Suite 在功能上差异很大,吸引到的企业类型各不相同,但它们都提供免费版本,并可选择购买付费支持服务和附加组件。 所有产品都可以在本地或云端运行。 最重要的是,所有供应商都为其软件提供 SaaS (Software as a Service,软件即服务) 解决方案。
|
||||
|
||||
### grommunio
|
||||
|
||||
[grommunio][2],以前被称为 grammm,在 AGPLv3 许可下发布的。 它由奥地利同名公司开发和支持。 与 Exchange 不同,grommunio 提供符合标准的邮件服务器以及功能齐全的群件解决方案,具有电子邮件、联系人、日历、任务、文件共享等功能。 grommunio 适用于各种开源和专有邮件客户端,如 Windows Mail、Outlook、Android、Apple Mail/iOS、Thunderbird 等,并支持旧的 RPC over HTTP 协议和 Outlook 标准协议 MAPI over HTTP。 除此之外还包含:用于移动设备的 Exchange ActiveSync 和各种标准协议,如 CalDAV(日历)、CardDAV(地址簿)、IMAP、POP3、SMTP 和 LDAP,以及 Active Directory(用于同步用户帐户)。
|
||||
|
||||
外部开源应用程序还提供了一些 Microsoft 的 API 或协议不支持的功能。 例如,开发人员合并了 [Jitsi][3](视频和音频电话软件)、[Mattermost][4](聊天软件)以及文件共享和同步([ownCloud][5])。除此之外,grommunio 还配备了基本的移动设备管理软件 (MDM)。
|
||||
|
||||
grommunio 的设计面向大量不同的用户,并且与 Exchange 一样,它支持数据库分片(数据库在多个主机之间的水平分布)。 灵活的存储后端允许管理员通过添加其他服务器或云帐户来扩展他们的设置。 grommunio 仅将 MySQL 数据库用于元数据,而所有“内容”(例如邮件和群件对象)都存储在每个用户的 SQLite 数据库中。 有关底层架构的更多信息,请查看[制造商的网站][6]。
|
||||
|
||||
社区版是免费的,其中包括所有的 grommunio 功能并支持最多五个用户帐户。
|
||||
|
||||
### Kopano
|
||||
|
||||
来自德国和荷兰的软件制造商 Kopano 出品的 [Kopano][7] 也获得了 AGPLv3 许可并基于 Zarafa 软件堆栈。 与其前身不同,Kopano 的目标不只是成为 Exchange 的替代品。 相反,它提供一个完整的群件解决方案,除了电子邮件、联系人、日历、任务、笔记和文档编辑这些标准功能外,它还包括实时通信。 Kopano 与[许多其他平台][8]、应用程序和服务交互,其中一些通过插件就能轻松实现。 对于视频会议,Kopano 团队基于 WebRTC 开发了自己的开源解决方案:Kopano Meet 提供端到端加密,在 Windows、macOS、Linux、Android 和 iOS 客户端都适用。
|
||||
|
||||
Outlook 客户端通过 ActiveSync(Z-Push 库)或 [Kopano OL Extension][9] (KOE) 来同步移动数据,KOE 是已经包含的 ActiveSync 的加强版。 Kopano 提供本机 Web 客户端 (WebApp)、移动设备客户端 (Mobility) 以及支持 Windows、Linux 和 macOS 的桌面版本 (DeskApp)。 它可以通过 IMAP、CalDAV 和 CardDAV 连接其他客户端。 所有直接连接到 Kopano 服务器的应用程序都使用 SOAP(简单对象访问协议)中的 MAPI。
|
||||
|
||||
Kopano Groupware 和 Kopano ONE(Kopano Groupware 的特别版)都提供免费的社区版本。 Kopano Meet 还可以作为应用程序或容器下载。
|
||||
|
||||
### Nextcloud
|
||||
|
||||
[Nextcloud][10] 在斯图加特和柏林(德国)都有办事处,已获得 AGPLv3 许可。 与 ownCloud 或 Dropbox 一样,用户可以通过桌面(Windows、Linux 和 macOS)、网络浏览器或本地应用程序(Android 和 iOS)访问软件套件。 从 18 版本开始,Nextcloud 除了拥有 Nextcloud Files(文件同步和共享)还包括了 Nextcloud Talk(通话、聊天和网络会议)和 Nextcloud Groupware(日历、联系人和邮件),并更名为 Nextcloud Hub。
|
||||
|
||||
用户和群组管理通过 OpenID 或 LDAP 进行。 Nextcloud 支持各种存储后端,例如 FTP、S3 和 Dropbox。 Nextcloud 可与多种数据库管理系统配合使用,包括 PostgreSQL、MariaDB、SQLite 和 Oracle 数据库。 管理员可以通过 [Nextcloud 应用程序商店][11] 中的 200 多个应用程序扩展功能,其中包括实时通信、音频和视频聊天、任务管理、邮件等等。
|
||||
|
||||
Nextcloud 是完全免费的。 最重要的是,该公司提供了 Nextcloud Enterprise 版本(针对企业部署进行了预配置、优化和强化)
|
||||
|
||||
### ownCloud
|
||||
|
||||
[ownCloud][12] 是由位于德国纽伦堡的 ownCloud GmbH 公司开发和维护的具有文件同步、共享和内容协作功能的软件。 它的客户端-服务器软件的核心和许多社区应用程序都是在 AGPLv3 下发布的。 一些扩展功能的企业应用程序获得 ownCloud 商业许可证 (OCL) 许可。
|
||||
|
||||
ownCloud主要是一款内容协作软件,包括在线办公文档编辑、日历、联系人同步等功能。移动客户端支持 Android 和 iOS,桌面应用可以和 Windows、macOS 和 Linux 的原生文件管理器结合使用。它允许访问 Web 界面,无需安装专用客户端软件。 ownCloud 支持 WebDAV、CalDAV 和 CardDAV 协定。 LDAP 协定也包含其中,但 ownCloud 同时连接到支持 OpenID Connect 身份验证标准的其他身份提供者。
|
||||
|
||||
ownCloud 可以整合 Microsoft Office Online Server、Office 365 和 Microsoft Teams,同时为Microsoft Outlook 和 eM Client 提供可用插件。 如有必要,外部存储功能可连接到不同的存储提供商,例如 Amazon S3、Dropbox、Microsoft SharePoint、Google Drive、Windows 网络驱动器 (SMB) 和 FTP。 该供应商还为企业客户提供额外的功能,如端到端加密、勒索软件和防病毒保护等(请参阅[完整功能列表][13])。
|
||||
|
||||
社区版免费且 100% 开源。
|
||||
|
||||
### OX 应用套件
|
||||
|
||||
[Open-Xchange][14] 成立于 2005 年,总部位于德国奥尔佩和纽伦堡。 今天,OX 在多个欧洲国家、美国和日本设有办事处。 [OX App Suite][15] 是一个模块化的电子邮件、通信和协作平台,主要为电信公司、托管公司和其他提供基于云的服务的提供商而设计。
|
||||
|
||||
OX 后端在 GPLv2 协议下发布,前端(UI)在 AGPLv3 下发布。 用户可以通过他们喜欢的浏览器(完全个性化的门户)或移动应用程序(Android 和 iOS)访问应用程序套件。 或者,本机客户端(移动设备和台式机)可用于 OX Mail 和 OX Drive。 得益于 CardDAV 和 CalDAV 扩展、Exchange Active Sync 和适用于 Android 的 OX Sync App,联系人、日历和任务得以同步。
|
||||
|
||||
OX 应用套件包含用于电子邮件、联系人、日历和任务的应用程序。 还有其他工具和扩展可用,其中一些是开源的,一些功能则要付费,包括 OX Documents(文本文档、电子表格、演示文稿)、OX Drive(管理、共享和同步文件)、OX Guard(电子邮件和文件加密)等等。 如需完整列表,请访问 OX 网站的[一般条款和条件][16]。
|
||||
|
||||
该应用免费提供有限功能的社区版。
|
||||
|
||||
### 开源电子邮件和群件
|
||||
|
||||
电子邮件和群件服务并不是必须花费(大量)金钱才可获得,更没有必要将就自己,(为了免费的服务而)依靠一个私人专有的、属于别人的服务器。 如果你不太热衷于管理职责,那么上述的这五个 Exchange 开源替代品都可以作为 SaaS 解决方案使用。 或者,所有供应商都提供专业技术支持,您可以在本地运行软件——一切尽在你的掌握中,但你却不会感觉自己孤军无援。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/21/11/open-source-alternatives-microsoft-exchange
|
||||
|
||||
作者:[Heike Jurzik][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[XiaotingHuang22](https://github.com/XiaotingHuang22)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/hej
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/team_dev_email_chat_video_work_wfm_desk_520.png?itok=6YtME4Hj (Working on a team, busy worklife)
|
||||
[2]: https://grommunio.com/
|
||||
[3]: https://opensource.com/article/20/5/open-source-video-conferencing
|
||||
[4]: https://opensource.com/article/20/7/mattermost
|
||||
[5]: https://opensource.com/article/21/7/owncloud-windows-files
|
||||
[6]: https://grommunio.com/features/architecture/
|
||||
[7]: https://kopano.com/
|
||||
[8]: https://kopano.com/products/interoperability/
|
||||
[9]: https://kb.kopano.io/display/WIKI/Setting+up+the+Kopano+OL+Extension
|
||||
[10]: https://nextcloud.com/
|
||||
[11]: https://apps.nextcloud.com/
|
||||
[12]: https://owncloud.com/
|
||||
[13]: https://owncloud.com/features/
|
||||
[14]: https://www.open-xchange.com/
|
||||
[15]: https://www.open-xchange.com/products/ox-app-suite/
|
||||
[16]: https://www.open-xchange.com/terms-and-conditions/
|
270
translated/tech/20220813 Level up your HTML document with CSS.md
Normal file
270
translated/tech/20220813 Level up your HTML document with CSS.md
Normal file
@ -0,0 +1,270 @@
|
||||
[#]: subject: "Level up your HTML document with CSS"
|
||||
[#]: via: "https://opensource.com/article/22/8/css-html-project-documentation"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "XiaotingHuang22"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
让 CSS 升级你的 HTML 文档
|
||||
======
|
||||
使用 CSS 让你的 HTML 项目更具风格。
|
||||
|
||||
当你编写文档时,无论是为开源项目还是技术写作项目,你都应该有两个目标:文档应该写得好,同时要易于阅读。 前者通过清晰的写作技巧和技术编辑来解决。第二个目标可以通过对 HTML 文档进行一些简单的更改来解决。
|
||||
|
||||
超文本标记语言或 HTML 是互联网的支柱。 自 1994 年“万维网”问世以来,所有网络浏览器都使用 HTML 来显示文档和网站。 几乎与此同时,HTML 一直支持 *stylesheet*,它是对 HTML 文档的一种特殊添加,用于定义文本在屏幕上的呈现方式。
|
||||
|
||||
单纯用 HTML 编写项目文档你也可以完成工作。 然而,纯 HTML 样式可能感觉有点简陋。 因此,尝试向 HTML 文档添加一些简单的样式,为文档添加一点活力,并使文档更清晰、更易于阅读。
|
||||
|
||||
### 定义一个 HTML 文档
|
||||
|
||||
让我们从一个纯 HTML 文档开始,探索如何向其添加样式。 一个空的 HTML 文档在顶部包含 <!DOCTYPE html> 定义,后面跟着一个 <html> 块来定义文档本身。 在 <html> 元素中,你还需要加上一个文档标头,其中包含有关文档的元数据,例如标题。 文档正文的内容放在父 <html> 块内的 <body> 块中。
|
||||
|
||||
你可以使用以下 HTML 代码定义一个空白页面:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>这是一个新文档</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
在另一篇关于[用 HTML 编写项目文档][2] 的文章中,我将一个开源棋盘游戏的自述文件从纯文本更新为 HTML 文档,并使用一些基本的 HTML 标记,如 <h1> 和 <h2> 作为标题和副标题,<p> 用于段落,<b> 和 <i> 用于粗体和斜体文本。 让我们从那篇文章结束的地方继续讲:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>简易 Senet</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>简易 Senet</h1>
|
||||
<h2>游戏玩法</h2>
|
||||
|
||||
<p>游戏会自动为你“投掷”投掷棒,并在屏幕右下角显示结果。</p>
|
||||
|
||||
<p>如果“投掷”结果为零,你失去本轮机会。</p>
|
||||
|
||||
<p>轮到你的时候,游戏会自动选择
|
||||
你在棋盘上的第一块棋子。 你不一定
|
||||
能够用这个棋子走棋,所以选择你的棋子
|
||||
移动,然后按 <i>Space</i>(或 <i>Enter</i>)移动
|
||||
它。 你可以通过几种不同的方法进行选择:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>向上</i>/<i>向下</i>/<i>向左</i>/<i>向右</i> to
|
||||
朝特定方块移动。</li>
|
||||
|
||||
<li>加号 (<b>+</b>) 或减号 (<b>-</b>) 使棋子在棋盘上向“左”或向“右”移动。
|
||||
请注意,它们会自动遵循棋盘的“倒过来的 S”方向移动。</li>
|
||||
|
||||
<li><em>Tab</em>在棋盘上选择下一个你想要移动的棋子。</li>
|
||||
</ul>
|
||||
|
||||
<p>要随时退出游戏,请按 <b>Q</b>(大写
|
||||
Q)或按 <i>Esc</i>,这样游戏会提示你是否想要
|
||||
放弃比赛。</p>
|
||||
|
||||
<p>如果你比对手更快将所有棋子移出棋盘,你就赢得了比赛。
|
||||
这同时需要运气和游戏策略!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
此 HTML 文档演示了利用 HTML 的技术写作者经常使用的一些块和内联元素。 块元素在围绕文本定义一个矩形。 段落和标题是块元素的示例,因为它们从文档的左边缘延伸到右边缘。 例如,<p> 在段落周围包含一个不可见的矩形。 相比之下,内联元素的使用则紧跟在它们包围的文本。 如果你在段落中的某些文本上使用 <b>,则只有被 <b> 和 </b> 包围的文本会变为粗体。
|
||||
|
||||
You can apply direct styling to this document to change the font, colors, and other text styles, but a more efficient way to modify the document's appearance is to apply a *stylesheet* to the document itself. You can do that in the <head> element, with other metadata. You can reference a file for the style sheet, but for this example, use a <style> block to define a style sheet within the document. Here's the <head> with an empty stylesheet:你可以将直接样式应用于此文档以更改字体、颜色和其他文本样式,但修改文档外观的更有效方法是将 *stylesheet* 应用于文档本身。 你可以在 <head> 元素中使用其他元数据执行此操作。 你可以为样式表引用文件,但在这个例子中,我使用 <style> 块在文档中定义样式表。 以下是带有空样式表的 <head> :
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>简易 Senet</title>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### 定义样式
|
||||
|
||||
由于你刚刚开始学习样式表,因此这里先演示一种基本样式:背景色。 我喜欢从背景颜色开始,因为它有助于演示块和内联元素。 让我们应用一个有点华丽的样式表,为所有 <p> 段落设置*浅蓝色*背景颜色,为 <ul> 无序列表设置*浅绿色*背景。 对任何粗体文本使用*黄色*背景,对任何斜体文本使用*粉红色*背景。
|
||||
|
||||
你可以在 HTML 文档的 <style> 块中使用样式来定义这些样式。 样式表使用与 HTML 文档不同的标记。 样式语法看起来像 `element { style; style; style; ... }` 并使用花括号将多种文本样式组合到一个定义中。
|
||||
|
||||
```
|
||||
<style>
|
||||
p { background-color: lightblue; }
|
||||
ul { background-color: lightgreen; }
|
||||
|
||||
b { background-color: yellow; }
|
||||
i { background-color: pink; }
|
||||
</style>
|
||||
```
|
||||
|
||||
请注意,每个样式都以分号结尾。
|
||||
|
||||
如果在网页浏览器中查看此 HTML 文档,你可以看到 <p> 和 <ul> 块元素如何填充为矩形,而 <b> 和 <i> 内联元素仅突出显示粗体和斜体文本。 这种对比色的使用可能看起来不太好看,但我想你可以清楚看到块和内联元素:
|
||||
|
||||
![辣眼睛!但是这些颜色确实能帮助我么更好地看出块和內联元素的区别。][3]
|
||||
|
||||
### 应用样式
|
||||
|
||||
你可以使用样式使这个自述文件更易于阅读。 因为你刚刚开始学习样式,还是先只用一些简单的样式元素:
|
||||
|
||||
* background-color 设置背景颜色
|
||||
* color 设置文字颜色
|
||||
* font-family 使用不同的文本字体
|
||||
* margin-top 在元素上方添加空间
|
||||
* margin-bottom 在元素下方添加空间
|
||||
* text-align 改变文本的显示方式,例如靠左、靠右或居中
|
||||
|
||||
让我们重新开始你的样式表并将这些新样式应用到文档中。 首先,在文档中使用更令人愉悦的字体。 如果你的 HTML 文档没有指定字体,网络浏览器会为你选择一种。 根据浏览器的设置方式,这可能是 *serif* 字体(如我的屏幕截图中使用的字体)或 *sans-serif* 字体。 Serif 字体在每个字母上添加了一个小笔画,这样在打印时更容易阅读。 Sans-serif 字体缺少这种额外的笔划,这使得文本在计算机显示器上显得更清晰。 常见的衬线字体包括 Garamond 或 Times New Roman。 流行的无衬线字体包括 Roboto 和 Arial。
|
||||
|
||||
例如,要将文档正文字体设置为 Roboto,你可以使用以下样式:
|
||||
|
||||
```
|
||||
body { font-family: Roboto; }
|
||||
```
|
||||
|
||||
通过设置字体,你假设查看文档的人也安装了该字体。 有些字体已经十分常见,以至于它们被认为是事实上的“网页安全”字体。 这些字体包括 Arial 等无衬线字体和 Times New Roman 等衬线字体。 Roboto 是一种较新的字体,可能还无法随处可用。 因此,网页设计师通常不会只列出一种字体,而是设置一种或多种“备用”字体。 你可以通过用逗号分隔来添加这些替代字体。 例如,如果用户的系统上没有 Roboto 字体,你可以使用以下样式定义将 Arial 字体用作文本正文:
|
||||
|
||||
```
|
||||
body { font-family: Roboto, Arial; }
|
||||
```
|
||||
|
||||
所有网络浏览器都定义了默认的衬线和无衬线字体,你可以使用这些名称来引用它们。 用户可以更改他们喜欢用于 serif 和 sans-serif 的字体,因此不太可能对每个人都一样,但在字体列表中使用 serif 或 sans-serif 通常是个好主意。 通过添加该字体,至少用户可以大致了解你希望 HTML 文档的呈现方式:
|
||||
|
||||
```
|
||||
body { font-family: Roboto, Arial, sans-serif; }
|
||||
```
|
||||
|
||||
如果字体名称不止一个单词,则你必须在其两边加上引号。 HTML 允许你在此处使用单引号或双引号。 为标题和副标题定义一些衬线字体,包括 Times New Roman:
|
||||
|
||||
```
|
||||
h1 { font-family: "Times New Roman", Garamond, serif; }
|
||||
h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
```
|
||||
|
||||
请注意,h1 标题和 h2 副标题使用完全相同的字体定义。 如果你想避免无谓的打字,可以使用样式表快捷方式为 h1 和 h2 使用相同的样式定义:
|
||||
|
||||
```
|
||||
h1, h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
```
|
||||
|
||||
在编写文档时,许多技术作者更喜欢将主标题放在页面的中央。 您可以在块元素(例如 h1 标题)上使用 text-align 来使标题居中:
|
||||
|
||||
```
|
||||
h1 { text-align: center; }
|
||||
```
|
||||
|
||||
为了让粗体和斜体文本更突出,请将它们置于稍微不同的颜色中。 对于某些文档,我可能会使用 *dark blue* 表示粗体文本,使用 *dark green* 表示斜体文本。 这些颜色非常接近黑色,但颜色的细微差别足以吸引读者的注意力。
|
||||
|
||||
```
|
||||
b { color: darkblue; }
|
||||
i { color: darkgreen; }
|
||||
```
|
||||
|
||||
最后,我更喜欢在我的列表元素周围添加额外的间距,以使它们更易于阅读。 如果每个列表项只有几个词,额外的空间可能无关紧要。 但是我的示例文本中的中间项很长,可以换到第二行。 额外的空间有助于读者更清楚地看到此列表中的每个项目。 你可以使用边距样式在块元素上方和下方添加空间:
|
||||
|
||||
```
|
||||
li { margin-top: 10px; margin-bottom: 10px; }
|
||||
```
|
||||
|
||||
这种样式定义了一个距离,此处我将其指定为每个列表元素上方和下方的 10px(十个*像素*)。 你可以使用多种不同的距离度量。 十像素实际上就是屏幕上十个像素的空间,无论是台式机显示器、笔记本电脑显示屏,还是手机或平板电脑屏幕。
|
||||
|
||||
假设你真的只是想在列表元素之间添加一个额外的空行,你也可以使用 em 来测量。 *em* 是一个旧的排版术语,如果你指的是左右间距,它就是大写 **M** 的宽度,或者对于垂直间距,就是大写 **M** 的高度。 所以你可以改用 1em 来写边距样式:
|
||||
|
||||
```
|
||||
li { margin-top: 1em; margin-bottom: 1em; }
|
||||
```
|
||||
|
||||
HTML 文档中的完整样式列表如下所示:
|
||||
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>简易 Senet</title>
|
||||
<style>
|
||||
body { font-family: Roboto, Arial, sans-serif; }
|
||||
h1, h2 { font-family: "Times New Roman", Garamond, serif; }
|
||||
h1 { text-align: center; }
|
||||
b { color: darkblue; }
|
||||
i { color: darkgreen; }
|
||||
li { margin-top: 1em; margin-bottom: 1em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>简易 Senet</h1>
|
||||
<h2>游戏玩法</h2>
|
||||
|
||||
<p>游戏会自动为你“投掷”投掷棒,并在屏幕右下角显示结果。</p>
|
||||
|
||||
<p>如果“投掷”结果为零,你失去本轮机会。</p>
|
||||
|
||||
<p>轮到你的时候,游戏会自动选择
|
||||
你在棋盘上的第一块棋子。 你不一定
|
||||
能够用这个棋子走棋。所以选择你的棋子
|
||||
移动,然后按 <i>Space</i>(或 <i>Enter</i>)移动
|
||||
它。 你可以通过几种不同的方法进行选择:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>向上</i>/<i>向下</i>/<i>向左</i>/<i>向右</i> to
|
||||
朝特定方块移动。</li>
|
||||
|
||||
<li>加号 (<b>+</b>) 或减号 (<b>-</b>) 使棋子在棋盘上向“左”或向“右”移动。
|
||||
请注意,它们会自动遵循棋盘的“倒过来的 S”方向移动。</li>
|
||||
|
||||
<li><em>Tab</em>在棋盘上选择下一个你想要移动的棋子。</li>
|
||||
</ul>
|
||||
|
||||
<p>要随时退出游戏,请按 <b>Q</b>(大写
|
||||
Q)或按 <i>Esc</i>,这样游戏会提示你是否想要
|
||||
放弃比赛。</p>
|
||||
|
||||
<p>如果你比对手更快将所有棋子移出棋盘,你就赢得了比赛。
|
||||
这同时需要运气和游戏策略!</p>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
在网页浏览器上查看时,你会看到采用无衬线字体的自述文件,标题和副标题使用衬线字体。 页面标题居中。 粗体和斜体文本使用略有不同的颜色来吸引读者的注意力而不会分散注意力。 最后,列表项周围有额外的空间,使每个项目更易于阅读。
|
||||
|
||||
![通过添加一些样式,我们使这个自述文件更易于阅读。][4]
|
||||
|
||||
这是在技术写作中使用样式的简单介绍。 掌握了基础知识后,你可能会对 [Mozilla 的 HTML 指南][5] 感兴趣。 它包括一些很棒的初学者教程,因此你可以学习如何创建自己的网页。
|
||||
|
||||
有关 CSS 样式的更多信息,我推荐 [Mozilla 的 CSS 指南][6]。
|
||||
|
||||
图片来自: (Jim Hall, CC BY-SA 4.0)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/22/8/css-html-project-documentation
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[XiaotingHuang22](https://github.com/XiaotingHuang22)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed
|
||||
[1]: https://opensource.com/sites/default/files/lead-images/painting_computer_screen_art_design_creative.png
|
||||
[2]: https://opensource.com/article/22/8/writing-project-documentation-html
|
||||
[3]: https://opensource.com/sites/default/files/2022-08/style-html-1.png
|
||||
[4]: https://opensource.com/sites/default/files/2022-08/style-html-2.png
|
||||
[5]: https://developer.mozilla.org/en-US/docs/Web/HTML
|
||||
[6]: https://developer.mozilla.org/en-US/docs/Web/CSS
|
@ -0,0 +1,72 @@
|
||||
[#]: subject: "Measure pi with a Raspberry Pi"
|
||||
[#]: via: "https://opensource.com/article/23/3/measure-pi-raspberry-pi"
|
||||
[#]: author: "Jim Hall https://opensource.com/users/jim-hall"
|
||||
[#]: collector: "lkxed"
|
||||
[#]: translator: "geekpi"
|
||||
[#]: reviewer: " "
|
||||
[#]: publisher: " "
|
||||
[#]: url: " "
|
||||
|
||||
使用树莓派测量圆周率
|
||||
======
|
||||
|
||||
世界各地将 3 月 14 日定为圆周率日。许多人通过在房子周围找到的物体测量圆周率来庆祝圆周率日。我想用我的树莓派 3B 为今年的 Pi Day 做一些类似的事情。继续阅读以了解我如何使用我的树莓派测量圆周率。
|
||||
|
||||
你需要什么:
|
||||
|
||||
- 树莓派单板机
|
||||
- 方格纸
|
||||
- 带毫米和厘米测量值的标尺
|
||||
- 笔
|
||||
|
||||
### 1. 画一个圆
|
||||
|
||||
圆周率是圆的周长与其直径的比值。要计算圆周率,我们需要测量一个完美绘制的圆的周长和直径。幸运的是,树莓派主板上的安装孔足够大,可以使用铅笔或钢笔。我通过一个树莓派板安装孔插入了一根图钉,小心地将针放在一张方格纸上两条线的交点上。
|
||||
|
||||
握住别针,我将一支笔插入对面的安装孔中,并通过将笔绕着别针移动来画一个圆圈。树莓派主板底面的焊点会卡在纸上,但小心点还是可以画好圆圈的。
|
||||
|
||||
![Use the Raspberry Pi as a compass to draw a circle.][1]
|
||||
|
||||
### 2. 把圆分成段
|
||||
|
||||
通过画一条穿过圆心的垂直线将圆分成两半,通过画一条穿过圆心的水平线将圆再次分成四分之一。当我画圆的时候,我把图钉正好放在图画纸上两条线的交点上,这样就很容易找到垂直和水平的中心线。你可以通过在对角线上画一条线来创造一个 "八分 "片。
|
||||
|
||||
![Each small wedge is 1/8 of a circle.][2]
|
||||
|
||||
进一步的划分是与尺子的练习。我用尺子找到“四分之一楔形”和“八分之一楔形”任意两个交点的中点,做成一个 1/16 的楔形。你可以使用相同的方法制作越来越小的 1/32 和 1/64 圆的切片。通过非常小心,我还能够在圆的 1/128 处测量出一个非常窄的楔形:
|
||||
|
||||
![If you are careful, you can keep dividing to find 1/128 of a circle.][3]
|
||||
|
||||
### 3. 估算周长
|
||||
|
||||
我最小的楔形是一个圆的 1/128。如此小的切片,楔形的外弧非常小,我们可以用一条直线来近似它。这实际上不是圆周长的 1/128,但它足够接近,我们可以将其用作一个很好的估计。
|
||||
|
||||
![Use the mm measurement on your ruler to measure the outer arc of the 1/128 segment.][4]
|
||||
|
||||
使用我的尺子上的毫米测量值,我测量了我的 1/128 楔形的外弧为 3.8 毫米。这样,我可以估计圆的周长为 3.8 毫米乘以 128,即 486.4 毫米。要转换为厘米,除以十:**48.64cm**。
|
||||
|
||||
### 4. 计算圆周率
|
||||
|
||||
圆周率的值是圆的周长与其直径的比值。我们在步骤 3 中估算了周长。测量直径是使用尺子测量圆周的简单练习。我的圆是 **15.4cm**。
|
||||
|
||||
现在我们知道了周长和直径,我们可以将圆周率计算为 48.64 除以 15.4,即 **3.158**。这与 pi 的实际值 3.141 相差不远。
|
||||
|
||||
测量圆周率是一项有趣的数学练习!各个年龄段的数学爱好者都可以使用方格纸、笔和尺子等简单工具自行测量圆周率。以一种有趣的新方式使用你的树莓派来绘制圆并独立测量圆周率。这是一个估计值,因为我们将圆上的 1/128 弧近似为一条直线,但这使我们无需太多努力就足够接近了。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/23/3/measure-pi-raspberry-pi
|
||||
|
||||
作者:[Jim Hall][a]
|
||||
选题:[lkxed][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jim-hall
|
||||
[b]: https://github.com/lkxed/
|
||||
[1]: https://opensource.com/sites/default/files/2023-03/10000000000003E8000003E8BE7DE71919BB0C82.jpg
|
||||
[2]: https://opensource.com/sites/default/files/2023-03/100000010000028A0000028A0625B218857F031C.webp
|
||||
[3]: https://opensource.com/sites/default/files/2023-03/100000000000079E00000514506C8EE5131D886A.webp
|
||||
[4]: https://opensource.com/sites/default/files/2023-03/10000000000003E8000003E881402FB71F1945FF.jpg
|
Loading…
Reference in New Issue
Block a user